"""Arcade Starter Tools for Posthog

DO NOT EDIT THIS MODULE DIRECTLY.

THIS MODULE WAS AUTO-GENERATED BY TRANSPILING THE API STARTER TOOL JSON DEFINITIONS
IN THE ../wrapper_tools DIRECTORY INTO PYTHON CODE. ANY CHANGES TO THIS MODULE WILL
BE OVERWRITTEN BY THE TRANSPILER.
"""
import asyncio
import json
import jsonschema
from enum import Enum
from typing import Annotated, Any

import httpx

from arcade_tdk import tool, ToolContext
from arcade_tdk.errors import RetryableToolError

from .request_body_schemas import REQUEST_BODY_SCHEMAS

# Retry configuration
INITIAL_RETRY_DELAY = 0.5  # seconds

HTTP_CLIENT = httpx.AsyncClient(
    timeout=httpx.Timeout(60.0, connect=10.0),
    limits=httpx.Limits(max_keepalive_connections=20, max_connections=100),
    transport=httpx.AsyncHTTPTransport(retries=3),
    http2=True,
    follow_redirects=True,
)

class ToolMode(str, Enum):
    """Mode for tools with complex request bodies."""
    GET_REQUEST_SCHEMA = "get_request_schema"
    EXECUTE = "execute"



def remove_none_values(data: dict[str, Any]) -> dict[str, Any]:
    return {k: v for k, v in data.items() if v is not None}


async def make_request(
    url: str,
    method: str,
    params: dict[str, Any] | None = None,
    headers: dict[str, Any] | None = None,
    content: str | None = None,
    data: dict[str, Any] | None = None,
    auth: tuple[str, str] | None = None,
    max_retries: int = 3,
) -> httpx.Response:
    """Make an HTTP request with retry logic for 5xx server errors."""
    for attempt in range(max_retries):
        try:
            response = await HTTP_CLIENT.request(
                url=url,
                auth=auth,
                method=method,
                params=params,
                headers=headers,
                content=content,
            )
            response.raise_for_status()
        except httpx.HTTPStatusError as e:
            # Only retry on 5xx server errors
            if e.response.status_code >= 500 and attempt < max_retries - 1:
                # Exponential backoff: 0.5s, 1s, 2s
                await asyncio.sleep(INITIAL_RETRY_DELAY * (2 ** attempt))
                continue
            # Re-raise for 4xx errors or if max retries reached
            raise
        except httpx.RequestError as e:
            # Don't retry request errors (network issues are handled by transport)
            raise
        else:
            return response

    # This should never be reached, but satisfies type checker
    raise httpx.RequestError("Max retries exceeded")  # noqa: TRY003


async def make_request_with_schema_validation(
    url: str,
    method: str,
    request_data: dict[str, Any],
    schema: dict[str, Any] | str,
    auth: tuple[str, str] | None = None,
    params: dict[str, Any] | None = None,
    headers: dict[str, Any] | None = None,
    max_retries: int = 3,
) -> httpx.Response:
    """Make an HTTP request with schema validation on format errors."""
    # Parse schema if it's a string, skip validation if parsing fails
    parsed_schema = None
    if isinstance(schema, str):
        try:
            parsed_schema = json.loads(schema)
        except Exception:
            # If schema parsing fails, just skip validation
            parsed_schema = None
    else:
        parsed_schema = schema

    try:
        response = await make_request(
            url=url,
            auth=auth,
            method=method,
            params=params,
            headers=headers,
            content=json.dumps(request_data),
            max_retries=max_retries,
        )
    except httpx.HTTPStatusError as e:
        # Only provide schema validation for format-related errors
        if e.response.status_code in (400, 422):
            api_error_details = (
                f"API returned {e.response.status_code}: {e.response.text}"
            )

            # Only run validation if we have a valid parsed schema
            if parsed_schema is not None:
                # Run validation to provide additional context
                is_valid, validation_error = validate_json_against_schema(
                    request_data, parsed_schema
                )

                if not is_valid:
                    # Schema validation found issues - additional context
                    additional_context = (
                        f"{api_error_details}\n\n"
                        f"Schema validation found the following issues:\n"
                        f"{validation_error}"
                    )
                else:
                    # Schema validation passed - just show API error
                    additional_context = api_error_details
            else:
                # No valid schema - just show API error
                additional_context = api_error_details

            raise RetryableToolError(
                message=(
                    f"API request failed with validation error: "
                    f"{e.response.status_code}"
                ),
                developer_message=api_error_details,
                additional_prompt_content=additional_context,
            ) from e
        else:
            # For non-validation errors, re-raise as-is
            raise
    else:
        return response


def validate_json_against_schema(
    json_data: dict[str, Any], schema: dict[str, Any]
) -> tuple[bool, str | None]:
    """Validate JSON data against an OpenAPI/JSON Schema.

    This provides full JSON Schema Draft 7 validation including:
    - Required fields, types, enums
    - Pattern validation (regex)
    - Format validation (email, uuid, date-time, etc.)
    - Min/max length and values
    - oneOf, anyOf, allOf
    - And all other JSON Schema features

    Args:
        json_data: The JSON data to validate
        schema: The JSON Schema to validate against

    Returns:
        Tuple of (is_valid, error_messages). If valid, error_messages is None.
        If invalid, error_messages contains all validation errors.
    """
    try:
        validator = jsonschema.Draft7Validator(
            schema, format_checker=jsonschema.Draft7Validator.FORMAT_CHECKER
        )
        # Collect ALL validation errors
        errors = list(validator.iter_errors(json_data))
        if errors:
            # Format all errors with their paths
            error_messages = []
            for error in errors:
                error_path = (
                    ".".join(str(p) for p in error.path)
                    if error.path
                    else "root"
                )
                error_messages.append(f"{error.message} at {error_path}")
            # Join all errors with newlines
            return False, "\n".join(error_messages)
        else:
            return True, None
    except jsonschema.SchemaError as e:
        return False, f"Invalid schema: {e.message}"
    except Exception as e:
        return False, f"Validation error: {e!s}"

@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_app_metrics(
    context: ToolContext,
    plugin_config_id: Annotated[int, "A unique integer value identifying the plugin configuration."],  # noqa: E501
    project_id: Annotated[str, "A string representing the ID of the project to access metrics for. Obtain this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_app_metrics_retrieve'."]:  # noqa: E501
    """Retrieve application metrics for a specific project environment.

    This tool retrieves application metrics for a specified project environment from Datadog. Use it to gain insights into application performance and operations for a given project ID and metric ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/app_metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=plugin_config_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_app_metrics_error_details(
    context: ToolContext,
    plugin_config_id: Annotated[int, "A unique integer identifying the plugin configuration."],
    project_id: Annotated[str, "String representing the Project ID to access. Obtain this ID via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_app_metrics_error_details_retrieve'."]:  # noqa: E501
    """Retrieve detailed error metrics for a specific app.

    Use this tool to get detailed error metrics for a specific app within a project. It retrieves error details associated with application metrics."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/app_metrics/{id}/error_details/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=plugin_config_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_app_metrics_exports(
    context: ToolContext,
    plugin_configuration_id: Annotated[str, "The ID of the plugin configuration to retrieve metrics for. Ensure it matches the correct configuration in your Datadog setup."],  # noqa: E501
    project_id_of_the_posthog_project: Annotated[str, "The ID of the Datadog project to access. Obtain it via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_app_metrics_historical_exports_retrieve'."]:  # noqa: E501
    """Retrieve historical app metrics exports for a project.

    This tool retrieves historical app metrics exports for a specific project and plugin configuration in Datadog. Call it when you need to access past metrics data for analysis or reporting."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/app_metrics/{plugin_config_id}/historical_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), plugin_config_id=plugin_configuration_id, project_id=project_id_of_the_posthog_project),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_historical_app_metrics(
    context: ToolContext,
    export_id: Annotated[str, "The identifier of the historical export you want to retrieve. This should be a valid string corresponding to a specific export."],  # noqa: E501
    plugin_configuration_id: Annotated[str, "The ID of the plugin configuration to retrieve historical metrics for. This identifies which plugin's data you want to access."],  # noqa: E501
    project_id: Annotated[str, "The Project ID to access for retrieving historical app metrics. Obtain it via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_app_metrics_historical_exports_retrieve_2'."]:  # noqa: E501
    """Retrieve historical app metrics for a specific environment.

    This tool retrieves historical metrics data for a specific application's environment. It should be called when detailed analytics or historical performance data is needed for analysis or reporting."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/app_metrics/{plugin_config_id}/historical_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=export_id, plugin_config_id=plugin_configuration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_env_batch_exports(
    context: ToolContext,
    project_identifier: Annotated[str, "The Project ID to access for fetching batch exports. Obtain it by calling /api/projects/."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The initial index from which to return the results. Use this to navigate pages."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_list'."]:
    """Retrieve the list of batch exports for a specific environment.

    Use this tool to obtain a list of batch exports associated with a specific project environment. It is useful for monitoring and managing environment-related data exports."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_result_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_batch_export_for_environments(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project you want to access for batch export. Obtain it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_create'."]:  # noqa: E501
    """Initiate a batch export for selected environments.

    This tool creates a batch export for environments within a specified project in Datadog. Use it to organize and retrieve environment data efficiently.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTFORENVIRONMENTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTFORENVIRONMENTS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTFORENVIRONMENTS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTFORENVIRONMENTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_batch_export_backfills(
    context: ToolContext,
    batch_export_identifier: Annotated[str, "The unique identifier for the batch export to retrieve specific backfill details."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access batch export backfills. Obtainable via /api/projects/."],  # noqa: E501
    pagination_cursor: Annotated[str | None, "The pagination cursor for retrieving the next set of results in a paginated response."] = None,  # noqa: E501
    results_ordering_field: Annotated[str | None, "Specify the field by which to order the batch export backfills results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_backfills_list'."]:  # noqa: E501
    """Retrieve a list of batch export backfills.

    Fetch the details of batch export backfills associated with a specified project and batch export. Useful for monitoring or auditing backfill activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/backfills/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"cursor": pagination_cursor, "ordering": results_ordering_field}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_backfill_for_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_identifier: Annotated[str | None, "The unique identifier of the BatchExport for which to create a backfill.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Call /api/projects/ to retrieve this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_backfills_create'."]:  # noqa: E501
    """Create a new backfill for a BatchExport.

    This tool is used to create a new backfill for a BatchExport by specifying the project and batch export IDs. It should be called when there's a need to initiate a backfill operation for specific data exports.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEBACKFILLFORBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_identifier:
        missing_params.append(("batch_export_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEBACKFILLFORBATCHEXPORT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEBACKFILLFORBATCHEXPORT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/backfills/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEBACKFILLFORBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_export_backfill(
    context: ToolContext,
    batch_export_backfill_uuid: Annotated[str, "The UUID identifying the specific batch export backfill to retrieve."],  # noqa: E501
    batch_export_identifier: Annotated[str, "The identifier for the specific batch export. Provide as a string to retrieve backfill details."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access. Use /api/projects/ to retrieve the ID if unknown."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_backfills_retrieve'."]:  # noqa: E501
    """Retrieve details of a batch export backfill.

    Use this tool to get information about a specific batch export backfill in a given environment using project ID, export ID, and backfill ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/backfills/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_backfill_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_batch_export_backfill(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_identifier: Annotated[str | None, "A unique identifier string for the batch export backfill to be canceled.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    batch_export_backfill_id: Annotated[str | None, "A UUID string identifying the specific batch export backfill to cancel.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Call /api/projects/ to find the project ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_backfills_cancel_create'."]:  # noqa: E501
    """Cancel a batch export backfill process.

    Use this tool to cancel an ongoing batch export backfill for a specific project and batch. It should be called when a backfill process needs to be halted.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTBACKFILL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_identifier:
        missing_params.append(("batch_export_identifier", "path"))
    if not batch_export_backfill_id:
        missing_params.append(("batch_export_backfill_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTBACKFILL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTBACKFILL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/backfills/{id}/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_backfill_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTBACKFILL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_exports(
    context: ToolContext,
    batch_export_identifier: Annotated[str, "The ID of the batch export you wish to access. Required to retrieve batch export runs for a specific project."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier of the project you want to access in Datadog. Use /api/projects/ to find the ID."],  # noqa: E501
    order_by_field: Annotated[str | None, "Specify the field used to order the batch export run results. This determines the sorting criteria for the list of export runs."] = None,  # noqa: E501
    pagination_cursor: Annotated[str | None, "The value used for paginating results in a list of export runs. It allows fetching subsequent pages of results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_runs_list'."]:  # noqa: E501
    """Fetches a list of batch export runs for a given environment.

    Use this tool to retrieve detailed information about batch export runs for a specific environment within a Datadog project. It requires specifying the project and batch export identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/runs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"cursor": pagination_cursor, "ordering": order_by_field}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_export_run(
    context: ToolContext,
    batch_export_id: Annotated[str, "A unique identifier for the batch export run. Provide the UUID identifying this export."],  # noqa: E501
    batch_export_run_id: Annotated[str, "A UUID string identifying this specific batch export run for retrieval."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project you wish to access. Retrieve this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_runs_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific environment export run.

    Call this tool to get information about a specific batch export run for an environment in a project on Datadog. Useful for tracking and checking the status of export operations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/runs/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_id, id=batch_export_run_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_batch_export_run(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_run_id: Annotated[str | None, "A UUID string identifying the specific batch export run to be canceled.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    batch_export_run_uuid: Annotated[str | None, "A UUID string that identifies the batch export run to be canceled.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_runs_cancel_create'."]:  # noqa: E501
    """Cancel an ongoing batch export run.

    Use this tool to cancel an ongoing batch export run in DataDog. It should be called when you need to stop a specific export process immediately.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTRUN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_run_id:
        missing_params.append(("batch_export_run_id", "path"))
    if not batch_export_run_uuid:
        missing_params.append(("batch_export_run_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTRUN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTRUN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/runs/{id}/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_run_id, id=batch_export_run_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CANCELBATCHEXPORTRUN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_batch_export_logs(
    context: ToolContext,
    batch_export_identifier: Annotated[str, "A string representing the unique identifier for the batch export."],  # noqa: E501
    batch_export_run_id: Annotated[str, "A UUID string identifying the specific batch export run."],
    project_identifier: Annotated[str, "The unique Project ID needed to access the specific project. Retrieve this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_runs_logs_retrieve'."]:  # noqa: E501
    """Retrieve logs from a specific environment batch export run.

    Use this tool to get logs from a specified batch export run within an environment. It requires details about the project, batch export, and run ID to locate the logs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/runs/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_run_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retry_batch_export_run(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_identifier: Annotated[str | None, "A string representing the UUID of the batch export run to retry.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    batch_export_run_id: Annotated[str | None, "The UUID identifying the batch export run to retry.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID for accessing the specific project. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_runs_retry_create'."]:  # noqa: E501
    """Initiate a retry of a batch export run.

    Use this tool to retry a specific batch export run within a project environment. This is equivalent to backfilling one run.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RETRYBATCHEXPORTRUN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_identifier:
        missing_params.append(("batch_export_identifier", "path"))
    if not batch_export_run_id:
        missing_params.append(("batch_export_run_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RETRYBATCHEXPORTRUN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RETRYBATCHEXPORTRUN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{batch_export_id}/runs/{id}/retry/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_run_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RETRYBATCHEXPORTRUN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_batch_export(
    context: ToolContext,
    batch_export_uuid: Annotated[str, "A UUID string identifying the specific batch export to retrieve details for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve via /api/projects/."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific environment batch export.

    Call this tool to fetch and retrieve details about a specific environment batch export using the project and export identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_batch_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_uuid: Annotated[str | None, "The UUID identifying the specific batch export to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID to access; retrieve from /api/projects/ if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_update'."]:  # noqa: E501
    """Update environment batch exports details.

    Use this tool to update the details of environment batch exports for a specific project. It is helpful when modifications are needed in the batch export configurations of environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTBATCHEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_uuid:
        missing_params.append(("batch_export_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTBATCHEXPORTS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTBATCHEXPORTS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTBATCHEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string that uniquely identifies the environment export batch to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it with a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_partial_update'."]:  # noqa: E501
    """Update environment export batch details.

    Use this tool to update specific details of an environment export batch in Datadog. This is useful for modifying existing export configurations or details without creating a new batch.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_batch_export(
    context: ToolContext,
    batch_export_uuid: Annotated[str, "A UUID string identifying the batch export to delete."],
    project_id: Annotated[str, "The ID of the project to access for batch export deletion. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_destroy'."]:  # noqa: E501
    """Delete a batch export in a specific environment.

    Use this tool to delete a specific batch export for a given environment within a project on Datadog. This is useful when you need to manage or clean up batch exports."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def trigger_batch_export_backfill(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_uuid: Annotated[str | None, "A UUID string identifying this batch export.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The Project ID for accessing the desired project. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_backfill_create'."]:  # noqa: E501
    """Trigger a backfill for a BatchExport.

    Use this tool to trigger a backfill for a BatchExport. Note that this endpoint is deprecated; consider using the updated endpoint POST /batch_exports/<id>/backfills/ instead.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["TRIGGERBATCHEXPORTBACKFILL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_uuid:
        missing_params.append(("batch_export_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["TRIGGERBATCHEXPORTBACKFILL"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["TRIGGERBATCHEXPORTBACKFILL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/backfill/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["TRIGGERBATCHEXPORTBACKFILL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_logs(
    context: ToolContext,
    batch_export_id: Annotated[str, "A UUID string that specifies the batch export to retrieve logs for. This is a unique identifier for the log batch export."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access for retrieving environment batch export logs. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_logs_retrieve'."]:  # noqa: E501
    """Retrieve logs from environment batch exports.

    Fetch logs for a specific batch export within a given environment. This tool should be used when you need to access logs related to batch exports for diagnostic or reporting purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def pause_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the batch export to be paused.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique identifier for the project. Use /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_pause_create'."]:  # noqa: E501
    """Pause a batch export operation.

    Use this tool to pause an ongoing batch export associated with a specific project and export ID. Suitable for temporarily halting data exports without cancelling them entirely.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["PAUSEBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["PAUSEBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["PAUSEBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/pause/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["PAUSEBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def run_environment_test_step(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_uuid: Annotated[str | None, "A UUID string to identify the specific batch export for the test step execution.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique Project ID for the targeted environment. Obtainable via `/api/projects/`.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_run_test_step_create'."]:  # noqa: E501
    """Initiate a test step execution for environment batch exports.

    This tool initiates the execution of a test step for a specified batch export in a given environment project using Datadog's API. It should be called when you need to run a specific test step within the context of environment batch exports.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RUNENVIRONMENTTESTSTEP"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_uuid:
        missing_params.append(("batch_export_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RUNENVIRONMENTTESTSTEP"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RUNENVIRONMENTTESTSTEP"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/run_test_step/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RUNENVIRONMENTTESTSTEP"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def unpause_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the batch export to unpause.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve using a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_unpause_create'."]:  # noqa: E501
    """Unpause a paused BatchExport to resume data export.

    Use this tool to unpause a paused BatchExport, allowing data export to continue. Ideal for resuming exports that were previously halted.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UNPAUSEBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UNPAUSEBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UNPAUSEBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/{id}/unpause/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UNPAUSEBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access for initiating the batch export. To find this, call /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_run_test_step_new_create'."]:  # noqa: E501
    """Initiate a batch export for environment tests.

    Use this tool to start a new batch export for testing environments in a specified project. It triggers the export process and should be called when a batch export is needed for environment test steps.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTBATCHEXPORT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTBATCHEXPORT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/run_test_step_new/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environments_batch_export_status(
    context: ToolContext,
    project_id_for_export_status: Annotated[str, "The Project ID to retrieve the test batch export status. Obtainable from a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_batch_exports_test_retrieve'."]:  # noqa: E501
    """Gets the status of a test batch export for environments.

    Call this tool to retrieve the status of a test batch export for a specific environment using the project ID. Useful for checking the progress or completion of export tasks."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/batch_exports/test/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_export_status),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_dashboards(
    context: ToolContext,
    project_id: Annotated[str, "Project ID required to access a specific environment in Datadog. Use the /api/projects/ endpoint to find the ID."],  # noqa: E501
    initial_index_for_results: Annotated[int | None, "The index from which to start returning results, useful for pagination."] = None,  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response. Accepted values are 'json' or 'txt'."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "The number of dashboard results to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_list'."]:
    """Retrieve dashboards for a specific environment.

    Use this tool to get a list of dashboards associated with a specific environment in a Datadog project. It's useful for monitoring and managing different environments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format, "limit": results_per_page, "offset": initial_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project for accessing its environment. Retrieve via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Options: 'json', 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_create'."]:
    """Create a new dashboard within a specific environment.

    Use this tool to create a dashboard within a specific project environment in Datadog. Ideal for setting up new dashboards quickly in designated environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARD"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_collaborators_on_dashboard(
    context: ToolContext,
    dashboard_identifier: Annotated[int, "The unique identifier for the dashboard. Must be an integer and is required to retrieve collaborators."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project. Obtainable by calling the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_collaborators_list'."]:  # noqa: E501
    """Retrieve collaborators for a dashboard in a project.

    Use this tool to get a list of collaborators associated with a specific dashboard within a given project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/collaborators/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_dashboard_collaborator(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "The unique identifier of the dashboard to which the collaborator is being added. It must be an integer value.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve using the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_collaborators_create'."]:  # noqa: E501
    """Add a collaborator to a specific dashboard.

    Use this tool to add a collaborator to a specified dashboard within a project environment on Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ADDDASHBOARDCOLLABORATOR"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ADDDASHBOARDCOLLABORATOR"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ADDDASHBOARDCOLLABORATOR"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/collaborators/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ADDDASHBOARDCOLLABORATOR"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_dashboard_collaborator(
    context: ToolContext,
    collaborator_user_uuid: Annotated[str, "The unique user ID of the collaborator to be removed from the dashboard."],  # noqa: E501
    dashboard_id: Annotated[int, "The unique identifier of the dashboard from which you want to remove a collaborator. This should be an integer."],  # noqa: E501
    project_id: Annotated[str, "ID of the project to access. Retrieve the ID using the /api/projects/ endpoint if needed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_collaborators_destroy'."]:  # noqa: E501
    """Remove a collaborator from a dashboard in a specific environment.

    This tool removes a specified collaborator from a dashboard in a given environment using their unique user ID. Use this when you need to manage dashboard access by removing collaborators."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/collaborators/{user__uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_id, project_id=project_id, user__uuid=collaborator_user_uuid),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_shared_dashboards(
    context: ToolContext,
    dashboard_identifier: Annotated[int, "The unique integer ID of the dashboard whose sharing information you want to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access for retrieving shared dashboard details. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_sharing_list'."]:  # noqa: E501
    """Retrieve shared dashboard information for a specified project.

    Call this tool to get details about how dashboards are shared within a specific project environment. Useful for understanding dashboard access and distribution."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/sharing/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dashboard_sharing_password(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_identifier: Annotated[int | None, "The unique integer identifier for the dashboard. This ID is required to create a sharing password.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project for which you want to create a dashboard sharing password. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_sharing_passwords_create'."]:  # noqa: E501
    """Create a password for sharing a dashboard.

    Use this tool to create a new password for configuring how a dashboard is shared in a specific environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDASHBOARDSHARINGPASSWORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_identifier:
        missing_params.append(("dashboard_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDASHBOARDSHARINGPASSWORD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDASHBOARDSHARINGPASSWORD"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/sharing/passwords/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDASHBOARDSHARINGPASSWORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_dashboard_sharing_password(
    context: ToolContext,
    dashboard_identifier: Annotated[int, "The unique integer identifier for the dashboard from which the password is to be deleted."],  # noqa: E501
    password_identifier: Annotated[str, "The unique identifier of the password to be deleted from the dashboard's sharing configuration. This is required to specify which password to remove."],  # noqa: E501
    project_identifier: Annotated[str, "Unique identifier for the project. Retrieve by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_sharing_passwords_destroy'."]:  # noqa: E501
    """Delete a password from a dashboard's sharing configuration.

    Use this tool to remove a password from the sharing settings of a specific dashboard in a project environment. This operation is crucial when you want to update the security configurations or remove outdated credentials."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/sharing/passwords/{password_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, password_id=password_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def refresh_dashboard_sharing(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "The unique integer ID of the Datadog dashboard to refresh the sharing link for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Specify the Project ID for accessing the desired project in Datadog. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_sharing_refresh_create'."]:  # noqa: E501
    """Refresh a dashboard's sharing link in Datadog environments.

    Use this tool to refresh the sharing link for a specific dashboard within a Datadog environment. This is useful for updating the link to maintain access or to apply new sharing settings.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{dashboard_id}/sharing/refresh/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environment_dashboard(
    context: ToolContext,
    dashboard_id: Annotated[int, "A unique integer value identifying the dashboard to retrieve."],
    project_id: Annotated[str, "Project ID for accessing the specific environment dashboard. Obtainable via call to /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response data. Use 'json' for JSON format or 'txt' for plain text format."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_retrieve'."]:  # noqa: E501
    """Retrieve a specific dashboard for an environment.

    This tool retrieves dashboard information for a specified environment using the project and dashboard IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "A unique integer value to identify the environment dashboard to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve this using the /api/projects/ endpoint if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the desired format of the response. Options are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_update'."]:
    """Update settings of an environment dashboard.

    This tool updates the settings of a specified environment dashboard within a project, using provided dashboard identifiers.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDASHBOARD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDASHBOARD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDASHBOARD"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dashboard_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "Unique integer identifying the dashboard to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Call /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the response. Options include 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_partial_update'."]:  # noqa: E501
    """Update specific dashboard settings in an environment.

    Use this tool to partially update the settings of a specific dashboard within a given environment, identified by project and dashboard IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDENVIRONMENT"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_dashboard(
    context: ToolContext,
    dashboard_id: Annotated[int, "A unique integer value identifying the dashboard to be marked as deleted."],  # noqa: E501
    project_id: Annotated[str, "Project ID to access the desired project. Retrieve using /api/projects/ if needed."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response. Options include 'json' and 'txt'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_destroy'."]:
    """Mark a dashboard as deleted.

    Use this tool to set a specific dashboard as deleted for a project environment. This action is performed by patching the dashboard's status to \"deleted\" instead of a hard delete."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def move_dashboard_tile(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "A unique integer value identifying this dashboard within Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The identifier for the project you want to access. Retrieve it by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the desired format of the response data. Options are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_move_tile_partial_update'."]:  # noqa: E501
    """Move a tile's position in a specific dashboard.

    Use this tool to update the position of a tile within a specified dashboard environment in Datadog. This is useful when reorganizing dashboard layouts or customizing views.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MOVEDASHBOARDTILE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MOVEDASHBOARDTILE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MOVEDASHBOARDTILE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{id}/move_tile/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MOVEDASHBOARDTILE"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def stream_dashboard_tiles(
    context: ToolContext,
    dashboard_id: Annotated[int, "A unique integer value identifying the dashboard to stream."],
    project_id: Annotated[str, "The ID of the project you wish to access. Obtain this by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format for the streamed dashboard response. Choose 'json' for JSON format or 'txt' for plain text."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_stream_tiles_retrieve'."]:  # noqa: E501
    """Stream dashboard metadata and tiles via Server-Sent Events.

    Use this tool to retrieve streaming metadata and tiles from a specific dashboard using Server-Sent Events. It can be helpful for real-time updates and renders of dashboards in a specified environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/{id}/stream_tiles/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_dashboard_from_template(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The Project ID for the target environment in Datadog. Retrieve this ID via the /api/projects/ API call.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the response. Choose between 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dashboards_create_from_template_json_create'."]:  # noqa: E501
    """Create an environment dashboard from a template.

    Use this tool to create a new environment dashboard in Datadog by applying a template JSON. This is useful for quickly setting up dashboards in specified projects.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARDFROMTEMPLATE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARDFROMTEMPLATE"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARDFROMTEMPLATE"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dashboards/create_from_template_json/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDASHBOARDFROMTEMPLATE"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_data_color_themes(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID to access specific environment data color themes. Obtain by calling /api/projects/."],  # noqa: E501
    initial_index: Annotated[int | None, "The initial index from which to return the results. Used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "The maximum number of results to return on each page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_data_color_themes_list'."]:  # noqa: E501
    """Retrieve data color themes for a specific environment.

    Call this tool to obtain a list of data color themes available in a given environment within a project. It provides thematic options for displaying data visually."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/data_color_themes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_data_color_theme(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "Project ID to access the desired project. Obtain it through a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_data_color_themes_create'."]:  # noqa: E501
    """Create a new data color theme for the environment.

    This tool allows you to create a new data color theme within a specified environment for a project. Use this when you need to define or update visual styles for data representation in an environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDATACOLORTHEME"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDATACOLORTHEME"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDATACOLORTHEME"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/data_color_themes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDATACOLORTHEME"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_color_theme(
    context: ToolContext,
    color_theme_id: Annotated[int, "A unique integer value identifying the data color theme for the environment."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project whose environment color theme data is being accessed. Obtain it via `/api/projects/`."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_data_color_themes_retrieve'."]:  # noqa: E501
    """Retrieve color theme data for a specific environment.

    This tool retrieves detailed color theme data for a specified environment in a project. Use this tool when you need to access or display the visual theme settings of an environment in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=color_theme_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_color_theme(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    data_color_theme_id: Annotated[int | None, "A unique integer value identifying the data color theme to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_data_color_themes_update'."]:  # noqa: E501
    """Update the color theme of an environment.

    Use this tool to change the data color theme of a specific environment identified by project and theme IDs. Useful for customizing the visual presentation of projects.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTCOLORTHEME"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not data_color_theme_id:
        missing_params.append(("data_color_theme_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTCOLORTHEME"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTCOLORTHEME"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=data_color_theme_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTCOLORTHEME"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_theme(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    color_theme_id: Annotated[int | None, "A unique integer identifying the data color theme to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you want to access. Obtain it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_data_color_themes_partial_update'."]:  # noqa: E501
    """Update color themes for project environments.

    This tool updates the color themes of data environments within a specified project. It's useful for changing visual settings or themes in your Datadog project environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTTHEME"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not color_theme_id:
        missing_params.append(("color_theme_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTTHEME"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTTHEME"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=color_theme_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTTHEME"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_color_theme(
    context: ToolContext,
    data_color_theme_id: Annotated[int, "A unique integer value used to identify the data color theme to be deleted."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project for accessing its environment. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_data_color_themes_destroy'."]:  # noqa: E501
    """Delete a specific environment's color theme in Datadog.

    This tool deletes a color theme from a specified environment in Datadog. It should be called when you need to remove a particular color theme from a project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=data_color_theme_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_dataset_items(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project you're accessing. Use /api/projects/ to find it."],  # noqa: E501
    filter_by_dataset_id: Annotated[str | None, "Specify the dataset ID to filter the results by a specific dataset."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page. This defines pagination size."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index from which to return the results. Use this to control the starting point of the returned dataset items."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dataset_items_list'."]:
    """Retrieve dataset items for a specific environment.

    Use this tool to fetch and list all dataset items within a specified environment, given a project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dataset_items/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"dataset": filter_by_dataset_id, "limit": results_per_page, "offset": results_start_index}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_dataset_item(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project you want to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dataset_items_create'."]:  # noqa: E501
    """Create a dataset item in the specified environment.

    This tool allows you to add a new dataset item to a specific environment within a project. Use it when you need to manage or update datasets in your environments efficiently.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASETITEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASETITEM"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASETITEM"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dataset_items/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASETITEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_dataset_item(
    context: ToolContext,
    dataset_item_id: Annotated[str, "A UUID string that identifies the specific dataset item to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project to access. To find it, call /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dataset_items_retrieve'."]:  # noqa: E501
    """Retrieve a specific environment dataset item by ID.

    Use this tool to fetch details of a specific dataset item within an environment using the project and item IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_dataset_item(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_item_uuid: Annotated[str | None, "A UUID string uniquely identifying the dataset item to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique identifier of the project you want to access. Retrieve it by making a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dataset_items_update'."]:  # noqa: E501
    """Update an environment dataset item in a project.

    Use this tool to update specific details of a dataset item within a given environment of a project. It should be called when you need to modify existing dataset entries in an environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASETITEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_item_uuid:
        missing_params.append(("dataset_item_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASETITEM"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASETITEM"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASETITEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_environment_dataset_item(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_item_id: Annotated[str | None, "A UUID string specifying the dataset item to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project to access. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dataset_items_partial_update'."]:  # noqa: E501
    """Update specific fields in an environment dataset item.

    This tool updates specific fields of an existing item in the environment dataset for a given project. It should be called when partial modifications are needed for dataset items.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASETITEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_item_id:
        missing_params.append(("dataset_item_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASETITEM"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASETITEM"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASETITEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_dataset_item(
    context: ToolContext,
    dataset_item_id: Annotated[str, "A UUID string identifying the dataset item to mark as deleted."],  # noqa: E501
    project_id: Annotated[str, "The unique Project ID for accessing the desired project. Retrieve by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_dataset_items_destroy'."]:  # noqa: E501
    """Marks a dataset item in an environment as deleted.

    This tool is used to effectively remove a dataset item from an environment by marking it as deleted. It should be called when a permanent deletion is intended, following the API's restriction against hard deletion. The tool sets the 'deleted' attribute to true for the specified item."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_datasets(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve the ID by calling /api/projects/."],  # noqa: E501
    dataset_ids: Annotated[list[str] | None, "List of dataset IDs to filter results. Provide multiple IDs separated by commas."] = None,  # noqa: E501
    ordering_criteria: Annotated[list[str] | None, "Specify the ordering of the dataset results. Options include `created_at`, `-created_at`, `updated_at`, `-updated_at`. Multiple criteria can be provided as a list."] = None,  # noqa: E501
    results_limit_per_page: Annotated[int | None, "Specifies the number of datasets to return per page. This is used to control pagination and manage the volume of data retrieved in a single call."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index to start returning datasets from, for pagination purposes."] = None,  # noqa: E501
    search_terms: Annotated[str | None, "Search terms to filter datasets by name, description, or metadata."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_datasets_list'."]:
    """Retrieve datasets for a specified project environment.

    This tool retrieves a list of datasets associated with a specified project environment within Datadog. It should be called when you need to view datasets for a particular project's environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/datasets/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"id__in": dataset_ids, "limit": results_limit_per_page, "offset": results_start_index, "order_by": ordering_criteria, "search": search_terms}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_dataset(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id_for_environment: Annotated[str | None, "Project ID for accessing the project where the dataset environment will be created. To get this ID, call the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_datasets_create'."]:
    """Create a dataset environment in a specified project.

    This tool is used to create a new dataset environment within a specified project in Datadog. It should be called when you need to set up a dataset environment in a given project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASET"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id_for_environment:
        missing_params.append(("project_id_for_environment", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASET"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASET"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/datasets/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_environment),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTDATASET"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_dataset(
    context: ToolContext,
    environment_dataset_id: Annotated[str, "A UUID string identifying the specific environment dataset to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_datasets_retrieve'."]:
    """Retrieve a specific environment dataset by ID.

    Use this tool to retrieve detailed information about a specific environment dataset using the project and dataset IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_dataset_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_dataset(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_id: Annotated[str | None, "A UUID string identifying the specific dataset to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Retrieve the ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_datasets_update'."]:
    """Updates details of a specific environment dataset.

    Use this tool to update the details of a specific dataset within an environment by specifying the project and dataset IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASET"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_id:
        missing_params.append(("dataset_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASET"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASET"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTDATASET"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_environment_dataset(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_uuid: Annotated[str | None, "A UUID string identifying the dataset to update within the environment.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique identifier of the project to access. Retrieve via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_datasets_partial_update'."]:  # noqa: E501
    """Update dataset in a specific environment.

    Use this tool to partially update an existing dataset within a specified environment using the project and dataset identifiers.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASET"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_uuid:
        missing_params.append(("dataset_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASET"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASET"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTDATASET"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_dataset(
    context: ToolContext,
    dataset_uuid: Annotated[str, "A UUID string identifying the dataset to be marked as deleted."],
    project_identifier: Annotated[str, "The unique identifier for the project. Use /api/projects/ to find it."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_datasets_destroy'."]:
    """Delete a dataset by setting it to deleted status.

    Use this tool to mark a dataset as deleted by setting its \"deleted\" attribute to true. A hard delete is not supported, so this operation ensures the dataset is flagged as deleted in the system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_endpoint_run_status(
    context: ToolContext,
    endpoint_name: Annotated[str, "The name of the endpoint you want to update or retrieve status for."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access. Obtain it via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_endpoints_run_retrieve'."]:  # noqa: E501
    """Retrieve the run status of an endpoint.

    Use this tool to get the current run status of a specific endpoint within a project environment on Datadog. It's useful for checking the operation and status of a given endpoint run."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/endpoints/{name}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), name=endpoint_name, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_endpoint(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    endpoint_name: Annotated[str | None, "The name of the endpoint to update. This is used to identify the specific endpoint within the project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_endpoints_run_create'."]:  # noqa: E501
    """Update an existing environment endpoint.

    This tool updates an existing endpoint for a specific project in Datadog environments. It should be called when modifications to the endpoint's state or configuration are needed. Parameters for the update are optional.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTENDPOINT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not endpoint_name:
        missing_params.append(("endpoint_name", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTENDPOINT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTENDPOINT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/endpoints/{name}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), name=endpoint_name, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTENDPOINT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_last_execution_times(
    context: ToolContext,
    endpoint_names: Annotated[list[str], "List of endpoint names to retrieve execution times for. Each name should be a string."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you wish to access. Use the /api/projects/ endpoint to retrieve the ID if needed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_endpoints_last_execution_times_create'."]:  # noqa: E501
    """Retrieve last execution times for multiple endpoints.

    Use this tool to get the most recent execution times for various endpoints over the past six months within a specific environment."""  # noqa: E501
    request_data: Any = {"names": endpoint_names}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/endpoints/last_execution_times/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_error_tracking_assignment_rules(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page when listing error tracking assignment rules."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index to start returning results from within the list."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_list'."]:  # noqa: E501
    """Retrieve error tracking assignment rules for a given environment.

    Use this tool to get a list of error tracking assignment rules for a specified environment within a project. It helps in understanding the rules applied in error tracking for different environments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_error_tracking_assignment_rule(
    context: ToolContext,
    assignee_username: Annotated[str, "Username of the individual to whom the error tracking assignment rule is assigned. This should be a valid username within the project."],  # noqa: E501
    assignment_rule_filters: Annotated[str, "Filters to specify the criteria for the error tracking assignment rule. Input as a string."],  # noqa: E501
    order_key_priority: Annotated[int, "An integer specifying the priority order of the rule. Lower values imply higher priority."],  # noqa: E501
    project_id: Annotated[str, "ID of the project to access. Retrieve via /api/projects/ call."],
    rule_id: Annotated[str, "A unique identifier for the error tracking assignment rule to be created."],  # noqa: E501
    disabled_data_state: Annotated[str | None, "Indicates if data for the error tracking rule is disabled. Use 'true' to disable, 'false' to enable."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_create'."]:  # noqa: E501
    """Create a new error tracking assignment rule.

    Use this tool to create a new error tracking assignment rule for specific environments. It is useful for managing error tracking configurations in a project environment."""  # noqa: E501
    request_data: Any = {"id": rule_id, "filters": assignment_rule_filters, "assignee": assignee_username, "order_key": order_key_priority, "disabled_data": disabled_data_state}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_error_tracking_assignment_rules(
    context: ToolContext,
    error_tracking_rule_id: Annotated[str, "A UUID identifying the error tracking assignment rule to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_retrieve'."]:  # noqa: E501
    """Retrieve error tracking assignment rules for a project.

    This tool retrieves information about specific error tracking assignment rules for a given project in Datadog. Call this tool to obtain details about assignment rules using the project and rule IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_rule_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_rules(
    context: ToolContext,
    assignee_identifier: Annotated[str, "The unique identifier for the person to whom errors will be assigned. This can be a user ID or username within the project."],  # noqa: E501
    assignment_rule_id: Annotated[str, "A UUID string that identifies the error tracking assignment rule to update."],  # noqa: E501
    environment_id: Annotated[str, "The unique identifier for the environment whose error tracking rules are being updated."],  # noqa: E501
    filter_criteria: Annotated[str, "Specifies the filter criteria for updating error tracking assignment rules. This should be a string detailing the conditions used to filter the errors."],  # noqa: E501
    project_id: Annotated[str, "Project ID to access. Retrieve it via a call to /api/projects/."],
    update_order_key: Annotated[int, "The order key for arranging assignment rules in a specified sequence. Provide an integer value."],  # noqa: E501
    disable_error_data: Annotated[str | None, "Specify whether to disable error data for tracking rules. Accepts a string value indicating the disabled state."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_update'."]:  # noqa: E501
    """Updates error tracking assignment rules for a project.

    Use this tool to update the assignment rules for error tracking in a specific project environment. This helps in managing how errors are assigned within a project."""  # noqa: E501
    request_data: Any = {"id": environment_id, "filters": filter_criteria, "assignee": assignee_identifier, "order_key": update_order_key, "disabled_data": disable_error_data}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_assignment_rules(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project to access for updating error tracking rules. Obtain it via `/api/projects/`."],  # noqa: E501
    assignee_for_error_tracking: Annotated[str | None, "The identifier of the assignee for the error tracking rule. This should be a string representing the user or team to which the error tracking assignment is being made."] = None,  # noqa: E501
    disabled_data: Annotated[str | None, "Provide a string indicating which data or fields should be marked as disabled in the error tracking rules."] = None,  # noqa: E501
    error_tracking_rule_id: Annotated[str | None, "A UUID string identifying the specific error tracking assignment rule to update."] = None,  # noqa: E501
    filter_expression: Annotated[str | None, "Provide a string that specifies criteria for selecting which rules to update. Use logical expressions to define this filter."] = None,  # noqa: E501
    order_key: Annotated[int | None, "The order key for sorting or prioritizing the assignment rules. Provide as an integer."] = None,  # noqa: E501
    rule_identifier: Annotated[str | None, "The unique ID of the error tracking assignment rule to update."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_partial_update'."]:  # noqa: E501
    """Partially update error tracking assignment rules for environments.

    Use this tool to update specific properties of error tracking assignment rules within a given environment. This can be used to modify existing rules by providing the project and rule identifiers."""  # noqa: E501
    request_data: Any = {"id": rule_identifier, "filters": filter_expression, "assignee": assignee_for_error_tracking, "order_key": order_key, "disabled_data": disabled_data}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=rule_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_error_tracking_rule(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain this by calling /api/projects/."],  # noqa: E501
    rule_id: Annotated[str, "The UUID of the error tracking assignment rule to be deleted."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_destroy'."]:  # noqa: E501
    """Deletes a specified error tracking assignment rule.

    Use this tool to delete a specific error tracking assignment rule within a Datadog environment by providing the project and rule IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=rule_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reorder_assignment_rules(
    context: ToolContext,
    project_id: Annotated[str, "The Project ID for accessing the desired project. Retrieve it using /api/projects/."],  # noqa: E501
    disable_rule_data: Annotated[str | None, "Specify whether rule data is disabled, using 'true' or 'false'."] = None,  # noqa: E501
    rule_filters: Annotated[str | None, "A string containing conditions to filter assignment rules for reordering. Useful for applying specific criteria when reordering rules."] = None,  # noqa: E501
    rule_id: Annotated[str | None, "The specific ID of the assignment rule to be reordered within the project environment."] = None,  # noqa: E501
    rule_order_position: Annotated[int | None, "The new position for the assignment rule in the order list. Use an integer to specify the desired position."] = None,  # noqa: E501
    target_assignee: Annotated[str | None, "Specifies the assignee for the error tracking rules in the project. This should be a valid user identifier in the Datadog environment."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_assignment_rules_reorder_partial_update'."]:  # noqa: E501
    """Reorder error tracking assignment rules in a project environment.

    This tool allows reordering of assignment rules for error tracking within a specific project environment. Useful for prioritizing rules in Datadog environments."""  # noqa: E501
    request_data: Any = {"id": rule_id, "filters": rule_filters, "assignee": target_assignee, "order_key": rule_order_position, "disabled_data": disable_rule_data}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/assignment_rules/reorder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_error_tracking_fingerprints(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project you want to access. Obtain this by calling /api/projects/."],  # noqa: E501
    initial_index_for_results: Annotated[int | None, "The initial index from which to return the results for the error tracking fingerprints list."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page."] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_fingerprints_list'."]:  # noqa: E501
    """Retrieve error tracking fingerprints for a specific project.

    This tool retrieves a list of error tracking fingerprints for a given project, allowing users to analyze and monitor errors efficiently."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/fingerprints/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_index_for_results}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_error_tracking_fingerprint(
    context: ToolContext,
    error_tracking_fingerprint_uuid: Annotated[str, "A UUID identifying the error tracking issue fingerprint v2."],  # noqa: E501
    project_id: Annotated[str, "Project ID to access specific project data. Use /api/projects/ to retrieve this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_fingerprints_retrieve'."]:  # noqa: E501
    """Retrieve a specific error tracking fingerprint by ID.

    Use this tool to fetch detailed information about a specific error tracking fingerprint within a project environment. It is called when needing insights into an error identifier."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/fingerprints/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_fingerprint_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_error_fingerprint(
    context: ToolContext,
    error_fingerprint_uuid: Annotated[str, "A UUID string identifying the specific error tracking issue fingerprint to be marked as deleted."],  # noqa: E501
    posthog_project_id: Annotated[str, "The ID of the Datadog project you want to modify. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_fingerprints_destroy'."]:  # noqa: E501
    """Mark an error fingerprint as deleted in Datadog.

    Use this tool to mark an error fingerprint as deleted in a specified Datadog project environment. This does not perform a hard delete but sets the fingerprint's status to 'deleted' using a DELETE request."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/fingerprints/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_fingerprint_uuid, project_id=posthog_project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def resolve_github_file_links(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve the ID via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_git_provider_file_links_resolve_github_retrieve'."]:  # noqa: E501
    """Resolve GitHub file links for error tracking projects.

    This tool retrieves resolved file links from GitHub for error tracking within specific environments, helping to pinpoint file locations in your project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/git-provider-file-links/resolve_github/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_error_tracking_grouping_rules(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    initial_index_for_results: Annotated[int | None, "The starting index from which to return results, used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page when listing error tracking grouping rules."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_list'."]:  # noqa: E501
    """Retrieve error tracking grouping rules for a project.

    This tool fetches the error tracking grouping rules for a specified project within Datadog environments. It is useful for understanding how errors are categorized and grouped in the project's monitoring setup."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_index_for_results}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_error_tracking_grouping_rule(
    context: ToolContext,
    assignee_identifier: Annotated[str, "The identifier of the user to whom the error tracking issue is assigned. Provide a valid user ID or username."],  # noqa: E501
    error_tracking_filters: Annotated[str, "Filters for error tracking grouping rule. Provide criteria to classify errors, such as error types or patterns."],  # noqa: E501
    order_priority_key: Annotated[int, "An integer representing the priority or sequence order of the error tracking grouping rule within the project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
    rule_identifier: Annotated[str, "A unique string identifier for the new error tracking grouping rule."],  # noqa: E501
    grouping_rule_disabled_data: Annotated[str | None, "Indicate if the grouping rule data should be disabled. Accepts a boolean in string form, like 'true' or 'false'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_create'."]:  # noqa: E501
    """Create a new error tracking grouping rule for a project.

    This tool is used to create a new error tracking grouping rule within a specified project environment. It helps in organizing and managing error tracking efficiently."""  # noqa: E501
    request_data: Any = {"id": rule_identifier, "filters": error_tracking_filters, "assignee": assignee_identifier, "order_key": order_priority_key, "disabled_data": grouping_rule_disabled_data}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_error_grouping_rules(
    context: ToolContext,
    grouping_rule_id: Annotated[str, "A UUID string identifying this specific error tracking grouping rule for retrieval."],  # noqa: E501
    project_id_for_access: Annotated[str, "The ID of the project you are trying to access for retrieving error tracking grouping rules. Obtain using the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_retrieve'."]:  # noqa: E501
    """Retrieve error tracking grouping rules for an environment.

    This tool retrieves error tracking grouping rules for a specified environment and project. It should be called when you need detailed information about the grouping rules applied to error tracking in a particular environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=grouping_rule_id, project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_grouping_rules(
    context: ToolContext,
    assignee_user_id: Annotated[str, "The user ID of the person to whom the error tracking task is assigned."],  # noqa: E501
    filters_for_grouping_rules: Annotated[str, "Specify filters as a string to refine which errors to group. This can include criteria like error type or severity."],  # noqa: E501
    grouping_rule_id: Annotated[str, "A UUID string identifying the error tracking grouping rule to update in Datadog."],  # noqa: E501
    priority_order_key: Annotated[int, "Specify the integer value to determine the priority order of grouping rules."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    rule_id: Annotated[str, "The unique identifier for the error tracking grouping rule to be updated."],  # noqa: E501
    disabled_data: Annotated[str | None, "A string indicating which data to disable in the error tracking grouping rules. Provide the specific data identifier or description."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_update'."]:  # noqa: E501
    """Update error tracking grouping rules for a project.

    Use this tool to update the grouping rules for error tracking within a specified project environment in Datadog."""  # noqa: E501
    request_data: Any = {"id": rule_id, "filters": filters_for_grouping_rules, "assignee": assignee_user_id, "order_key": priority_order_key, "disabled_data": disabled_data}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=rule_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_grouping_rules(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    assigned_user: Annotated[str | None, "Specify the user assigned to manage the error tracking rules. It should be the username or ID of the Datadog user."] = None,  # noqa: E501
    disable_data_filtering: Annotated[str | None, "Specifies data filtering rules to be disabled. Provide a string indicating the types of rules or data aspects to disable."] = None,  # noqa: E501
    error_tracking_rule_uuid: Annotated[str | None, "A UUID string identifying the error tracking grouping rule to update."] = None,  # noqa: E501
    filters_string: Annotated[str | None, "String containing filtering conditions for updating grouping rules. Specify conditions to narrow down rules to be updated."] = None,  # noqa: E501
    grouping_rule_order_key: Annotated[int | None, "An integer that specifies the priority order of the error grouping rule within a project. Higher values may denote higher priority."] = None,  # noqa: E501
    rule_id: Annotated[str | None, "The ID of the grouping rule to be updated. Required for specifying which rule to modify within the project."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_partial_update'."]:  # noqa: E501
    """Update error tracking grouping rules for a project.

    Use this tool to update specific error tracking grouping rules within a project environment on Datadog. It should be called when you need to modify grouping rules for error tracking purposes in a specified project."""  # noqa: E501
    request_data: Any = {"id": rule_id, "filters": filters_string, "assignee": assigned_user, "order_key": grouping_rule_order_key, "disabled_data": disable_data_filtering}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=rule_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_error_tracking_rule(
    context: ToolContext,
    error_tracking_rule_id: Annotated[str, "A UUID string identifying the specific error tracking grouping rule to be deleted."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtain it using /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_destroy'."]:  # noqa: E501
    """Delete an error tracking grouping rule in a project.

    Use this tool to delete a specific error tracking grouping rule within a Datadog environment by specifying the project and rule identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_rule_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reorder_error_tracking_rules(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you wish to access. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
    disabled_data_details: Annotated[str | None, "Specify details of the data to disable or modify. Format as a string describing which elements are affected."] = None,  # noqa: E501
    error_grouping_filters: Annotated[str | None, "Filters to apply for selecting specific error tracking rules to reorder. This can include criteria like rule severity, type, etc."] = None,  # noqa: E501
    error_tracking_rule_id: Annotated[str | None, "Unique identifier for the error tracking rule you want to reorder."] = None,  # noqa: E501
    new_order_key: Annotated[int | None, "An integer representing the new order position for the error tracking grouping rules."] = None,  # noqa: E501
    rule_assignee: Annotated[str | None, "Assign a person or role responsible for the error tracking grouping rule. Expected to be a string representing a user's name or identifier."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_grouping_rules_reorder_partial_update'."]:  # noqa: E501
    """Reorder error tracking grouping rules in a project.

    Use this tool to change the order of error tracking grouping rules within a specified project environment. Useful for prioritizing or restructuring how errors are grouped."""  # noqa: E501
    request_data: Any = {"id": error_tracking_rule_id, "filters": error_grouping_filters, "assignee": rule_assignee, "order_key": new_order_key, "disabled_data": disabled_data_details}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/grouping_rules/reorder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_error_tracking_releases(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project to access. Obtain by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "The number of results to return per page for error tracking releases."] = None,  # noqa: E501
    start_index_for_results: Annotated[int | None, "The starting index for the results to be returned. Use this to paginate results in the list of error tracking releases."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_list'."]:  # noqa: E501
    """Retrieve releases from error tracking for a specific environment.

    Fetches a list of releases related to error tracking within a specified environment of a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index_for_results}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_error_tracking_release(
    context: ToolContext,
    error_release_id: Annotated[str, "Unique identifier for the error tracking release to be accessed or modified."],  # noqa: E501
    hash_identifier: Annotated[str, "Unique string identifier for the release hash. Required for tracking specific releases."],  # noqa: E501
    project_id: Annotated[str, "ID of the project for which to create an error tracking release. Obtainable via /api/projects/."],  # noqa: E501
    project_name: Annotated[str, "The name of the project for which you want to create an error tracking release."],  # noqa: E501
    release_creation_timestamp: Annotated[str, "Timestamp indicating when the error tracking release was created. Format should be ISO 8601 (e.g., 2023-10-02T14:48:00Z)."],  # noqa: E501
    release_version: Annotated[str, "The version identifier for the new error tracking release."],
    team_identifier: Annotated[int, "The integer ID of the team associated with the error tracking release. Required to specify the team context in Datadog."],  # noqa: E501
    release_metadata: Annotated[str | None, "Optional metadata for the error tracking release. Provide additional information in a string format."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_create'."]:  # noqa: E501
    """Create a new error tracking release for a project.

    Use this tool to create a new error tracking release for a specified project within Datadog. This can help manage and track errors in different project environments, ensuring a systematic approach to error monitoring."""  # noqa: E501
    request_data: Any = {"id": error_release_id, "hash_id": hash_identifier, "team_id": team_identifier, "created_at": release_creation_timestamp, "metadata": release_metadata, "version": release_version, "project": project_name}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_error_tracking_release(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID to access specific error tracking release data. Obtainable via /api/projects/ call."],  # noqa: E501
    release_uuid: Annotated[str, "A UUID string identifying the specific error tracking release to retrieve details for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_retrieve'."]:  # noqa: E501
    """Retrieves details of a specific error tracking release.

    Use this tool to obtain detailed information about a specific error tracking release within a project environment. Call this when you need insights into a particular release's error tracking data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=release_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_releases(
    context: ToolContext,
    created_at_timestamp: Annotated[str, "The timestamp indicating when the release was created. Format should be ISO 8601 (e.g., '2023-09-23T18:25:43.511Z')."],  # noqa: E501
    project_identifier: Annotated[str, "The Project ID for accessing the specific project in Datadog. Obtainable by calling /api/projects/."],  # noqa: E501
    project_key: Annotated[str, "The identifier or name of the project for which you're updating the error tracking release."],  # noqa: E501
    release_hash_id: Annotated[str, "A unique identifier for the release you want to update. Provides a reference to the specific release version within the project's error tracking data."],  # noqa: E501
    release_id: Annotated[str, "A UUID string identifying the error tracking release to update."],
    release_version: Annotated[str, "The version of the release being updated. This should typically be a string representing the version code or number."],  # noqa: E501
    team_identifier: Annotated[int, "The unique integer identifier for the team. Used to specify which team's release information to update."],  # noqa: E501
    update_id: Annotated[str, "The unique identifier for the release you want to update."],
    metadata_description: Annotated[str | None, "Provide a string with additional information or details about the release metadata."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_update'."]:  # noqa: E501
    """Update error tracking releases in a project environment.

    Use this tool to update error tracking releases for a specific project environment in Datadog. Ideal for modifying release information in error tracking systems."""  # noqa: E501
    request_data: Any = {"id": update_id, "hash_id": release_hash_id, "team_id": team_identifier, "created_at": created_at_timestamp, "metadata": metadata_description, "version": release_version, "project": project_key}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=update_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_release(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve by calling /api/projects/."],  # noqa: E501
    error_tracking_release_id: Annotated[str | None, "A UUID string identifying the error tracking release to be updated."] = None,  # noqa: E501
    release_creation_date: Annotated[str | None, "The date and time when the error tracking release was created. Expected in ISO 8601 format (e.g., 2023-10-31T14:30:00Z)."] = None,  # noqa: E501
    release_hash_identifier: Annotated[str | None, "A unique string identifier for the error tracking release to be updated."] = None,  # noqa: E501
    release_id: Annotated[str | None, "The unique identifier of the error tracking release to update."] = None,  # noqa: E501
    release_metadata: Annotated[str | None, "Metadata for the error tracking release. This should be a string detailing any additional information relevant to the release."] = None,  # noqa: E501
    release_project_name: Annotated[str | None, "The name of the project associated with the error tracking release to be updated."] = None,  # noqa: E501
    release_version: Annotated[str | None, "The specific version of the error tracking release to update. It should be a string representing the version number."] = None,  # noqa: E501
    team_identifier: Annotated[int | None, "The unique identifier for the team associated with the error tracking release. Expected to be an integer."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_partial_update'."]:  # noqa: E501
    """Update details for an error tracking release.

    Use this tool to modify the details of an error tracking release within a specified project environment on Datadog."""  # noqa: E501
    request_data: Any = {"id": release_id, "hash_id": release_hash_identifier, "team_id": team_identifier, "created_at": release_creation_date, "metadata": release_metadata, "version": release_version, "project": release_project_name}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=release_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_error_tracking_release(
    context: ToolContext,
    error_tracking_release_id: Annotated[str, "A UUID string identifying the error tracking release to be deleted."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project being accessed. Use `/api/projects/` to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_destroy'."]:  # noqa: E501
    """Deletes a specific error tracking release from a project environment.

    This tool deletes a specific error tracking release identified by its ID from a given project environment in Datadog. It should be called when there is a need to permanently remove a release from error tracking records."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_release_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_error_tracking_release_hash(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
    release_hash_id: Annotated[str, "The unique identifier for the error tracking release hash. This ID is necessary to retrieve the specific details."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_releases_hash_retrieve'."]:  # noqa: E501
    """Retrieve details for a specific error tracking release hash.

"""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/releases/hash/{hash_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), hash_id=release_hash_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_error_tracking_suppression_rules(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page."] = None,
    results_start_index: Annotated[int | None, "The starting index for the results to be returned, useful for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_list'."]:  # noqa: E501
    """List error tracking suppression rules for a project environment.

    Fetches the error tracking suppression rules for a specified project environment. Use this tool to retrieve information about existing suppression rules within a particular environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_error_tracking_suppression_rule(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
    suppress_rule_order_key: Annotated[int, "An integer representing the order or priority of the suppression rule in the list. Determines processing sequence."],  # noqa: E501
    suppression_rule_filters: Annotated[str, "A string defining the criteria to filter which errors should be suppressed. Specify conditions relevant to your project's needs."],  # noqa: E501
    suppression_rule_id: Annotated[str, "A unique identifier for the suppression rule to be created. This ID helps in tracking and managing the specific rule."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_create'."]:  # noqa: E501
    """Create a new error tracking suppression rule.

    Use this tool to create a new suppression rule for error tracking environments. It should be called when you need to suppress specific errors in a project's environment."""  # noqa: E501
    request_data: Any = {"id": suppression_rule_id, "filters": suppression_rule_filters, "order_key": suppress_rule_order_key}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_suppression_rule_details(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project to access. Obtainable via the /api/projects/ call."],  # noqa: E501
    suppression_rule_uuid: Annotated[str, "A UUID string identifying the specific error tracking suppression rule."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_retrieve'."]:  # noqa: E501
    """Retrieve details of a suppression rule in error tracking.

    Use this tool to get information about a specific suppression rule in the error tracking system, including its settings and parameters. It is useful when you need to understand or manage rule configurations within a project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=suppression_rule_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_suppression_rules(
    context: ToolContext,
    filters: Annotated[str, "String criteria used to specify which errors to suppress. Format should align with Datadog's filtering syntax."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Use the API call /api/projects/ to obtain this ID."],  # noqa: E501
    rule_id: Annotated[str, "The unique identifier for the suppression rule to be updated."],
    suppression_rule_id: Annotated[str, "A UUID string identifying the error tracking suppression rule."],  # noqa: E501
    suppression_rule_order_key: Annotated[int, "Specify the order key for the suppression rule. This determines its priority in execution."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_update'."]:  # noqa: E501
    """Update error tracking suppression rules for a project.

    Call this tool to update suppression rules for error tracking within a specific project environment on Datadog."""  # noqa: E501
    request_data: Any = {"id": rule_id, "filters": filters, "order_key": suppression_rule_order_key}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=rule_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_suppression_rule(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you're trying to access. Call /api/projects/ to find the ID."],  # noqa: E501
    rule_id: Annotated[str | None, "The unique identifier of the suppression rule to update. This ID is required to specify which rule you want to partially update."] = None,  # noqa: E501
    rule_order_key: Annotated[int | None, "Specify the order for the suppression rule as an integer. Determines rule priority or execution sequence."] = None,  # noqa: E501
    suppression_rule_filters: Annotated[str | None, "A string defining filters for the suppression rule updates (e.g., specific conditions or parameters)."] = None,  # noqa: E501
    suppression_rule_id: Annotated[str | None, "The UUID identifying the error tracking suppression rule to update."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_partial_update'."]:  # noqa: E501
    """Update error tracking suppression rules for a project.

    Use this tool to partially update suppression rules for error tracking in specific environments within a project on Datadog."""  # noqa: E501
    request_data: Any = {"id": rule_id, "filters": suppression_rule_filters, "order_key": rule_order_key}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=rule_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_error_suppression_rule(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Use /api/projects/ to find it."],  # noqa: E501
    suppression_rule_uuid: Annotated[str, "A UUID string that uniquely identifies the error tracking suppression rule to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_destroy'."]:  # noqa: E501
    """Delete an error tracking suppression rule.

    Use this tool to delete a specific error tracking suppression rule in a given project environment within Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=suppression_rule_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reorder_error_tracking_suppression_rules(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project for which you want to reorder suppression rules. To locate the ID, make a call to /api/projects/."],  # noqa: E501
    error_tracking_filters: Annotated[str | None, "Specify filter criteria to narrow down which suppression rules are reordered, using a string format."] = None,  # noqa: E501
    new_order_key: Annotated[int | None, "Integer representing the new order sequence for suppression rules in a project."] = None,  # noqa: E501
    suppression_rule_id: Annotated[str | None, "The unique ID of the suppression rule you're reordering within the project."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_suppression_rules_reorder_partial_update'."]:  # noqa: E501
    """Reorder error tracking suppression rules for a project.

    Use this tool to reorder suppression rules within a specified project's error tracking environment. This is essential for adjusting the priority or sequence of how errors are suppressed."""  # noqa: E501
    request_data: Any = {"id": suppression_rule_id, "filters": error_tracking_filters, "order_key": new_order_key}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/suppression_rules/reorder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_error_tracking_symbol_sets(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The initial index from which to return the results for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_list'."]:  # noqa: E501
    """Retrieve error tracking symbol sets for a project.

    This tool retrieves a list of error tracking symbol sets associated with a specific project environment in Datadog. Use this when you need to access symbol set information for debugging or monitoring purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_symbol_set(
    context: ToolContext,
    project_id: Annotated[str, "Project ID needed to access the specific project for creating a symbol set. Obtainable via /api/projects/ call."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_create'."]:  # noqa: E501
    """Create a new symbol set for error tracking in a project.

    This tool is used to create a new symbol set for error tracking within a specified project in Datadog. It should be called when you want to add symbol sets to environments for better error tracking."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_error_tracking_symbol_set(
    context: ToolContext,
    error_tracking_symbol_set_uuid: Annotated[str, "A UUID string identifying the specific error tracking symbol set to retrieve."],  # noqa: E501
    project_id: Annotated[str, "Project ID for accessing the specified project. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific error tracking symbol set.

    Use this tool to obtain detailed information about a specific error tracking symbol set for a project environment within Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_symbol_set_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_symbol_set(
    context: ToolContext,
    error_tracking_symbol_set_id: Annotated[str, "A UUID identifying the error tracking symbol set to update."],  # noqa: E501
    project_id_for_symbol_set_update: Annotated[str, "The ID of the project for updating the symbol set. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_update'."]:  # noqa: E501
    """Update error tracking symbol sets in environments.

    Use this tool to update the symbol sets for error tracking within a specified environment by providing the project and symbol set IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_symbol_set_id, project_id=project_id_for_symbol_set_update),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_error_tracking_symbols(
    context: ToolContext,
    error_tracking_symbol_set_id: Annotated[str, "A UUID identifying the error tracking symbol set to update."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project you wish to access. Retrieve by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_partial_update'."]:  # noqa: E501
    """Update symbol sets for error tracking in a specific environment.

    Use this tool to update symbol sets for error tracking within a specified project environment. It should be called when you need to modify existing symbol set data in the Datadog environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=error_tracking_symbol_set_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_symbol_set(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Use the /api/projects/ endpoint to find this ID."],  # noqa: E501
    symbol_set_id: Annotated[str, "A UUID string identifying the error tracking symbol set to delete."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_destroy'."]:  # noqa: E501
    """Deletes an error tracking symbol set by ID.

    Use this tool to delete a specific error tracking symbol set for a project by providing the project and symbol set IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=symbol_set_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def complete_symbol_set_upload(
    context: ToolContext,
    project_id_for_symbol_set: Annotated[str, "Specify the Project ID for accessing the project in Datadog. Retrieve using the /api/projects/ endpoint."],  # noqa: E501
    reference_id: Annotated[str, "A unique identifier for the symbol set upload reference."],
    symbol_set_id: Annotated[str, "A UUID string identifying the specific error tracking symbol set to be finalized."],  # noqa: E501
    team_identifier: Annotated[int, "The unique integer identifier representing the team within the Datadog project."],  # noqa: E501
    upload_created_at_timestamp: Annotated[str, "The timestamp marking when the upload was created, in ISO 8601 format."],  # noqa: E501
    upload_session_id: Annotated[str, "The unique identifier for the symbol set upload session you wish to complete. This ID is obtained during the initial upload process."],  # noqa: E501
    storage_pointer: Annotated[str | None, "A string representing the storage location pointer for the symbol set. Required to identify the upload location within Datadog."] = None,  # noqa: E501
    upload_failure_reason: Annotated[str | None, "Provide the reason for upload failure if applicable. This helps in diagnosing issues related to the symbol set upload process in Datadog."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_finish_upload_update'."]:  # noqa: E501
    """Finalize the upload of symbol sets in Datadog error tracking.

    Use this tool to complete the upload process of symbol sets in Datadog's error tracking environment for a specific project. Call this when you need to finalize an upload that has already started."""  # noqa: E501
    request_data: Any = {"id": upload_session_id, "ref": reference_id, "team_id": team_identifier, "created_at": upload_created_at_timestamp, "storage_ptr": storage_pointer, "failure_reason": upload_failure_reason}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/{id}/finish_upload/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=upload_session_id, project_id=project_id_for_symbol_set),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def complete_symbol_sets_upload(
    context: ToolContext,
    project_id: Annotated[str, "Specifies the Project ID for access. Obtain this ID via the /api/projects/ endpoint."],  # noqa: E501
    reference_identifier: Annotated[str, "A string used to identify the symbol set upload reference. It helps in finalizing the upload process."],  # noqa: E501
    symbol_set_id: Annotated[str, "Unique identifier for the symbol set upload session to complete."],  # noqa: E501
    team_identifier: Annotated[int, "The integer ID of the team associated with the symbol sets upload you are finalizing. Required for access control and process completion."],  # noqa: E501
    upload_completion_timestamp: Annotated[str, "Timestamp indicating when the upload process was completed, in ISO 8601 format."],  # noqa: E501
    storage_pointer: Annotated[str | None, "A string value representing the storage pointer identifier for the symbol sets. Used to specify the location where the symbol sets are stored."] = None,  # noqa: E501
    upload_failure_reason: Annotated[str | None, "A description of the reason for the upload failure, if applicable. Provide detailed information about what caused the issue."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_bulk_finish_upload_create'."]:  # noqa: E501
    """Complete the uploading process for symbol sets in error tracking.

    Use this tool to finalize the upload process for symbol sets in error tracking environments. Typically called after all parts of symbol sets are uploaded to signal completion."""  # noqa: E501
    request_data: Any = {"id": symbol_set_id, "ref": reference_identifier, "team_id": team_identifier, "created_at": upload_completion_timestamp, "storage_ptr": storage_pointer, "failure_reason": upload_failure_reason}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/bulk_finish_upload/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def start_error_tracking_upload(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Obtainable via /api/projects/ API call."],  # noqa: E501
    team_id: Annotated[int, "Numeric ID of the team associated with the error tracking upload."],
    upload_creation_timestamp: Annotated[str, "The ISO 8601 timestamp indicating when the upload was created. This helps to record the exact time of initiating the upload process."],  # noqa: E501
    upload_reference: Annotated[str, "A unique identifier for the bulk upload session to ensure proper tracking and management."],  # noqa: E501
    upload_task_id: Annotated[str, "Unique identifier for the bulk upload task. Used to reference the upload process."],  # noqa: E501
    storage_pointer: Annotated[str | None, "A string that identifies where the symbol sets are stored. Use this to specify the location for the bulk upload."] = None,  # noqa: E501
    upload_failure_reason: Annotated[str | None, "Provide a description if there was a failure during bulk upload initiation. This can help identify issues with the upload process."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_bulk_start_upload_create'."]:  # noqa: E501
    """Initiate a bulk upload for error tracking symbols.

    Use this tool to start a bulk upload process for symbol sets in error tracking within specified environments. Ideal for managing error tracking data efficiently."""  # noqa: E501
    request_data: Any = {"id": upload_task_id, "ref": upload_reference, "team_id": team_id, "created_at": upload_creation_timestamp, "storage_ptr": storage_pointer, "failure_reason": upload_failure_reason}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/bulk_start_upload/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def start_symbol_upload(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Obtain it via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_error_tracking_symbol_sets_start_upload_create'."]:  # noqa: E501
    """Initiate symbol set upload for error tracking environments.

    This tool is used to start the upload of a symbol set for error tracking within a specified environment. It should be called when you need to upload symbols to aid in error monitoring and tracking."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/error_tracking/symbol_sets/start_upload/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_evaluation_run(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access for the evaluation run. Retrieve it using /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluation_runs_create'."]:  # noqa: E501
    """Initiate a new evaluation run for a project.

    This tool creates a new evaluation run within a specified project and enqueues it for asynchronous execution. It should be called when you need to start an evaluation process related to an environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/evaluation_runs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_evaluations(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project to access evaluations. Retrieve via /api/projects/."],  # noqa: E501
    evaluation_ids: Annotated[list[str] | None, "List of evaluation IDs to filter results. Multiple IDs allowed, separated by commas."] = None,  # noqa: E501
    evaluation_ordering: Annotated[list[str] | None, "Specify the ordering of results. Use created_at, updated_at, or name, with optional '-' for descending."] = None,  # noqa: E501
    filter_by_enabled_status: Annotated[bool | None, "Filter by enabled (true) or disabled (false) evaluations."] = None,  # noqa: E501
    results_offset_index: Annotated[int | None, "The initial index from which to return the results, allowing pagination control."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page in the environment evaluations list."] = None,  # noqa: E501
    search_query: Annotated[str | None, "Search in the evaluation's name or description. Use this to filter results by specific keywords."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluations_list'."]:
    """Retrieve evaluations for a specific project environment.

    Call this tool to obtain a list of evaluations for the environment of a specified project in Datadog. Useful for monitoring and analyzing environment performance and configurations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/evaluations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"enabled": filter_by_enabled_status, "id__in": evaluation_ids, "limit": results_per_page, "offset": results_offset_index, "order_by": evaluation_ordering, "search": search_query}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_evaluation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID to access. Obtainable from calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluations_create'."]:
    """Create a new environment evaluation for a project.

    Use this tool to create and initiate an evaluation process for a specific environment within a project. Suitable for tracking and assessing environment configurations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEVALUATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEVALUATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEVALUATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/evaluations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEVALUATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_evaluation(
    context: ToolContext,
    evaluation_id: Annotated[str, "A UUID string that uniquely identifies the evaluation to be retrieved."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project to access. Use /api/projects/ to find it."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluations_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific environment evaluation.

    Use this tool to get details about a specific environment evaluation by providing the project and evaluation IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/evaluations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=evaluation_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_evaluation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    evaluation_id: Annotated[str | None, "A UUID string uniquely identifying the evaluation to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to update. Obtainable via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluations_update'."]:
    """Update an environment's evaluation in a project.

    Use this tool to update the evaluation details of a specific environment within a given project. It requires the project and evaluation identifiers to locate and modify the corresponding record.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEVALUATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not evaluation_id:
        missing_params.append(("evaluation_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEVALUATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEVALUATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/evaluations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=evaluation_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTEVALUATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_environment_evaluation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    evaluation_id: Annotated[str | None, "A UUID string that identifies the specific environment evaluation to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Provide the Project ID to identify and access the specific project. Use /api/projects/ to retrieve the ID if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluations_partial_update'."]:  # noqa: E501
    """Update specific environment evaluation details.

    This tool updates specific details of an environment evaluation using partial data. It should be called when there is a need to modify environment evaluations for a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTEVALUATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not evaluation_id:
        missing_params.append(("evaluation_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTEVALUATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTEVALUATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/evaluations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=evaluation_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTEVALUATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_evaluation(
    context: ToolContext,
    evaluation_uuid: Annotated[str, "A UUID string identifying the evaluation to be marked as deleted."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access in Datadog. Retrieve it via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_evaluations_destroy'."]:  # noqa: E501
    """Marks an evaluation as deleted in the environment.

    Use this tool to mark a specific evaluation as deleted in a Datadog environment by setting the \"deleted\" flag to true. This is useful for managing evaluation records without permanent deletion."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/evaluations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=evaluation_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_event(
    context: ToolContext,
    event_id: Annotated[str, "The unique identifier for the environment event you want to retrieve details for."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project you want to access. Use /api/projects/ to obtain it if unknown."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the desired format of the response. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_events_retrieve'."]:
    """Retrieve details of a specific environment event.

    Use this tool to fetch detailed information about a specific event within a given environment in your project using DataDog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/events/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_event_values(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access environment data. Retrieve via /api/projects/."],  # noqa: E501
    output_format: Annotated[str | None, "Specifies the format of the returned data. Use 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_events_values_retrieve'."]:  # noqa: E501
    """Retrieve event values for a specific environment.

    This tool should be called to retrieve event values for a particular environment within a project. It requires the project ID to access the relevant environment data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/events/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def environment_exports_overview(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve the ID using a call to /api/projects/."],  # noqa: E501
    result_start_index: Annotated[int | None, "The initial index from which to start returning results for the exports list."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_exports_list'."]:
    """Retrieve a list of exports for a specified environment.

    This tool retrieves a list of data exports for a given project's environment. Use it to view available export data for analysis or record-keeping."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique ID of the project for which you want to create environment exports. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_exports_create'."]:
    """Initiates the creation of environment exports in Datadog.

    Use this tool to initiate the creation of environment export files for a specific project in Datadog. This is useful for backing up or transferring project environment settings.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEXPORTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEXPORTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_exports(
    context: ToolContext,
    export_id: Annotated[int, "A unique integer value identifying the exported asset to retrieve."],
    project_id: Annotated[str, "The ID of the project to access. Retrieve using /api/projects/."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_exports_retrieve'."]:
    """Retrieve details of an environment export in Datadog.

    Call this tool to get information about a specific environment export using its project ID and export ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_export_content(
    context: ToolContext,
    exported_asset_id: Annotated[int, "A unique integer value identifying the exported asset. Required to retrieve the specific environment export content."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the desired project. Retrieve the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_exports_content_retrieve'."]:  # noqa: E501
    """Retrieve content of a specific environment export.

    Fetches the content of a specific export for a given environment using the project and export IDs. Use this to obtain detailed export information."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/exports/{id}/content/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=exported_asset_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_file_systems(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Use /api/projects/ to retrieve this ID if unknown."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The initial index from which to return the results. Use this to paginate through data."] = None,  # noqa: E501
    results_per_page_limit: Annotated[int | None, "Specify the number of results to return per page when listing file systems."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A search term to filter the results based on specific criteria."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_list'."]:
    """Retrieve file systems for a given project environment.

    Fetches a list of file systems associated with a specified project environment using the project ID. Useful for obtaining storage details within the project's context."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page_limit, "offset": initial_result_index, "search": search_term}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_file_system_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access for environment creation. Retrieve it from /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_create'."]:
    """Create a new file system environment in a project.

    Use this tool to create a new file system environment within a specified project. It should be called when setting up storage environments for applications or data within a project on Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environment_file_system_details(
    context: ToolContext,
    file_system_uuid: Annotated[str, "A UUID string identifying the file system to retrieve details for."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the specific project environment. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_retrieve'."]:  # noqa: E501
    """Retrieve details of a file system in a specific environment.

    Call this tool to get information about a file system within a specified project environment. Useful for monitoring or managing resources."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_file_system(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_id: Annotated[str | None, "A UUID string identifying this file system for the update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique identifier for the project containing the environment. Retrieve using the /api/projects/ endpoint if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_update'."]:
    """Update a file system for a specific environment.

    This tool updates the file system within a specified environment using the project and file system IDs. Use it when changes to the environment's file system are required.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTFILESYSTEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_id:
        missing_params.append(("file_system_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTFILESYSTEM"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTFILESYSTEM"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTFILESYSTEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_environment_file_system(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_id: Annotated[str | None, "A UUID string that uniquely identifies the specific file system to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique identifier for the project you want to modify. Use the endpoint `/api/projects/` to retrieve this ID if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_partial_update'."]:  # noqa: E501
    """Partially update a file system environment in a project.

    Use this tool to update specific fields of a file system environment in a given project within Datadog. It should be called when modifications are needed for an existing environment's file system settings.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTFILESYSTEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_id:
        missing_params.append(("file_system_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTFILESYSTEM"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTFILESYSTEM"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTFILESYSTEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_filesystem_environment(
    context: ToolContext,
    filesystem_id: Annotated[str, "A UUID string identifying the file system to be deleted."],
    project_identifier: Annotated[str, "The Project ID of the specific environment. Obtainable through /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_destroy'."]:  # noqa: E501
    """Deletes a file system in the specified environment.

    Use this tool to delete a file system within a given environment by specifying the project and file system IDs. This action is irreversible and should be used when you want to remove unwanted or obsolete file systems."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=filesystem_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_file_count_in_folder(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_uuid: Annotated[str | None, "A UUID string identifying the file system to get the file count.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID for accessing the desired project. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_count_create'."]:  # noqa: E501
    """Retrieve the count of all files in a specified folder.

    This tool is used to obtain the count of files within a specified directory for a given project. Call this tool when you need to know how many files are present in a specific folder.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GETFILECOUNTINFOLDER"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_uuid:
        missing_params.append(("file_system_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GETFILECOUNTINFOLDER"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GETFILECOUNTINFOLDER"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/count/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GETFILECOUNTINFOLDER"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_file_system_link(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_uuid: Annotated[str | None, "A UUID string that uniquely identifies the file system to be linked.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve using /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_link_create'."]:  # noqa: E501
    """Create a link between environment and file system.

    This tool creates a link between a specified environment and a file system within a project in Datadog. It should be used when you want to associate a file system with an environment. The action is confirmed upon successful execution.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLINK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_uuid:
        missing_params.append(("file_system_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLINK"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLINK"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/link/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLINK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def move_file_within_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_uuid: Annotated[str | None, "A UUID string identifying the file system to move within the environment.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID for accessing the specific project environment. Obtain it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_move_create'."]:  # noqa: E501
    """Move a file within an environment's file system.

    Use this tool to move a file from one location to another within the file system of a specified environment in a project. It's useful for reorganizing content or changing file structures in the environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MOVEFILEWITHINENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_uuid:
        missing_params.append(("file_system_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MOVEFILEWITHINENVIRONMENT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MOVEFILEWITHINENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/{id}/move/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MOVEFILEWITHINENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def count_files_in_directory(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The project ID for accessing the desired project. Retrieve this ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_count_by_path_create'."]:  # noqa: E501
    """Get count of all files in a specified folder.

    Use this tool to obtain the total number of files within a specific folder in a given project environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["COUNTFILESINDIRECTORY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["COUNTFILESINDIRECTORY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["COUNTFILESINDIRECTORY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/count_by_path/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["COUNTFILESINDIRECTORY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_file_system_log_view(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID to access the specific environment. Use /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_log_view_create'."]:  # noqa: E501
    """Create a file system log view for an environment.

    This tool is used to create a file system log view for a specific project environment. It should be called when there is a need to set up or modify logging configurations in the environment's file system.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLOGVIEW"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLOGVIEW"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLOGVIEW"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/log_view/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTFILESYSTEMLOGVIEW"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_unfiled_file_system_items(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the specific project whose unfiled file system items you want to retrieve. To obtain this ID, call /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_unfiled_retrieve'."]:  # noqa: E501
    """Retrieve unfiled file system items for a project.

    Use this tool to access unfiled file system items within a specified project environment on Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system/unfiled/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_file_system_shortcuts(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project whose file system shortcuts you want to access. Use the /api/projects/ call to find the ID."],  # noqa: E501
    result_start_index: Annotated[int | None, "The initial index from which to start returning results for the file system shortcuts list."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page when retrieving file system shortcuts."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_shortcut_list'."]:  # noqa: E501
    """Retrieve file system shortcuts for a specified project.

    This tool fetches a list of file system shortcuts for a specific project by its project ID. It should be called when you need to view or manage shortcuts within a project's environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system_shortcut/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_file_system_shortcut(
    context: ToolContext,
    creation_timestamp: Annotated[str, "The timestamp indicating when the file system shortcut was created. Format: YYYY-MM-DDTHH:MM:SSZ."],  # noqa: E501
    file_system_path: Annotated[str, "The file system path where the shortcut will point to. This should specify the environment-specific directory."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project to access. Obtain it via a call to /api/projects/."],  # noqa: E501
    shortcut_identifier: Annotated[str, "A unique identifier for the filesystem shortcut to be created. Used to distinguish this shortcut."],  # noqa: E501
    reference_name: Annotated[str | None, "A string representing the reference name for the file system shortcut. Use a unique identifier or description that aids in shortcut identification."] = None,  # noqa: E501
    shortcut_type: Annotated[str | None, "Specify the type of shortcut to create, such as \"folder\" or \"file\"."] = None,  # noqa: E501
    target_href: Annotated[str | None, "The URL or path to which the file system shortcut will point. This should be a valid string representing the reference destination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_shortcut_create'."]:  # noqa: E501
    """Create a file system shortcut for a project environment.

    This tool allows you to create a file system shortcut in a specified environment for a project in Datadog. Use it to quickly set up shortcuts for accessing environment-specific directories."""  # noqa: E501
    request_data: Any = {"id": shortcut_identifier, "path": file_system_path, "type": shortcut_type, "ref": reference_name, "href": target_href, "created_at": creation_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system_shortcut/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_file_system_shortcut(
    context: ToolContext,
    file_system_shortcut_id: Annotated[str, "A UUID string identifying the specific file system shortcut to retrieve details for."],  # noqa: E501
    project_identifier: Annotated[str, "The unique Project ID needed to access the specific project. Obtain this by querying /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_shortcut_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific file system shortcut.

    This tool fetches details about a specific file system shortcut using the provided project ID and shortcut ID. It should be called when you need information about a particular file system shortcut in a project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_shortcut_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_env_file_system_shortcut(
    context: ToolContext,
    creation_timestamp: Annotated[str, "The timestamp when the shortcut was created. Format: ISO 8601 string."],  # noqa: E501
    file_system_path: Annotated[str, "The path of the file system shortcut to update. Specify the full directory path as a string."],  # noqa: E501
    file_system_shortcut_id: Annotated[str, "A UUID string identifying the file system shortcut to be updated."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    shortcut_id: Annotated[str, "Unique identifier of the file system shortcut to update in the specified environment."],  # noqa: E501
    reference_identifier: Annotated[str | None, "The reference identifier for the file system shortcut to be updated."] = None,  # noqa: E501
    shortcut_href: Annotated[str | None, "The URL or URI of the file system shortcut to update."] = None,  # noqa: E501
    shortcut_type: Annotated[str | None, "Specifies the type of the file system shortcut to be updated, such as 'document' or 'folder'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_shortcut_update'."]:  # noqa: E501
    """Updates a file system shortcut in a specified environment.

    Use this tool to update the file system shortcut for a given environment by specifying the project and shortcut IDs."""  # noqa: E501
    request_data: Any = {"id": shortcut_id, "path": file_system_path, "type": shortcut_type, "ref": reference_identifier, "href": shortcut_href, "created_at": creation_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=shortcut_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_env_file_system_shortcut(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Retrieve it via a call to /api/projects/."],  # noqa: E501
    created_at_timestamp: Annotated[str | None, "The timestamp of when the file system shortcut was created, in ISO 8601 format."] = None,  # noqa: E501
    file_system_shortcut_id: Annotated[str | None, "Unique identifier for the file system shortcut to be updated."] = None,  # noqa: E501
    file_system_shortcut_type: Annotated[str | None, "Specifies the type of the file system shortcut to update, such as 'symlink' or 'hardlink'."] = None,  # noqa: E501
    reference_identifier: Annotated[str | None, "A unique string identifier for the file system shortcut to be updated."] = None,  # noqa: E501
    shortcut_file_path: Annotated[str | None, "The path to the file system shortcut that needs to be updated in the environment."] = None,  # noqa: E501
    shortcut_href: Annotated[str | None, "The URL or link to the file system shortcut that needs updating. This should be a valid URI."] = None,  # noqa: E501
    shortcut_id: Annotated[str | None, "A UUID string that uniquely identifies the file system shortcut to update."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_shortcut_partial_update'."]:  # noqa: E501
    """Update a file system shortcut in a specific environment.

    This tool updates a file system shortcut for a specific project environment based on given identifiers. Call this tool when you need to modify details of an existing file system shortcut within an environment."""  # noqa: E501
    request_data: Any = {"id": file_system_shortcut_id, "path": shortcut_file_path, "type": file_system_shortcut_type, "ref": reference_identifier, "href": shortcut_href, "created_at": created_at_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_shortcut_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_file_system_shortcut(
    context: ToolContext,
    file_system_shortcut_id: Annotated[str, "The UUID string that uniquely identifies the file system shortcut to be deleted."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project you wish to access. Retrieve this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_file_system_shortcut_destroy'."]:  # noqa: E501
    """Deletes a file system shortcut in an environment.

    Use this tool to delete a specified file system shortcut within a given project environment. It is called when a shortcut needs to be removed from the environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_shortcut_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_groups(
    context: ToolContext,
    group_type_index: Annotated[int, "The index representing the specific group type to list. Use this to filter groups by type."],  # noqa: E501
    project_id: Annotated[str, "ID of the project to access. Retrieve the ID from the /api/projects/ endpoint."],  # noqa: E501
    search_group_name: Annotated[str, "Search term for the group name to filter results."],
    pagination_cursor: Annotated[str | None, "The pagination cursor value to navigate through the paginated list of environment groups."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_list'."]:
    """Retrieve all groups for a specific environment's group type.

    Use this tool to list all groups of a given group type within a specific environment. Ensure to specify the group type index to get the desired data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"cursor": pagination_cursor, "group_type_index": group_type_index, "search": search_group_name}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_group(
    context: ToolContext,
    environment_group_key: Annotated[str, "A string identifier for the environment group. It must be unique within the project."],  # noqa: E501
    group_type_index: Annotated[int, "An integer representing the index of the group type to be created within the project. Ensure it matches the available types for grouping."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project to access. Retrieve using /api/projects/."],  # noqa: E501
    environment_group_properties: Annotated[str | None, "A JSON string containing key-value pairs for the properties of the environment group. Define attributes like settings and configurations relevant to the group."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_create'."]:
    """Create a new environment group in a project.

    Use this tool to create a new environment group within a specified project. Suitable for managing and organizing environment settings in Datadog."""  # noqa: E501
    request_data: Any = {"group_type_index": group_type_index, "group_key": environment_group_key, "group_properties": environment_group_properties}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_group_activity(
    context: ToolContext,
    group_type_index: Annotated[int, "An integer that specifies the type of group to find within the environment."],  # noqa: E501
    project_id: Annotated[str, "Project ID required to access activity data for the specified environment group. Obtain this ID by making a call to /api/projects/."],  # noqa: E501
    user_id_for_group_retrieval: Annotated[str, "Specify the user ID to retrieve group activities for within a project."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_activity_retrieve'."]:  # noqa: E501
    """Retrieve activity data for groups within an environment.

    Use this tool to access activity details for groups within a specific environment by providing the project ID. Ideal for monitoring or analyzing environment group activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"group_type_index": group_type_index, "id": user_id_for_group_retrieval}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_group_property(
    context: ToolContext,
    creation_date: Annotated[str, "The date when the property was created, in ISO 8601 format."],
    environment_group_type_index: Annotated[int, "An integer representing the group type index to identify the environment group."],  # noqa: E501
    group_key: Annotated[str, "Specify the key of the environment group you want to target for property deletion."],  # noqa: E501
    group_key_for_deletion: Annotated[str, "The key of the property to delete from the environment group."],  # noqa: E501
    group_type_index: Annotated[int, "Specify the group type index to identify which group to delete the property from. This should be an integer value."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project. Obtain it by calling /api/projects/."],  # noqa: E501
    group_properties_to_delete: Annotated[str | None, "A comma-separated list of property names you want to delete from the environment group."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_delete_property_create'."]:  # noqa: E501
    """Deletes a property from an environment group.

    This tool is used to delete a specific property from an environment group in a project. It should be called when you need to remove such properties from environment groups within Datadog."""  # noqa: E501
    request_data: Any = {"group_type_index": environment_group_type_index, "group_key": group_key_for_deletion, "group_properties": group_properties_to_delete, "created_at": creation_date}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/delete_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({"group_key": group_key_for_deletion, "group_type_index": environment_group_type_index}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def find_environment_groups(
    context: ToolContext,
    environment_group_key: Annotated[str, "Specify the key of the environment group you want to find within the project."],  # noqa: E501
    group_type_to_find: Annotated[int, "Specify the type of environment group to find. This is represented as an integer value that corresponds to a specific group type within the project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Call /api/projects/ to find the project ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_find_retrieve'."]:  # noqa: E501
    """Retrieve details of environment groups by project ID.

    Use this tool to fetch detailed information about environment groups within a specified project in Datadog. It is useful for monitoring and managing distinct environments in a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/find/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"group_key": environment_group_key, "group_type_index": group_type_to_find}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_property_definitions(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID for accessing environment groups. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_property_definitions_retrieve'."]:  # noqa: E501
    """Retrieve property definitions for environment groups.

    Use this tool to get property definitions for environment groups in your project, identified by project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/property_definitions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_property_values(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project to access. Retrieve this ID via a call to the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_property_values_retrieve'."]:  # noqa: E501
    """Retrieve property values of environments within a project.

    This tool retrieves property values for environment groups within a specified project. It is useful when you need to access configuration or metadata associated with environments in a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/property_values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_related_environment_groups(
    context: ToolContext,
    group_type_identifier: Annotated[int, "An integer representing the specific group type to locate within the environment groups."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access related environment groups. Obtainable via a call to /api/projects/."],  # noqa: E501
    user_id_for_group_search: Annotated[str, "The ID of the user for whom you want to find related groups. This helps in retrieving specific group associations for the given user."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_related_retrieve'."]:  # noqa: E501
    """Retrieve related environment groups for a project.

    Use this tool to obtain information about environment groups that are related to a specified project. This can be useful for understanding the interconnections and dependencies within an environment setup."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/related/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"group_type_index": group_type_identifier, "id": user_id_for_group_search}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_group_property(
    context: ToolContext,
    creation_timestamp: Annotated[str, "The date and time when the property was created, in ISO 8601 format (e.g., '2023-10-05T14:48:00Z')."],  # noqa: E501
    environment_group_key: Annotated[str, "A unique identifier for the environment group whose property is being updated."],  # noqa: E501
    group_key: Annotated[str, "Specify the key of the group to locate within the project for updating properties."],  # noqa: E501
    group_type_identifier: Annotated[int, "A unique integer representing the type of environment group to locate and update."],  # noqa: E501
    group_type_index_identifier: Annotated[int, "The integer index identifying the type of the environment group to be updated. Ensure it corresponds to the correct group type required for the operation."],  # noqa: E501
    project_id: Annotated[str, "The unique Project ID for accessing specific project resources. Retrieve this ID by making a call to /api/projects/."],  # noqa: E501
    group_properties: Annotated[str | None, "A JSON string representing the properties to update in the environment group."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_groups_update_property_create'."]:  # noqa: E501
    """Update a property of an environment group.

    This tool updates a specific property within a group of environments in a project. It should be called when there's a need to change configuration or settings for environment groups."""  # noqa: E501
    request_data: Any = {"group_type_index": group_type_index_identifier, "group_key": environment_group_key, "group_properties": group_properties, "created_at": creation_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/groups/update_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({"group_key": environment_group_key, "group_type_index": group_type_index_identifier}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_hog_functions(
    context: ToolContext,
    project_identifier: Annotated[str, "The Project ID to access the specific project. Use /api/projects/ to find the ID."],  # noqa: E501
    created_at: Annotated[str | None, "The creation date of the hog function. Expected in ISO 8601 format (e.g., 2023-10-11T15:00:00Z)."] = None,  # noqa: E501
    created_by_user_id: Annotated[int | None, "The user ID of the person who created the hog functions."] = None,  # noqa: E501
    function_id: Annotated[str | None, "The unique identifier for the hog function to be retrieved. Specify this to get details of a specific function."] = None,  # noqa: E501
    function_types: Annotated[list[str] | None, "Specify one or more hog function types to filter by, separated by commas."] = None,  # noqa: E501
    include_enabled_functions: Annotated[bool | None, "If set to true, returns only enabled hog functions; otherwise, returns all functions."] = None,  # noqa: E501
    results_offset: Annotated[int | None, "The initial index from which to return the results for paginated data."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page for the hog functions list."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A string used to search and filter the list of hog functions."] = None,  # noqa: E501
    update_timestamp: Annotated[str | None, "A timestamp indicating the last update time of the hog function. Use format YYYY-MM-DDTHH:MM:SSZ."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_list'."]:
    """Retrieve a list of hog functions for a given project.

    This tool retrieves a list of hog functions associated with a specified project. It should be called when there is a need to track or analyze file system views related to the project's hog functions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"created_at": created_at, "created_by": created_by_user_id, "enabled": include_enabled_functions, "id": function_id, "limit": results_per_page, "offset": results_offset, "search": search_term, "type": function_types, "updated_at": update_timestamp}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_hog_function_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Call /api/projects/ to retrieve project IDs if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_create'."]:  # noqa: E501
    """Track and create a new file system view in an environment.

    This tool is used to create a new 'hog function' environment, which involves logging each GET request on the resource to track file system views. It should be called when there is a need to initialize or track views within a project environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_hog_function_views(
    context: ToolContext,
    hog_function_uuid: Annotated[str, "A UUID string to identify the specific hog function for view tracking."],  # noqa: E501
    target_project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_retrieve'."]:  # noqa: E501
    """Tracks views on a specific hog function by logging access.

    Use this tool to track access and log views on a specific hog function within a given project. Each call logs a new view entry."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_hog_functions(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_uuid: Annotated[str | None, "A UUID string identifying this hog function to update and log views.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access. Retrieve it using a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_update'."]:  # noqa: E501
    """Update and log views of file system resources.

    This tool updates hog functions for a given project and logs each GET request as a new view. Use this tool to track changes and log views on file system resources within specified environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_uuid:
        missing_params.append(("hog_function_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_hog_function_view_log(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_uuid: Annotated[str | None, "A UUID string identifying the hog function to log a view for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_partial_update'."]:  # noqa: E501
    """Log a new view for an environment's hog function.

    Use this tool to track and log a new view on a specified hog function in Datadog environments. It should be called whenever a GET request to the resource logs a new view.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWLOG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_uuid:
        missing_params.append(("hog_function_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWLOG"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWLOG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWLOG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_hog_function(
    context: ToolContext,
    hog_function_id: Annotated[str, "A UUID string identifying the specific hog function to mark as deleted."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project to access. To find it, make a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_destroy'."]:  # noqa: E501
    """Marks a hog function as deleted in a project.

    Use this tool to mark a hog function as deleted by setting its \"deleted\" flag to true for a specific project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_hog_function_broadcast(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_id: Annotated[str | None, "A UUID string identifying the hog function for broadcast creation.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "String representing the ID of the project to access. Obtain the ID via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_broadcast_create'."]:  # noqa: E501
    """Create a broadcast for hog functions in an environment.

    This tool is used to create a broadcast for hog functions within a specified environment in Datadog. Call this tool when you need to track file system views by logging a new view with each GET request on the resource.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONBROADCAST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_id:
        missing_params.append(("hog_function_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONBROADCAST"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONBROADCAST"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/broadcast/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTIONBROADCAST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_hog_function_invocation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_id: Annotated[str | None, "A UUID string identifying the hog function to track in the specified project environment.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Call /api/projects/ to retrieve the ID if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_invocations_create'."]:  # noqa: E501
    """Track and log hog function invocations in a project.

    Use this tool to track and log each invocation of a hog function within a specified project environment. This is useful for monitoring and analyzing function usage.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["TRACKHOGFUNCTIONINVOCATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_id:
        missing_params.append(("hog_function_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["TRACKHOGFUNCTIONINVOCATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["TRACKHOGFUNCTIONINVOCATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/invocations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["TRACKHOGFUNCTIONINVOCATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_hog_function_logs(
    context: ToolContext,
    hog_function_uuid: Annotated[str, "A UUID string identifying the specific hog function to retrieve logs for."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_logs_retrieve'."]:  # noqa: E501
    """Retrieve logs for hog function views in an environment.

    Fetches logs related to views of a specific hog function within a project environment. It should be called to track file system views for specified functions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_hog_function_metrics(
    context: ToolContext,
    hog_function_uuid: Annotated[str, "A UUID string identifying the specific hog function for which metrics are being retrieved."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID of the target project. Retrieve via /api/projects/ if unknown."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_metrics_retrieve'."]:  # noqa: E501
    """Retrieve hog function metrics for a specific environment.

    Use this tool to obtain metrics related to hog functions in a specified environment. It tracks and logs each GET request as a new view, providing insights into the file system's operation within the environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_hog_function_metrics_totals(
    context: ToolContext,
    hog_function_uuid: Annotated[str, "A UUID string identifying the specific HOG function for which to retrieve metrics."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_metrics_totals_retrieve'."]:  # noqa: E501
    """Retrieve total metrics for a specific HOG function.

    Use this tool to obtain total metrics data for a specified HOG function within a project environment. Useful for tracking metrics related to file system views."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/{id}/metrics/totals/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_hog_function_icon(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_icon_retrieve'."]:  # noqa: E501
    """Retrieve the icon for a specified hog function view access.

    This tool retrieves the icon associated with a particular hog function under a specified project in Datadog. It should be called when you need to access or display the hog function's icon for a given project ID. Each access is logged as a view."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/icon/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_hog_function_icons(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the correct ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_icons_retrieve'."]:  # noqa: E501
    """Logs and retrieves hog function icons for a given environment.

    Use this tool to log a view and retrieve icons of hog functions for a specific environment using the project ID. It is useful for tracking and managing file system views associated with different environments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/icons/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_hog_functions_order(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project whose HogFunctions you want to rearrange. Use /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_hog_functions_rearrange_partial_update'."]:  # noqa: E501
    """Update the execution order of HogFunctions.

    Use this tool to change the sequence in which multiple HogFunctions are executed within a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONSORDER"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONSORDER"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONSORDER"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/hog_functions/rearrange/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONSORDER"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environment_insights(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the correct ID."],  # noqa: E501
    created_by_user_id: Annotated[int | None, "The user ID of who created the insight. Expected as an integer."] = None,  # noqa: E501
    initial_result_index: Annotated[int | None, "The initial index from which to start returning results."] = None,  # noqa: E501
    refresh_method: Annotated[str | None, "Strategy for refreshing insights, with options for cache use and sync/async execution. Choices include: 'force_cache', 'blocking', 'async', 'lazy_async', 'force_blocking', and 'force_async'."] = "force_cache",  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the retrieved insights (csv or json)."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page for pagination."] = None,  # noqa: E501
    return_basic_insight_metadata_only: Annotated[bool | None, "Set to true to return only basic metadata without results for faster response."] = None,  # noqa: E501
    short_identifier: Annotated[str | None, "The short identifier for the environment to retrieve insights for. This is unique per environment."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_list'."]:
    """Retrieve insights for a specific environment.

    Use this tool to get insights for a specified environment within a given project. It logs each view upon retrieval."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"basic": return_basic_insight_metadata_only, "created_by": created_by_user_id, "format": response_format, "limit": results_per_page, "offset": initial_result_index, "refresh": refresh_method, "short_id": short_identifier}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_insight(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID to access the specific project. Retrieve using /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the format of the output data. Accepted values are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_create'."]:
    """Create a new insight for an environment.

    Use this tool to add a new insight for a specified environment within a project. It logs a new view each time it is called and is useful for tracking file system views in your projects.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINSIGHT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINSIGHT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINSIGHT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINSIGHT"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_insights(
    context: ToolContext,
    insight_id: Annotated[int, "The identifier for the specific insight. Provide as an integer to specify which insight's sharing details to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "Unique identifier for the project to access. Retrieve via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_sharing_list'."]:  # noqa: E501
    """Retrieve sharing details of environment insights.

    Fetches the sharing details of insights related to specific environments using the provided project and insight IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{insight_id}/sharing/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_sharing_password(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_identifier: Annotated[int | None, "The unique integer ID of the insight for which you want to create a sharing password.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_sharing_passwords_create'."]:  # noqa: E501
    """Create a new password for sharing configuration.

    Use this tool to create a new password for the sharing configuration of a specific insight within a project environment on Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATESHARINGPASSWORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_identifier:
        missing_params.append(("insight_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATESHARINGPASSWORD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATESHARINGPASSWORD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{insight_id}/sharing/passwords/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATESHARINGPASSWORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_insight_sharing_password(
    context: ToolContext,
    insight_identifier: Annotated[int, "The unique integer ID of the insight whose sharing password you want to delete."],  # noqa: E501
    password_identifier: Annotated[str, "The unique identifier of the password to be deleted from the sharing configuration."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project you wish to access. Obtain this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_sharing_passwords_destroy'."]:  # noqa: E501
    """Delete a password from an insight's sharing configuration.

    Use this tool to delete a password associated with an insight's sharing configuration in a specific environment. This is useful for managing access to shared insights by ensuring only the desired passwords remain active."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{insight_id}/sharing/passwords/{password_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_identifier, password_id=password_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def refresh_insights_sharing(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_id: Annotated[int | None, "The ID of the insight you want to refresh sharing for. This should be an integer.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Use /api/projects/ to find the project ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_sharing_refresh_create'."]:  # noqa: E501
    """Refresh sharing status of insights in a project.

    This tool is used to refresh the sharing status of insights within a specific project on Datadog. Ideal for when updates or changes need to be made visible to shared environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSSHARING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_id:
        missing_params.append(("insight_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSSHARING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSSHARING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{insight_id}/sharing/refresh/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSSHARING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_environment_insights(
    context: ToolContext,
    insight_identifier: Annotated[int, "A unique integer identifying the specific insight to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    dashboard_id_context: Annotated[int | None, "The ID of the dashboard to apply its filters and date range if loading insight in the context of a dashboard."] = None,  # noqa: E501
    insight_refresh_strategy: Annotated[str | None, "Determines how to refresh the insight: choose from 'force_cache', 'blocking', 'async', 'lazy_async', 'force_blocking', or 'force_async'. Dictates calculation synchronization and use of cache."] = "force_cache",  # noqa: E501
    output_format: Annotated[str | None, "Specify the format for the output data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_retrieve'."]:
    """Retrieve insights for a specific environment.

    This tool is used to retrieve insights data for a specified environment within a project. It should be called when detailed information about an environment's insights is needed."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format, "from_dashboard": dashboard_id_context, "refresh": insight_refresh_strategy}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_insights(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_identifier: Annotated[int | None, "A unique integer identifying the specific insight to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique string ID of the project to access. Obtainable via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the format for the response data. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_update'."]:
    """Update insights for a specified environment.

    Used to update tracking information for file system views in a specified environment. Each update logs a new view for the resource.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_identifier:
        missing_params.append(("insight_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTS"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_insights_log(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_identifier: Annotated[int | None, "A unique integer identifying the environment insight to log.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The Project ID needed to access the desired environment insights. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the format of the data to be returned. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_partial_update'."]:  # noqa: E501
    """Log a view of environment insights to track changes.

    Call this tool to log a view of the environment insights for tracking file system changes. Each call logs a new view, helping in monitoring updates to environment insights.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTSLOG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_identifier:
        missing_params.append(("insight_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTSLOG"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTSLOG"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTINSIGHTSLOG"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_insight(
    context: ToolContext,
    insight_id: Annotated[int, "A unique integer value identifying the environment insight to be marked as deleted."],  # noqa: E501
    project_identification: Annotated[str, "The ID of the project to access. Obtain by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the response format for the deletion confirmation, either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_destroy'."]:
    """Marks an environment insight as deleted.

    Use this tool to mark an environment insight as deleted by setting its 'deleted' status to true. This action does not hard delete the record, but flags it as deleted."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_identification),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_insight_activity(
    context: ToolContext,
    insight_id: Annotated[int, "A unique integer identifying the specific insight to retrieve logs for."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access. Call /api/projects/ to retrieve it."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response. Allowed values are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_activity_retrieve_2'."]:  # noqa: E501
    """Retrieve logs of views on environment insights.

    This tool retrieves logs of views on environment insights for a specific project and insight ID. It should be called when there's a need to track or analyze access activities on environment insights."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_environment_insights(
    context: ToolContext,
    environment_project_id: Annotated[str, "Project ID for accessing environment insights. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the output format of the retrieved data. Accepts 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_activity_retrieve'."]:  # noqa: E501
    """Retrieve and log environment activity insights.

    This tool retrieves and logs insights on file system views for a specified environment. It should be called to obtain activity logs and understand usage patterns for a particular project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=environment_project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_insight_creation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the response format as either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_cancel_create'."]:  # noqa: E501
    """Cancel the creation of an environment insight.

    Use this tool to cancel an ongoing creation process for an environment insight in Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CANCELINSIGHTCREATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CANCELINSIGHTCREATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CANCELINSIGHTCREATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CANCELINSIGHTCREATION"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_last_viewed_insights(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access insights for. Use /api/projects/ to find the ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the returned data. Accepts 'csv' or 'json'. Defaults to 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_my_last_viewed_retrieve'."]:  # noqa: E501
    """Fetches the last 5 insights viewed, sorted by recency.

    This tool retrieves basic details about the last 5 insights viewed by the user, ordered with the most recent first. It is useful for accessing recent insights quickly."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/insights/my_last_viewed/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_insight_view_timestamps(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "Project ID to access. Retrieve this ID using the /api/projects/ endpoint if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the returned data. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_insights_viewed_create'."]:  # noqa: E501
    """Updates the view timestamps for specific insights.

    Use this tool to update the view timestamps for a list of insights identified by their IDs. This is useful for keeping track of which insights have been recently viewed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEINSIGHTVIEWTIMESTAMPS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEINSIGHTVIEWTIMESTAMPS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEINSIGHTVIEWTIMESTAMPS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/insights/viewed/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEINSIGHTVIEWTIMESTAMPS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_integrations(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID for accessing the desired project's environment. Obtain this ID by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page for the environment integrations list."] = None,  # noqa: E501
    starting_index: Annotated[int | None, "The initial index from which to return results, used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_list'."]:
    """Retrieve a list of integrations for a specified environment.

    Use this tool to get the integrations associated with a specific project environment in Datadog. Ideal for users looking to manage or view integrations for different environments within their projects."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_integration(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "Project ID needed to access the specific project. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_create'."]:  # noqa: E501
    """Create a new integration for a specified environment.

    This tool creates a new integration within a specified project environment on Datadog. Call this tool when you need to add integrations to enhance environment functionalities or connect with other services.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINTEGRATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINTEGRATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINTEGRATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTINTEGRATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_integration_details(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer value identifying the specific integration to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the specific environment. Retrieve it via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_retrieve'."]:  # noqa: E501
    """Retrieve integration details for a specific environment.

    Use this tool to fetch the details of a specific integration within a given environment in Datadog. It is useful for obtaining specific configuration and status information about an integration identified by its ID and project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_integration(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer representing the integration to be deleted."],
    project_identifier: Annotated[str, "The unique identifier for the project. Use an API call to /api/projects/ to retrieve this if unknown."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_destroy'."]:  # noqa: E501
    """Delete an integration from a project environment.

    Use this tool to delete a specific integration from a project environment in Datadog. Trigger it when an integration needs to be removed from a given project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_integration_channels(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the specific integration within Datadog."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project you want to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_channels_retrieve'."]:  # noqa: E501
    """Retrieve integration channels for a specific project.

    Use this tool to get a list of integration channels associated with a specific project within Datadog environments. Provide the project and integration IDs to retrieve the relevant information."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/channels/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_clickup_lists(
    context: ToolContext,
    integration_id: Annotated[int, "Unique integer identifying the specific integration."],
    project_id: Annotated[str, "The unique ID of the project you want to access. Retrieve it via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_clickup_lists_retrieve'."]:  # noqa: E501
    """Retrieve ClickUp lists for specific project integrations.

    Use this tool to fetch ClickUp lists linked to a given project's integrations. Ideal for obtaining detailed list information for environment integrations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/clickup_lists/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_clickup_spaces(
    context: ToolContext,
    integration_identifier: Annotated[int, "An integer value uniquely identifying the integration to retrieve ClickUp spaces for."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project to access specific ClickUp spaces. Obtain this ID via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_clickup_spaces_retrieve'."]:  # noqa: E501
    """Retrieve ClickUp spaces for a specific integration.

    Use this tool to retrieve ClickUp spaces linked to a specific integration within a project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/clickup_spaces/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_clickup_workspaces(
    context: ToolContext,
    clickup_project_id: Annotated[str, "The Project ID for accessing the desired ClickUp workspace. Obtain the ID by calling /api/projects/."],  # noqa: E501
    integration_id: Annotated[int, "A unique integer value identifying the integration to retrieve workspaces for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_clickup_workspaces_retrieve'."]:  # noqa: E501
    """Retrieve ClickUp workspaces for a specific integration.

    Use this tool to get the list of ClickUp workspaces associated with a specific integration in Datadog environments. It requires specifying the project and integration identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/clickup_workspaces/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=clickup_project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def verify_email_integration(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    integration_id: Annotated[int | None, "A unique integer value identifying this integration within the environment.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID for which you want to verify the email integration. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_email_verify_create'."]:  # noqa: E501
    """Verify email address for an integration's environment.

    This tool is used to confirm the email address for a specific integration within an environment. It should be called when you need to verify that the email address associated with an integration is valid and active.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["VERIFYEMAILINTEGRATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not integration_id:
        missing_params.append(("integration_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["VERIFYEMAILINTEGRATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["VERIFYEMAILINTEGRATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/email/verify/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["VERIFYEMAILINTEGRATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_github_repos_for_integration(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the specific integration within Datadog."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access. Obtain the project ID using the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_github_repos_retrieve'."]:  # noqa: E501
    """Retrieve GitHub repositories linked to a Datadog integration.

    Use this tool to get a list of GitHub repositories associated with a specific integration in a Datadog environment. It requires the project ID and integration ID to identify the specific environment and integration."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/github_repos/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_google_accessible_accounts(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the integration."],
    project_id: Annotated[str, "Project ID to access specific Google accounts. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_google_accessible_accounts_retrieve'."]:  # noqa: E501
    """Retrieve Google accessible accounts for a given integration.

    Use this tool to get a list of Google accessible accounts linked to a specific integration within a project environment. Call this when needing information about which Google accounts are accessible via the specified integration."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/google_accessible_accounts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_google_conversion_actions(
    context: ToolContext,
    integration_identifier: Annotated[int, "A unique integer identifying the integration."],
    project_id: Annotated[str, "The ID of the project you want to access. Obtain this from /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_google_conversion_actions_retrieve'."]:  # noqa: E501
    """Retrieve Google conversion actions for a specific environment.

    Call this tool to obtain information about Google conversion actions associated with a particular environment and integration in a project. Useful for analytics and tracking setup verification."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/google_conversion_actions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_integration_teams(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the integration to retrieve team details."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Find this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_linear_teams_retrieve'."]:  # noqa: E501
    """Retrieve linear teams for an integration in a project.

    This tool fetches information about linear teams associated with a specific integration within a given project's environment. It is useful for getting insight into team configurations and integration details."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/linear_teams/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_linkedin_ads_accounts(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer to identify the LinkedIn Ads integration within Datadog."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access LinkedIn Ads accounts. Retrieve this ID via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_linkedin_ads_accounts_retrieve'."]:  # noqa: E501
    """Retrieve LinkedIn Ads accounts linked to a project.

    Use this tool to get LinkedIn Ads accounts associated with a specific project and integration in your Datadog environment. Ideal for when you need to verify LinkedIn Ads account details or ensure correct account linkage."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/linkedin_ads_accounts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_linkedin_ads_conversion_rules(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the LinkedIn Ads integration to retrieve conversion rules for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project for which you want to retrieve LinkedIn Ads conversion rules. Obtain this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_linkedin_ads_conversion_rules_retrieve'."]:  # noqa: E501
    """Retrieve LinkedIn Ads conversion rules for a project.

    Use this tool to get the LinkedIn Ads conversion rules associated with a specific project in Datadog. It should be called when you need information about conversion rules linked to your LinkedIn Ads integrations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/linkedin_ads_conversion_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_twilio_phone_numbers(
    context: ToolContext,
    integration_identifier: Annotated[int, "A unique integer value identifying the Twilio integration for which phone numbers should be retrieved."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Use /api/projects/ to retrieve the ID if needed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_twilio_phone_numbers_retrieve'."]:  # noqa: E501
    """Retrieve Twilio phone numbers for a specific integration.

    Use this tool to fetch all Twilio phone numbers associated with a particular integration within a project environment. Useful for monitoring or managing communication channels."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/{id}/twilio_phone_numbers/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_integration_authorization(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project you want to access. Obtain the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_integrations_authorize_retrieve'."]:  # noqa: E501
    """Retrieve integration authorization status for a project.

    Use this tool to check the authorization status of integrations within a specified project environment. It helps verify if integrations are correctly authorized in the Datadog environment for the given project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/integrations/authorize/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_log_attributes(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project whose environment log attributes you want to retrieve. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_logs_attributes_retrieve'."]:  # noqa: E501
    """Retrieve log attributes for a specific environment.

    This tool fetches details about log attributes for a specific environment using a given project ID. It is used to gain insights into the log data of different environments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/logs/attributes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_logs_query_for_environment(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project being accessed. Use /api/projects/ to find it."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_logs_query_create'."]:
    """Create a logs query for a specific environment.

    This tool initiates a logs query for a specified environment within a project. It should be called when you need to analyze logs data from a particular environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/logs/query/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_log_sparkline(
    context: ToolContext,
    project_id_for_log_sparkline: Annotated[str, "The Project ID for accessing the environment logs in Datadog. Retrieve this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_logs_sparkline_create'."]:  # noqa: E501
    """Create a sparkline for environment logs in Datadog.

    This tool is used to create a sparkline visualization for logs in a specified environment within Datadog. It should be called when you need a graphical representation of log data for a particular project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/logs/sparkline/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_log_sparkline),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_logs_values(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_logs_values_retrieve'."]:  # noqa: E501
    """Fetch log values for a given environment and project.

    Call this tool to retrieve log values associated with a specific project environment using the provided project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/logs/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_max_tools_insight(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access to create the insight. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_max_tools_create_and_query_insight_create'."]:  # noqa: E501
    """Create an insight for maximum tools in a project.

    This tool creates an insight related to the maximum tools for a specified project within Datadog environments. It should be called when you need to generate insights for managing or analyzing tool usage limits."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/max_tools/create_and_query_insight/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_persisted_folders(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Obtain this by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page when retrieving folders."] = None,  # noqa: E501
    starting_index: Annotated[int | None, "The initial index from which to return the results, used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persisted_folder_list'."]:  # noqa: E501
    """Retrieve a list of persisted folders for a given environment.

    Use this tool to obtain all persisted folders within a specified project's environment. Suitable when you need to access or manage environment-specific folders."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persisted_folder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_persisted_folder(
    context: ToolContext,
    folder_creation_timestamp: Annotated[str, "Timestamp indicating when the folder was created. It should be in ISO 8601 format."],  # noqa: E501
    folder_id: Annotated[str, "A unique identifier for the persisted folder to be created in the environment."],  # noqa: E501
    folder_type: Annotated[str, "Specifies the type of the folder to create. Acceptable values are 'home' for Home directory and 'pinned' for Pinned directory."],  # noqa: E501
    folder_updated_at: Annotated[str, "Timestamp indicating when the folder was last updated."],
    project_identifier: Annotated[str, "The ID of the Datadog project for accessing a specific environment. Obtain this by calling /api/projects/."],  # noqa: E501
    folder_protocol: Annotated[str | None, "Specify the protocol for the persisted folder, typically as a string indicator."] = None,  # noqa: E501
    persisted_folder_path: Annotated[str | None, "Specify the path for the persisted folder in the Datadog environment. This should be a valid directory path within the project."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persisted_folder_create'."]:  # noqa: E501
    """Create a persisted folder in a Datadog environment.

    Use this tool to create a persistent storage folder within a specified Datadog project environment."""  # noqa: E501
    request_data: Any = {"id": folder_id, "type": folder_type, "protocol": folder_protocol, "path": persisted_folder_path, "created_at": folder_creation_timestamp, "updated_at": folder_updated_at}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persisted_folder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persisted_environment_folder(
    context: ToolContext,
    persisted_folder_id: Annotated[str, "A UUID string identifying the persisted folder to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the project related to the persisted folder. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persisted_folder_retrieve'."]:  # noqa: E501
    """Retrieve details of a persisted environment folder by ID.

    Use this tool to obtain information about a specific persisted folder within an environment, identified by its project ID and folder ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=persisted_folder_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_folder(
    context: ToolContext,
    folder_creation_date: Annotated[str, "The date and time when the folder was created, in ISO 8601 format (e.g., '2023-10-12T14:23:30Z')."],  # noqa: E501
    folder_id: Annotated[str, "The identifier for the folder to be updated in the environment."],
    folder_type: Annotated[str, "Specify the type of the folder: 'home' for Home, 'pinned' for Pinned."],  # noqa: E501
    folder_update_timestamp: Annotated[str, "Timestamp indicating when the folder was last updated. Expected in ISO 8601 format."],  # noqa: E501
    folder_uuid: Annotated[str, "A UUID string identifying the Persisted Folder to update."],
    project_identifier: Annotated[str, "String ID of the project to access. Retrieve by calling /api/projects/."],  # noqa: E501
    folder_path: Annotated[str | None, "The path of the folder within the environment project to update."] = None,  # noqa: E501
    folder_protocol_type: Annotated[str | None, "Specifies the protocol type for accessing the folder. Must be a string."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persisted_folder_update'."]:  # noqa: E501
    """Update a specific folder in an environment project.

    This tool updates the details of a persisted folder within a specified environment project. It should be called when modifications to folder settings or contents are needed in a given environment."""  # noqa: E501
    request_data: Any = {"id": folder_id, "type": folder_type, "protocol": folder_protocol_type, "path": folder_path, "created_at": folder_creation_date, "updated_at": folder_update_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=folder_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_env_folder(
    context: ToolContext,
    project_id: Annotated[str, "Provide the Project ID to access the specific environment. Retrieve it via /api/projects/."],  # noqa: E501
    environment_folder_creation_date: Annotated[str | None, "The creation date of the environment folder. Expected in YYYY-MM-DD format."] = None,  # noqa: E501
    environment_folder_id: Annotated[str | None, "The unique identifier for the environment folder to update. Provide a valid string ID."] = None,  # noqa: E501
    environment_folder_last_updated: Annotated[str | None, "The timestamp when the environment folder was last updated. Use ISO 8601 format."] = None,  # noqa: E501
    environment_folder_protocol: Annotated[str | None, "Specify the protocol type for the environment folder, such as 'home' or 'pinned'."] = None,  # noqa: E501
    folder_path: Annotated[str | None, "Specify the updated path for the environment folder."] = None,  # noqa: E501
    folder_type: Annotated[str | None, "Specify the type of the folder: `home` for Home or `pinned` for Pinned."] = None,  # noqa: E501
    persisted_folder_id: Annotated[str | None, "A UUID string that uniquely identifies the persisted folder to be updated."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persisted_folder_partial_update'."]:  # noqa: E501
    """Partially update a specific environment folder.

    Use this tool to partially update a specific persisted folder within an environment by providing the project and folder IDs."""  # noqa: E501
    request_data: Any = {"id": environment_folder_id, "type": folder_type, "protocol": environment_folder_protocol, "path": folder_path, "created_at": environment_folder_creation_date, "updated_at": environment_folder_last_updated}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_folder_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_persisted_folder(
    context: ToolContext,
    persisted_folder_uuid: Annotated[str, "A UUID identifying the persisted folder to be deleted."],
    project_id: Annotated[str, "The unique ID of the project where the folder resides. Retrieve this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persisted_folder_destroy'."]:  # noqa: E501
    """Delete a persisted folder from a project environment.

    This tool deletes a specified persisted folder within a project environment in Datadog. It should be called when a user wants to permanently remove a stored folder by specifying the project and folder IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=persisted_folder_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_person_details(
    context: ToolContext,
    person_id: Annotated[int, "Unique integer identifying the person to retrieve details for."],
    project_identifier: Annotated[str, "The ID of the project to retrieve the person's details. Obtainable via a call to /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format for the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_retrieve'."]:
    """Retrieve details of a specific person in a project.

    This tool calls the API to retrieve details about a person identified by their ID within a specific project environment. It is useful for fetching information about individuals to analyze or review their data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_person_properties(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_id: Annotated[int | None, "A unique integer identifier for the person whose properties are to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve using /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format for the endpoint response. Choose between 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_update'."]:
    """Update specific properties of a person in a project.

    Use this tool to update certain properties of a person within a project environment. It allows you to set only the specified properties without affecting others. To remove properties, use a different endpoint.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTIES"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_id:
        missing_params.append(("person_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTIES"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTIES"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTIES"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_persons_in_environment(
    context: ToolContext,
    project_id_of_target_environment: Annotated[str, "The Project ID for the environment you want to access. Find it with a call to /api/projects/."],  # noqa: E501
    distinct_ids_list: Annotated[list[str] | None, "List of unique identifiers for individuals to be updated or deleted. Each identifier should be a string."] = None,  # noqa: E501
    person_created_at: Annotated[str | None, "The timestamp of when the person was created, formatted as a string. This helps identify the creation date of the person within the system."] = None,  # noqa: E501
    person_id: Annotated[int | None, "The unique identifier for the person you want to update or delete. This is an integer value."] = None,  # noqa: E501
    person_identifier: Annotated[int | None, "A unique integer used to identify the person for modification or deletion."] = None,  # noqa: E501
    person_identifier_uuid: Annotated[str | None, "The unique identifier for the person whose data is to be updated or deleted. This UUID is required for the operation."] = None,  # noqa: E501
    person_name: Annotated[str | None, "The name of the person to modify. This is required for updating the person's information."] = None,  # noqa: E501
    person_properties: Annotated[str | None, "JSON string of properties and values to update for a person. This may include attributes like name, email, etc."] = None,  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response data. Acceptable values are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_partial_update'."]:  # noqa: E501
    """Modify or remove persons in a given environment.

    Use this tool to update or delete the information of persons within a specified environment using the project ID and person ID. For creating or further updating, the capture API or SDKs are recommended."""  # noqa: E501
    request_data: Any = {"id": person_id, "name": person_name, "distinct_ids": distinct_ids_list, "properties": person_properties, "created_at": person_created_at, "uuid": person_identifier_uuid}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id_of_target_environment),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_person_record(
    context: ToolContext,
    person_id: Annotated[int, "A unique integer value identifying the person to be deleted."],
    project_id: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
    delete_events_task: Annotated[bool | None, "If true, a task to delete all events associated with this person is created and queued, running every Sunday at 5 AM UTC."] = False,  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response, either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_destroy'."]:
    """Deletes an individual person record from a project.

    Use this tool to delete a specific person record from a project's environment. It is intended for individual deletions; for bulk actions, a different endpoint should be used."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"delete_events": delete_events_task, "format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_person_activity(
    context: ToolContext,
    person_id: Annotated[int, "A unique integer identifying the person whose activity you want to retrieve."],  # noqa: E501
    project_id: Annotated[str, "Project ID to access. Obtain by calling /api/projects/."],
    output_format: Annotated[str | None, "Specify the output format for the data, either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_activity_retrieve_2'."]:  # noqa: E501
    """Retrieve a person's activity from the environment.

    Use this tool to obtain information about a person's activity in a specific project environment by specifying the project and person IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def queue_person_events_deletion(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_identifier: Annotated[int | None, "A unique integer identifying the person whose events are to be deleted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID needed to access the specific project. Obtainable via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    events_export_format: Annotated[str | None, "The format in which to export events before deletion. Acceptable values are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_delete_events_create'."]:  # noqa: E501
    """Queue the deletion of all events for a specific person.

    This tool queues the deletion of all events associated with a specified person in a project. The deletion is scheduled to occur during non-peak hours, making it efficient for managing resources.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTSDELETION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTSDELETION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTSDELETION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/delete_events/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTSDELETION"],
        params=remove_none_values({"format": events_export_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_person_property(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    property_key_to_delete: Annotated[str | None, "Specify the property key of the person to delete.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    person_identifier: Annotated[int | None, "A unique integer identifier for the person whose property is to be deleted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to retrieve this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_delete_property_create'."]:  # noqa: E501
    """Deletes a specific property from a person.

    Use this tool to remove a property from a user in a specified project environment. It is designed for deleting attributes associated with a person. For creating or updating person properties, refer to the capture API.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DELETEPERSONPROPERTY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not property_key_to_delete:
        missing_params.append(("property_key_to_delete", "query"))
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DELETEPERSONPROPERTY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DELETEPERSONPROPERTY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/delete_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DELETEPERSONPROPERTY"],
        params=remove_none_values({"$unset": property_key_to_delete, "format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_person_recordings(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_id: Annotated[int | None, "A unique integer identifier for the person whose recordings should be deleted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project for which you want to queue recording deletions. Obtainable via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format for the response, either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_delete_recordings_create'."]:  # noqa: E501
    """Queue deletion of all recordings associated with a person.

    Use this tool to queue the deletion of all recordings related to a specific person in a project environment. This is useful when recordings need to be removed in batch for compliance or cleanup purposes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DELETEPERSONRECORDINGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_id:
        missing_params.append(("person_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DELETEPERSONRECORDINGS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DELETEPERSONRECORDINGS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/delete_recordings/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DELETEPERSONRECORDINGS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_person_property_timeline(
    context: ToolContext,
    person_identifier: Annotated[int, "Unique integer value for identifying the person."],
    project_id: Annotated[str, "The ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the format of the data to be retrieved. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_properties_timeline_retrieve'."]:  # noqa: E501
    """Retrieve timeline of property changes for a person.

    Use this tool to obtain the timeline of changes to a person's properties in a specified environment. Useful for tracking modifications over time."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/properties_timeline/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def read_or_delete_person(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_id: Annotated[int | None, "Unique integer identifier for the person to read or delete.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Unique identifier for the project to access. Retrieve via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the format of the response. Choose between 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_split_create'."]:  # noqa: E501
    """Read or delete a person's record in the environment.

    Use this tool to read or delete a person's record within a specific environment by providing the project and person ID. For creating or updating, refer to the capture API or SDKs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["READORDELETEPERSON"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_id:
        missing_params.append(("person_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["READORDELETEPERSON"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["READORDELETEPERSON"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/split/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["READORDELETEPERSON"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_person_property(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    property_key: Annotated[str | None, "The key of the property you want to update for a person.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    property_value: Annotated[str | None, "Specify the value for the property to update for a person.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    person_identifier: Annotated[int | None, "Unique identifier for the person. Use an integer value to specify the person whose property you wish to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Specify the ID of the project you wish to access. Retrieve the project ID via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "The format in which the response is returned. Choose either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_update_property_create'."]:  # noqa: E501
    """Update a specific property for a person in an environment.

    Use this tool to update a property for a person within a specified project environment. Ideal for when adjustments to a person's attributes are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not property_key:
        missing_params.append(("property_key", "query"))
    if not property_value:
        missing_params.append(("property_value", "query"))
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/{id}/update_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPERSONPROPERTY"],
        params=remove_none_values({"format": output_format, "key": property_key, "value": property_value}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_persons_activity(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project to access. Use /api/projects/ to find the ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response data. Choose either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_activity_retrieve'."]:  # noqa: E501
    """Retrieve activity data for persons in a project environment.

    Use this tool to read activity data for persons in a specific project environment. Suitable for obtaining detailed insights on user actions and behaviors."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def bulk_delete_persons_in_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    target_project_id: Annotated[str | None, "The ID of the project you wish to access for this operation. Retrieve it using the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    distinct_ids_to_delete: Annotated[dict[str, str] | None, "Provide a list of up to 1000 distinct IDs to delete all associated persons.  Only used when mode is 'execute'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the API response, either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    posthog_person_ids: Annotated[dict[str, str] | None, "A list of up to 1000 PostHog person IDs to delete from the environment.  Only used when mode is 'execute'."] = None,  # noqa: E501

    delete_events: Annotated[bool | None, "If true, a task to delete all events related to this person will be created and queued, executing at 5AM UTC every Sunday.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_bulk_delete_create'."]:  # noqa: E501
    """Bulk delete persons by IDs in a Datadog environment.

    Use this tool to remove multiple persons from a Datadog environment by providing up to 1000 PostHog person IDs or distinct IDs. Useful for managing large datasets efficiently.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["BULKDELETEPERSONSINENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["BULKDELETEPERSONSINENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["BULKDELETEPERSONSINENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/bulk_delete/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["BULKDELETEPERSONSINENVIRONMENT"],
        params=remove_none_values({"delete_events": delete_events, "distinct_ids": distinct_ids_to_delete, "format": response_format, "ids": posthog_person_ids}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_cohorts(
    context: ToolContext,
    project_id: Annotated[str, "Project ID for accessing the specified cohort data. Obtain this by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response. Supported values are 'csv' and 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_cohorts_retrieve'."]:  # noqa: E501
    """Retrieve persons cohort data from specified environments.

    This tool retrieves persons cohort data from a specified environment using the project ID. It does not support creation or updating of persons, which should be done using the capture API or other SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/cohorts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_persons_funnel_data(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the format of the data output: 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_funnel_retrieve'."]:  # noqa: E501
    """Fetch persons data from the funnel in a specified environment.

    Use this tool to retrieve persons data related to funnels in a specific project environment. This is useful for analytics and understanding user behavior within the project. To modify or delete persons, refer to relevant APIs or SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/funnel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_persons_funnel(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    target_project_id: Annotated[str | None, "The ID of the project you want to access. Obtain it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the output format for the funnel creation. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_funnel_create'."]:  # noqa: E501
    """Create a funnel for tracking persons.

    Use this tool to create a funnel for tracking persons within a specific project environment. For updating existing persons, consider using the capture API or relevant SDKs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNEL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNEL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNEL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/funnel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNEL"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_funnel_correlation(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve using /api/projects/."],
    response_format: Annotated[str | None, "Specifies the format of the response. Acceptable values are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_funnel_correlation_retrieve'."]:  # noqa: E501
    """Retrieve persons related to funnel correlation in an environment.

    Use this tool to access information about persons in relation to funnel correlations within a specified project environment. Ideal for analyzing user behavior and interactions concerning specific funnels."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/funnel/correlation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_persons_funnel_correlation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project to access. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specifies the output format of the response. Accepts 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_funnel_correlation_create'."]:  # noqa: E501
    """Create a funnel correlation for persons in a project.

    Use this tool to create a funnel correlation for persons within a specified project environment. This is ideal for tracking and analyzing how different user properties impact funnel performance.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNELCORRELATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNELCORRELATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNELCORRELATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/funnel/correlation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPERSONSFUNNELCORRELATION"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_lifecycle(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response data. Choose either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_lifecycle_retrieve'."]:  # noqa: E501
    """Retrieve lifecycle details of persons in a project.

    Use this tool to retrieve lifecycle information of persons within a specified project. This tool is for reading lifecycle data. For modifications, consider using other API options like the capture API, `$set`, `$unset`, or SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/lifecycle/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reset_distinct_id(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Retrieve this via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_reset_person_distinct_id_create'."]:  # noqa: E501
    """Reset a distinct_id for a deleted person.

    This tool resets a distinct_id for a person who has been deleted, allowing the distinct_id to be reused.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RESETDISTINCTID"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RESETDISTINCTID"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RESETDISTINCTID"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/persons/reset_person_distinct_id/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RESETDISTINCTID"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_person_stickiness(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique Project ID needed to access stickiness data. Obtainable via a call to /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response data. Available options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_stickiness_retrieve'."]:  # noqa: E501
    """Retrieve stickiness data for persons in a project environment.

    This tool retrieves data on the stickiness of persons within a specified project environment based on unique project identifiers. It is used for analyzing patterns of user engagement and retention."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/stickiness/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_trends(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access for retrieving person trends. Obtain this by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response: 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_trends_retrieve'."]:  # noqa: E501
    """Retrieve trends data for persons in a specified environment.

    Use this tool to obtain trends data related to persons within a given project environment. Ideal for reading current trends in person data for analysis. For creating or updating person data, refer to the capture API or SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/trends/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_data(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique Project ID required to access the specific environment. Obtainable via /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format in which the response should be returned. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_persons_values_retrieve'."]:  # noqa: E501
    """Retrieve information about persons in a specified environment.

    Use this tool to access data about persons within a specific project environment. It is intended for reading existing data. For creating or updating persons, refer to the CAPTURE API or SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/persons/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_plugin_logs(
    context: ToolContext,
    plugin_configuration_id: Annotated[str, "The identifier for the plugin configuration to retrieve logs for. Required to specify which plugin configuration's logs to access."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access logs for. Obtain this ID by calling /api/projects/."],  # noqa: E501
    results_offset_index: Annotated[int | None, "The starting index for the results to return from the API. Used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_plugin_configs_logs_list'."]:  # noqa: E501
    """Retrieve logs for a plugin configuration in a specific environment.

    Use this tool to obtain logs related to a particular plugin configuration within a specified environment. Useful for debugging or monitoring plugin activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/plugin_configs/{plugin_config_id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), plugin_config_id=plugin_configuration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_offset_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environment_query_results(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve it via a call to /api/projects/."],  # noqa: E501
    query_id: Annotated[str, "The ID of the specific query to retrieve results for within the project's environment."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_query_retrieve'."]:
    """Retrieve results of an environment query for a project.

    Fetch the results of a specific query within a project's environment using the project ID and query ID. This tool is ideal for retrieving data insights and analytics from environment queries."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/query/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_query(
    context: ToolContext,
    project_id_access: Annotated[str, "Specify the Project ID of the project you want to access. Obtain the ID by calling /api/projects/."],  # noqa: E501
    query_id: Annotated[str, "The unique ID of the environment query to be deleted. This is necessary to specify which query environment should be removed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_query_destroy'."]:
    """Delete a specific query environment.

    Use this tool to delete a query environment by specifying the project and query IDs. This action is experimental."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/query/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id_access),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_query_log_details(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project. Call /api/projects/ to find it."],  # noqa: E501
    query_id: Annotated[str, "The unique identifier for the query issued in the last 24 hours to retrieve its log details."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_query_log_retrieve'."]:
    """Retrieve query log details for a given query ID.

    Use this tool to fetch detailed query log information from the query_log_archive table for a specific query_id. The query must have been issued within the last 24 hours."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/query/{id}/log/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def check_posthog_env_authentication_async(
    context: ToolContext,
    posthog_project_id: Annotated[str, "Project ID to access a specific Datadog environment. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_query_check_auth_for_async_create'."]:  # noqa: E501
    """Check authentication for Datadog environment asynchronously.

    This tool checks if a user has authentication permissions for a specific Datadog environment asynchronously. It should be called when there is a need to verify user access permissions for a given project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/query/check_auth_for_async/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=posthog_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_draft_sql(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_query_draft_sql_retrieve'."]:  # noqa: E501
    """Retrieve draft SQL for a specific environment.

    This tool retrieves the draft SQL query for a specified project environment. It should be called when you need to access the draft SQL for analyzing or debugging purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/query/draft_sql/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_synthetic_playlists(
    context: ToolContext,
    project_identifier: Annotated[str, "A string representing the Project ID to access specific project environments for synthetic session recording playlists. Obtain the ID by calling /api/projects/."],  # noqa: E501
    created_by_user_id: Annotated[int | None, "The user ID of the creator of the playlists to filter results by. If not specified, playlists by any creator will be included."] = None,  # noqa: E501
    playlist_short_id: Annotated[str | None, "A unique identifier for the playlist. Used to specify which playlist to retrieve or target."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The starting index from which the results will be returned. Used for pagination in retrieving playlists."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_list'."]:  # noqa: E501
    """Retrieve synthetic session recording playlists.

    This tool retrieves a list of synthetic session recording playlists for a specified project environment. It should be called when you need to access these playlists to analyze or manage session recordings."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"created_by": created_by_user_id, "limit": results_per_page, "offset": starting_index_for_results, "short_id": playlist_short_id}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_session_recording_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Provide the Project ID to access the specific project. You can retrieve the ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_create'."]:  # noqa: E501
    """Create a new session recording playlist for an environment.

    Use this tool to create a session recording playlist within a specific environment by providing the required project ID. It logs views and tracks file system interactions with each GET request.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_session_recording_playlists(
    context: ToolContext,
    playlist_short_id: Annotated[str, "The short identifier of the session recording playlist to retrieve. Required for accessing specific playlist details."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier of the project to access. Obtain this ID from the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_retrieve'."]:  # noqa: E501
    """Retrieve a session recording playlist for a specific project.

    This tool retrieves session recording playlist details by accessing the specified project and playlist IDs. It should be called when you need information about a particular session recording playlist in an environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=playlist_short_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_session_recording_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID required to access the specific project. Obtainable via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    playlist_short_id: Annotated[str | None, "The short ID of the session recording playlist to update. It identifies the specific playlist within a project environment.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_update'."]:  # noqa: E501
    """Update a session recording playlist within an environment.

    Use this tool to modify details of a session recording playlist in a specified environment by providing the project and playlist identifiers.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not playlist_short_id:
        missing_params.append(("playlist_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=playlist_short_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_recording_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique ID of the project to access. Retrieve the ID via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_short_id: Annotated[str | None, "The unique short identifier for the session recording playlist you want to update. Typically a concise string for quick reference.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_partial_update'."]:  # noqa: E501
    """Update session recording playlists for a given project and ID.

    This tool updates session recording playlists by partially modifying the current resource. Use it when you need to change playlist details in a specific project environment. Each update logs a new view entry.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYRECORDINGPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not session_recording_short_id:
        missing_params.append(("session_recording_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYRECORDINGPLAYLIST"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYRECORDINGPLAYLIST"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=session_recording_short_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYRECORDINGPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_session_recording_playlist(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve by calling /api/projects/."],  # noqa: E501
    session_recording_playlist_short_id: Annotated[str, "The short ID of the session recording playlist to mark as deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_destroy'."]:  # noqa: E501
    """Mark a session recording playlist as deleted.

    Use this tool to mark a session recording playlist as deleted by setting its \"deleted\" status to true. This operation is non-reversible through a hard delete action, but effectively removes access to the playlist."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=session_recording_playlist_short_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_session_recordings(
    context: ToolContext,
    playlist_short_id: Annotated[str, "The unique short ID of the session recording playlist to retrieve recordings from."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project. Obtain this by calling the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_recordings_retrieve'."]:  # noqa: E501
    """Retrieve session recordings for a specified playlist.

    Use this tool to get session recordings from a specified session recording playlist in an environment by providing the project and playlist identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/recordings/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=playlist_short_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_session_recording_playlist_entry(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project to access. Obtain by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_id: Annotated[str | None, "The ID of the session recording to be added to the playlist.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_short_id: Annotated[str | None, "The short ID of the session recording to add to the playlist. It must be a valid string identifier.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_recordings_create'."]:  # noqa: E501
    """Add a recording to a session playlist.

    This tool logs a session recording to a specified session recording playlist for tracking purposes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLISTENTRY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not session_recording_id:
        missing_params.append(("session_recording_id", "path"))
    if not session_recording_short_id:
        missing_params.append(("session_recording_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLISTENTRY"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLISTENTRY"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/recordings/{session_recording_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, session_recording_id=session_recording_id, short_id=session_recording_short_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATESESSIONRECORDINGPLAYLISTENTRY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_session_recording(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find it."],
    session_recording_identifier: Annotated[str, "The unique identifier of the session recording to be deleted. This ID is required to specify which recording to remove from the playlist."],  # noqa: E501
    session_recording_short_id: Annotated[str, "The short ID of the session recording to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recording_playlists_recordings_destroy'."]:  # noqa: E501
    """Deletes a session recording from a playlist.

    Use this tool to remove a specific session recording from a playlist by providing the relevant IDs. This action is irreversible and should be used to manage or clean up recordings."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recording_playlists/{short_id}/recordings/{session_recording_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, session_recording_id=session_recording_identifier, short_id=session_recording_short_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_session_recordings(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project to access session recordings. Use the `/api/projects/` endpoint to find this ID if unknown."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of session recordings to return per page."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The initial index from which to return the session recordings results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_list'."]:  # noqa: E501
    """Retrieve session recordings for a specific environment.

    Use this tool to get a list of session recordings for a specific project environment. It helps in monitoring and analyzing user interactions within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_session_recording(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the Datadog project to access. Obtain it by calling /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "A UUID string identifying the specific session recording to retrieve."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_retrieve'."]:  # noqa: E501
    """Retrieve a specific session recording by ID.

    Use this tool to retrieve details of a specific session recording within a given project environment on Datadog. It should be called when details of a session recording are needed, such as in monitoring or analysis tasks."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_session_recording(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    session_recording_id: Annotated[str | None, "A UUID string identifying the session recording to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID to access. Obtain it via the /api/projects/ call.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_update'."]:  # noqa: E501
    """Update session recording details for a specific environment.

    Use this tool to update session recording information for a given project and session ID within a specific environment in Datadog. Call this tool when you need to modify the details of an existing session recording.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not session_recording_id:
        missing_params.append(("session_recording_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_session_recording(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    session_recording_uuid: Annotated[str | None, "A UUID string identifying the session recording to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_partial_update'."]:  # noqa: E501
    """Partially update session recording details.

    Use this tool to partially update details of a session recording within a specific project environment. It should be called when modifications are needed for an existing session recording without replacing all current data.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not session_recording_uuid:
        missing_params.append(("session_recording_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_session_recording(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Retrieve from /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "A UUID string identifying the session recording to delete."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_destroy'."]:  # noqa: E501
    """Delete a session recording from an environment.

    Use this tool to delete a specific session recording in a project environment. Call it when you need to remove a session recording identified by its ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_session_recording_sharing(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the project ID."],  # noqa: E501
    session_recording_id: Annotated[str, "The unique ID of the session recording you want to retrieve sharing details for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_sharing_list'."]:  # noqa: E501
    """Retrieve sharing details for a specific session recording.

    Use this tool to obtain sharing information for a specified session recording within a project environment. Ideal for tracking how session recordings are being shared across different platforms or users."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{recording_id}/sharing/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, recording_id=session_recording_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def generate_recording_password(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "Project ID for accessing a specific project. Retrieve via /api/projects/ to find the correct ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    recording_id: Annotated[str | None, "The unique identifier of the session recording for which you want to create a sharing password. This ID is necessary to specify the exact recording within the project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_sharing_passwords_create'."]:  # noqa: E501
    """Create a password for session recording sharing.

    This tool creates a new password for the sharing configuration of a session recording, identified by project and recording IDs. Use it when you need to secure sharing of session recordings with a password.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GENERATERECORDINGPASSWORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))
    if not recording_id:
        missing_params.append(("recording_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GENERATERECORDINGPASSWORD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GENERATERECORDINGPASSWORD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{recording_id}/sharing/passwords/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier, recording_id=recording_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GENERATERECORDINGPASSWORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_sharing_password(
    context: ToolContext,
    password_identifier: Annotated[str, "The unique identifier of the password to be deleted from the sharing configuration."],  # noqa: E501
    recording_id: Annotated[str, "The ID of the recording from which the password is to be deleted. This identifies the specific session recording."],  # noqa: E501
    target_project_id: Annotated[str, "The ID of the project from which to delete the password. Obtain this ID via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_sharing_passwords_destroy'."]:  # noqa: E501
    """Delete a password from the sharing configuration.

    Use this tool to delete a specific password from the session recording sharing configuration in a particular project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{recording_id}/sharing/passwords/{password_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), password_id=password_identifier, project_id=target_project_id, recording_id=recording_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def refresh_session_recording_sharing(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project. Retrieve it using the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_id: Annotated[str | None, "The unique identifier of the session recording to refresh sharing status. Required to specify which recording's sharing status to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_session_recordings_sharing_refresh_create'."]:  # noqa: E501
    """Refreshes the sharing status of a session recording.

    Use this tool to refresh the sharing status of a specific session recording within a project environment. Call this when you need to renew access or update the sharing link of a session recording using its project and recording identifiers.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REFRESHSESSIONRECORDINGSHARING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not session_recording_id:
        missing_params.append(("session_recording_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REFRESHSESSIONRECORDINGSHARING"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REFRESHSESSIONRECORDINGSHARING"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/session_recordings/{recording_id}/sharing/refresh/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, recording_id=session_recording_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REFRESHSESSIONRECORDINGSHARING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def generate_session_summaries(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve it by calling the /api/projects/ endpoint."],  # noqa: E501
    session_id_list: Annotated[list[str], "List of session IDs to be summarized, with a maximum of 300 IDs."],  # noqa: E501
    summarization_focus_area: Annotated[str | None, "Optional focus area for the summarization to guide the AI in highlighting specific patterns or information."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'create_session_summaries'."]:
    """Generate AI summaries for session recordings.

    Use this tool to create AI-generated summaries for a group of session recordings, identifying patterns and generating a comprehensive notebook."""  # noqa: E501
    request_data: Any = {"session_ids": session_id_list, "focus_area": summarization_focus_area}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_summaries/create_session_summaries/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def generate_individual_session_summary(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
    session_ids_to_summarize: Annotated[list[str], "List of session IDs for summarization, up to a maximum of 300."],  # noqa: E501
    summarization_focus_area: Annotated[str | None, "Optional focus area for refining the session summarization. Enhances the summary by concentrating on specified topics or elements."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'create_session_summaries_individually'."]:  # noqa: E501
    """Generate individual AI summaries for each session.

    Use this tool to generate AI-powered summaries for each session individually without grouping. Useful for analyzing session data at a granular level."""  # noqa: E501
    request_data: Any = {"session_ids": session_ids_to_summarize, "focus_area": summarization_focus_area}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/session_summaries/create_session_summaries_individually/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_session_properties(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Obtain from calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_sessions_property_definitions_retrieve'."]:  # noqa: E501
    """Retrieve session property definitions for an environment.

    Use this tool to get property definitions related to sessions within a specified environment. Useful for accessing environment-specific session attribute information."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/sessions/property_definitions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environment_session_values(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for which to retrieve session values. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_sessions_values_retrieve'."]:  # noqa: E501
    """Retrieve session values for a specific environment.

    Use this tool to obtain session values for a given project environment. It should be called when you need detailed data about sessions in a particular environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/sessions/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_environment_subscriptions(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project to access its environment subscriptions. Obtain this ID from the /api/projects/ endpoint."],  # noqa: E501
    result_start_index: Annotated[int | None, "Initial index to start retrieving results from for pagination purposes."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page."] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_subscriptions_list'."]:
    """Retrieve subscriptions for environment projects.

    Use this tool to obtain a list of all subscriptions associated with specific environment projects. Ideal for tracking or managing environment-related activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/subscriptions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_environment_subscription(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID to access the specific project. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_subscriptions_create'."]:  # noqa: E501
    """Create a new subscription for an environment.

    This tool is used to create a new subscription for a specific environment in a project. It is useful when you need to set up notification or monitoring preferences for the environment within the Datadog service.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTSUBSCRIPTION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTSUBSCRIPTION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTSUBSCRIPTION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/subscriptions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEENVIRONMENTSUBSCRIPTION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_subscription_details(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Obtain by calling /api/projects/."],  # noqa: E501
    subscription_id: Annotated[int, "A unique integer value identifying the subscription to retrieve details for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_subscriptions_retrieve'."]:  # noqa: E501
    """Retrieve details of a project's subscription environment.

    Fetch information related to a specific subscription within a project's environment using the project ID and subscription ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_environment_subscription(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    subscription_identifier: Annotated[int | None, "A unique integer value identifying the subscription to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you're accessing. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_subscriptions_update'."]:  # noqa: E501
    """Update environment subscription for a project.

    Use this tool to update the subscription details of an environment within a specified project in Datadog. Call this when you need to change settings or information related to an environment's subscription.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTSUBSCRIPTION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not subscription_identifier:
        missing_params.append(("subscription_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTSUBSCRIPTION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTSUBSCRIPTION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENVIRONMENTSUBSCRIPTION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_environment_subscription(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    subscription_id: Annotated[int | None, "Unique integer identifying the subscription to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_subscriptions_partial_update'."]:  # noqa: E501
    """Update a subscription for a specific environment.

    Use this tool to partially update a subscription within a specified environment in a project. This tool is called when changes to subscription details are needed, such as updating preferences or configurations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTSUBSCRIPTION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not subscription_id:
        missing_params.append(("subscription_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTSUBSCRIPTION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTSUBSCRIPTION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYENVIRONMENTSUBSCRIPTION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment_subscription(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for accessing its environment subscription. Obtain via a call to /api/projects/."],  # noqa: E501
    subscription_id: Annotated[int, "A unique integer value identifying the subscription to be marked as deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_subscriptions_destroy'."]:  # noqa: E501
    """Marks an environment subscription as deleted in Datadog.

    Use this tool to mark an environment subscription as deleted by setting its status to \"deleted.\" This does not perform a hard delete."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_user_interviews(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for accessing user interviews. Retrieve this by calling /api/projects/."],  # noqa: E501
    result_start_index: Annotated[int | None, "The starting index for returning user interviews results."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_user_interviews_list'."]:  # noqa: E501
    """Retrieve user interviews for a project environment.

    Use this tool to obtain a list of user interviews associated with a specific project environment by providing the project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/user_interviews/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_user_interview_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    access_project_id: Annotated[str | None, "The ID of the project to access for creating a user interview environment. Use /api/projects/ endpoint to retrieve if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_user_interviews_create'."]:  # noqa: E501
    """Create a user interview environment in a project.

    This tool is used to create a new user interview environment within a specified project using Datadog's API. It should be called when there is a need to organize or set up an environment for conducting user interviews.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEUSERINTERVIEWENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not access_project_id:
        missing_params.append(("access_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEUSERINTERVIEWENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEUSERINTERVIEWENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/user_interviews/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=access_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEUSERINTERVIEWENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_user_interview(
    context: ToolContext,
    interview_id: Annotated[str, "A UUID string identifying the specific user interview to be retrieved."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_user_interviews_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific user interview.

    This tool fetches the details of a user interview for a given environment by project ID and interview ID. It should be called when specific interview information is needed from the Datadog service."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/user_interviews/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=interview_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_user_interview_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_interview_id: Annotated[str | None, "A UUID string that uniquely identifies the user interview to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project for accessing environment details. Obtain by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_user_interviews_update'."]:  # noqa: E501
    """Update environment details for a user interview.

    Use this tool to update specific environment details of a user interview by specifying the project and interview IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEUSERINTERVIEWENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_interview_id:
        missing_params.append(("user_interview_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEUSERINTERVIEWENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEUSERINTERVIEWENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/user_interviews/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=user_interview_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEUSERINTERVIEWENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_interview_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_interview_id: Annotated[str | None, "A UUID string that uniquely identifies the user interview to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    target_project_id: Annotated[str | None, "The ID of the project to access. Obtain by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_user_interviews_partial_update'."]:  # noqa: E501
    """Partially update a user interview environment.

    Use this tool to apply partial updates to a specific user interview environment within a project. This helps in modifying certain attributes of the environment without altering the entire setup.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYINTERVIEWENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_interview_id:
        missing_params.append(("user_interview_id", "path"))
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYINTERVIEWENVIRONMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYINTERVIEWENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/user_interviews/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=user_interview_id, project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYINTERVIEWENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_user_interview(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for accessing the specific user interview. Obtain this by calling /api/projects/."],  # noqa: E501
    user_interview_id: Annotated[str, "A UUID string identifying the user interview to delete."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_user_interviews_destroy'."]:  # noqa: E501
    """Delete a user interview from an environment.

    Use this tool to delete a specific user interview from an environment in Datadog by providing the project and interview IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/user_interviews/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=user_interview_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_warehouse_saved_queries(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project you want to access. Obtain this ID by calling /api/projects/."],  # noqa: E501
    page_number: Annotated[int | None, "The page number within the paginated result set to retrieve. Use for navigating through results."] = None,  # noqa: E501
    search_term: Annotated[str | None, "The term used to filter and search through the saved queries."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_list'."]:  # noqa: E501
    """Retrieve a list of saved warehouse queries for a project.

    Call this tool to obtain the saved queries for warehouse tables within a specific project environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"page": page_number, "search": search_term}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_warehouse_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_create'."]:  # noqa: E501
    """Create a new warehouse saved query.

    Use this tool to create a new warehouse saved query within a specified environment. It facilitates the management of warehouse tables, allowing for efficient data handling and retrieval.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEWAREHOUSESAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEWAREHOUSESAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_warehouse_saved_query(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    saved_query_id: Annotated[str, "A UUID string identifying the specific data warehouse saved query to retrieve."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_retrieve'."]:  # noqa: E501
    """Retrieve details of a warehouse saved query.

    Fetches information about a specific saved query in the warehouse environment for a given project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_warehouse_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "A UUID identifying the specific saved query to update in the data warehouse.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project to access. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_update'."]:  # noqa: E501
    """Updates a saved query in the data warehouse.

    Use this tool to update an existing saved query within a DataDog environment's warehouse. It should be called when changes to the saved query parameters or configuration are required.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSEQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSEQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSEQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSEQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_warehouse_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "A UUID string identifying this data warehouse saved query for updates.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_partial_update'."]:  # noqa: E501
    """Update a warehouse saved query in a specified environment.

    This tool updates a specific saved query within the warehouse of a given environment. Use it to modify existing queries by specifying the project and query IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSESAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSESAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_saved_query(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve it with a call to /api/projects/."],  # noqa: E501
    saved_query_uuid: Annotated[str, "A UUID string identifying the data warehouse saved query to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_destroy'."]:  # noqa: E501
    """Delete a saved query from the warehouse.

    Use this tool to delete a specific saved query from the data warehouse based on project and query IDs. It is called when removing a saved query is necessary."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_environment_query_activity(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID for accessing the specific project. Retrieve it using /api/projects/."],  # noqa: E501
    query_id: Annotated[str, "A UUID string identifying the data warehouse saved query for retrieving activity details."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_activity_retrieve'."]:  # noqa: E501
    """Retrieve activity details of a saved warehouse query.

    Call this tool to get the activity history for a specific saved query in a Datadog environment's warehouse. Use it when you need details about a query's activity by providing the relevant project and query IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_saved_query_ancestors(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_id: Annotated[str | None, "A UUID string identifying the specific data warehouse saved query to fetch ancestors for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "ID of the project to access. Retrieve via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_ancestors_create'."]:  # noqa: E501
    """Retrieve ancestors of a saved query, including parents and beyond.

    This tool retrieves the ancestors of a saved query in the Datadog environments warehouse. It returns the immediate parents by default, but can look further back in the ancestor tree using the 'level' parameter. If the specified level exceeds the available ancestors (beyond the root), an empty list is returned.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["FETCHSAVEDQUERYANCESTORS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_id:
        missing_params.append(("saved_query_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["FETCHSAVEDQUERYANCESTORS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["FETCHSAVEDQUERYANCESTORS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/ancestors/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["FETCHSAVEDQUERYANCESTORS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_saved_query_workflow(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_id: Annotated[str | None, "A UUID string identifying the data warehouse saved query to cancel.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access for canceling the saved query. Retrieve the project ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_cancel_create'."]:  # noqa: E501
    """Cancel a running saved query workflow in Datadog.

    This tool cancels a running saved query workflow based on the provided project and query IDs. It should be called when you need to stop an ongoing query execution in Datadog's environment warehouse.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CANCELSAVEDQUERYWORKFLOW"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_id:
        missing_params.append(("saved_query_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CANCELSAVEDQUERYWORKFLOW"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CANCELSAVEDQUERYWORKFLOW"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CANCELSAVEDQUERYWORKFLOW"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_descendants_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "The UUID that uniquely identifies this saved query in the data warehouse.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project to access. Get this ID via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_descendants_create'."]:  # noqa: E501
    """Retrieve descendants of a specified saved query.

    This tool fetches the descendants of a saved query, optionally using a level parameter to determine depth. It is useful for exploring query hierarchies.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GETDESCENDANTSSAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GETDESCENDANTSSAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GETDESCENDANTSSAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/descendants/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GETDESCENDANTSSAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def undo_materialization_posthog(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "A UUID string identifying the data warehouse saved query to be reverted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id_for_access: Annotated[str | None, "Project ID to access the relevant Datadog environment. Retrieve by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_revert_materialization_create'."]:  # noqa: E501
    """Revert materialization to the original view in Datadog.

    Use this tool to delete a materialized table and its schedule, reverting it back to the original view in Datadog environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATIONPOSTHOG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_id_for_access:
        missing_params.append(("project_id_for_access", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATIONPOSTHOG"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATIONPOSTHOG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/revert_materialization/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATIONPOSTHOG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def run_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "A UUID string identifying the saved query to be executed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. To find the ID, call /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_saved_queries_run_create'."]:  # noqa: E501
    """Execute a saved query in the Datadog environment.

    This tool executes a saved query for a specified project in the Datadog environment. It should be called when you want to execute a pre-existing query and retrieve its results.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RUNSAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RUNSAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RUNSAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_saved_queries/{id}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RUNSAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_warehouse_tables(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A term to filter the warehouse tables based on specific criteria."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The index from which to begin returning the list of results for warehouse tables."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_list'."]:  # noqa: E501
    """Retrieve a list of warehouse tables for a given environment.

    Use this tool to obtain a list of warehouse tables within a specific environment for a project. Ideal for monitoring or managing data structures in your data warehouse."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index_for_results, "search": search_term}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_warehouse_table(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project to access for creating a warehouse table. Obtain it from /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_create'."]:  # noqa: E501
    """Create a new warehouse table for a specified environment.

    Use this tool to create a new warehouse table within a specified environment by providing the project ID. This is useful for setting up or expanding data storage in Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEWAREHOUSETABLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEWAREHOUSETABLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEWAREHOUSETABLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEWAREHOUSETABLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_warehouse_table(
    context: ToolContext,
    project_id: Annotated[str, "Project ID for accessing the specific data warehouse. Retrieve it using /api/projects/."],  # noqa: E501
    warehouse_table_id: Annotated[str, "A UUID string identifying this specific data warehouse table for retrieval."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific warehouse table.

    Use this tool to obtain information about a specific warehouse table in a given project environment. It is useful for accessing table details without modifying them."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_warehouse_table(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_id: Annotated[str | None, "A UUID string identifying the data warehouse table to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access. Retrieve via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_update'."]:  # noqa: E501
    """Update a specific warehouse table's information.

    Use this tool to update details of a specific warehouse table within a given project environment in Datadog. Ideal for modifying existing warehouse table configurations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSETABLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_id:
        missing_params.append(("warehouse_table_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSETABLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSETABLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSETABLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_warehouse_table(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_uuid: Annotated[str | None, "A UUID string that identifies the specific data warehouse table to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you wish to access. Obtainable by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_partial_update'."]:  # noqa: E501
    """Update specific warehouse tables in a project.

    This tool updates details of a specified warehouse table within a given project environment. It should be used when updates to table configurations or properties are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_uuid:
        missing_params.append(("warehouse_table_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_warehouse_table(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project containing the warehouse table to delete. Use /api/projects/ to obtain IDs."],  # noqa: E501
    warehouse_table_id: Annotated[str, "A UUID string that uniquely identifies the data warehouse table to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_destroy'."]:  # noqa: E501
    """Delete a specific warehouse table in a project.

    Use this tool to delete a specific warehouse table identified by its ID within a given project. Ideal for managing and cleaning up warehouse resources."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def refresh_warehouse_table_schema(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_uuid: Annotated[str | None, "A UUID string identifying the specific data warehouse table.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Obtain it by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_refresh_schema_create'."]:  # noqa: E501
    """Refresh the schema of a warehouse table.

    Use this tool to refresh the schema of a specific warehouse table in a given environment. It is useful for ensuring that the table's schema is up-to-date with any recent changes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REFRESHWAREHOUSETABLESCHEMA"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_uuid:
        missing_params.append(("warehouse_table_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REFRESHWAREHOUSETABLESCHEMA"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REFRESHWAREHOUSETABLESCHEMA"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/{id}/refresh_schema/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REFRESHWAREHOUSETABLESCHEMA"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_warehouse_table_schema(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_id: Annotated[str | None, "A UUID string identifying the data warehouse table to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The Project ID for accessing the desired project. Retrieve using /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_update_schema_create'."]:  # noqa: E501
    """Update the schema of a warehouse table.

    Use this tool to modify the structure of an existing warehouse table within a specified project environment. This tool allows for creating, reading, updating, and deleting table schemas as needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLESCHEMA"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_id:
        missing_params.append(("warehouse_table_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLESCHEMA"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLESCHEMA"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/{id}/update_schema/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLESCHEMA"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def manage_warehouse_table(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "Specify the Project ID for accessing the desired project. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_warehouse_tables_file_create'."]:  # noqa: E501
    """Create a warehouse table in Datadog environments.

    Use this tool to create a new warehouse table within a specified environment in Datadog. Ideal for managing data structures in your project environments.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MANAGEWAREHOUSETABLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MANAGEWAREHOUSETABLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MANAGEWAREHOUSETABLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/environments/{project_id}/warehouse_tables/file/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MANAGEWAREHOUSETABLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_web_vitals(
    context: ToolContext,
    filter_by_pathname: Annotated[str, "Specify the pathname to filter web vitals data for a particular resource."],  # noqa: E501
    project_id: Annotated[str, "Project ID for accessing the specific project's web vitals."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_web_vitals_retrieve'."]:  # noqa: E501
    """Retrieve web vitals for a specific project environment.

    Use this tool to get web vitals data for a given project ID's environment in Datadog. It is useful for monitoring and analyzing performance metrics."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/environments/{project_id}/web_vitals/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"pathname": filter_by_pathname}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_organizations(
    context: ToolContext,
    results_per_page: Annotated[int | None, "Specify the number of organization results to return per page."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index from where to start returning results. Useful for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'list'."]:
    """Retrieve a list of organizations.

    Use this tool to obtain a list of organizations from the Datadog service."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL")),  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_organization(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'create'."]:
    """Create a new organization in Datadog.

    Use this tool to create a new organization in Datadog. It should be called when there is a need to add an organization to the system.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEORGANIZATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters

    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEORGANIZATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEORGANIZATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL")),  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEORGANIZATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_organization_details(
    context: ToolContext,
    organization_id: Annotated[str, "A UUID string to identify the organization whose details you want to retrieve."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'retrieve'."]:
    """Retrieve details of a specific organization.

    Call this tool to obtain information about a specific organization by providing its ID. Useful for accessing organization details stored in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "A UUID string identifying the organization to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'update'."]:
    """Update details for a specific organization.

    Use this tool to change information about an existing organization in the system by providing its ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=organization_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_info(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "A UUID string identifying the organization to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'partial_update'."]:
    """Partially update organization information.

    Use this tool to partially update details of an organization by providing the organization ID and the necessary changes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONINFO"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONINFO"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONINFO"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=organization_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONINFO"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_organization(
    context: ToolContext,
    organization_id: Annotated[str, "A UUID string to identify the organization to be deleted."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'destroy'."]:
    """Delete an organization from Datadog.

    Use this tool to delete an organization by its ID from Datadog. This action is irreversible, and all data associated with the organization will be removed."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=organization_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def rollback_environments_migration(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_uuid: Annotated[str | None, "A UUID string identifying the organization for the rollback operation.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_rollback_create'."]:
    """Trigger rollback migration for multi-environment projects.

    Use this tool to initiate an environments rollback migration for users who were previously on multi-environment projects in Datadog. This involves mapping source environment IDs to target environment IDs to perform the rollback.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ROLLBACKENVIRONMENTSMIGRATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_uuid:
        missing_params.append(("organization_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ROLLBACKENVIRONMENTSMIGRATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ROLLBACKENVIRONMENTSMIGRATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{id}/environments_rollback/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=organization_uuid),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ROLLBACKENVIRONMENTSMIGRATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_batch_exports(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier of the organization for which to list batch exports. This is required to specify which organization's exports to retrieve."],  # noqa: E501
    result_offset: Annotated[int | None, "The starting index for returning results. Useful for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page for batch exports."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_list'."]:
    """Retrieve a list of batch exports for an organization.

    Use this tool to get a list of all batch exports associated with a specific organization. Ideal for monitoring and managing export activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_offset}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_batch_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "A string representing the unique identifier for the organization. Required to specify which organization the batch export will be created for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_create'."]:
    """Create a new batch export for an organization.

    This tool is used to create a new batch export operation for a specified organization in Datadog. It should be called when you need to initiate a process to export data in batches for organizational analysis or reporting.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_export_details(
    context: ToolContext,
    batch_export_id: Annotated[str, "A UUID string identifying this specific batch export."],
    organization_id: Annotated[str, "A unique identifier for the organization. Provide this to retrieve batch export details."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_retrieve'."]:
    """Retrieve details of a specific batch export in an organization.

    Use this tool to get detailed information about a specific batch export within an organization using Datadog's API. Suitable when you need to access export data by providing organization and batch export IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_batch_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying this batch export that needs to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A string representing the unique identifier for the organization whose batch export settings need updating. Ensure the correct ID is provided for successful updates.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_update'."]:
    """Update batch exports for a specific organization.

    This tool updates batch export settings for a given organization using their specific IDs. It should be called when adjustments to the exports configuration are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_batch_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string that uniquely identifies the batch export to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A string representing the unique identifier of the organization for which the batch exports need to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_partial_update'."]:
    """Update batch exports for an organization.

    This tool updates batch export settings for a specified organization in Datadog. It should be called when modifications to existing batch export configurations are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYBATCHEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYBATCHEXPORTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYBATCHEXPORTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYBATCHEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_batch_export(
    context: ToolContext,
    batch_export_id: Annotated[str, "A UUID string that uniquely identifies the batch export to be deleted."],  # noqa: E501
    organization_id: Annotated[str, "A string representing the unique identifier of the organization from which the batch export will be removed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_destroy'."]:
    """Delete a batch export from an organization.

    Use this tool to delete a specific batch export from an organization in Datadog. It should be called when you need to remove outdated or unnecessary batch export records."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def initiate_export_backfill(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the batch export to backfill.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A string representing the unique identifier of the organization. Required for initiating the backfill process.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_backfill_create'."]:
    """Triggers a backfill for a BatchExport.

    This tool is used to initiate a backfill process for a specified BatchExport. Note that this endpoint is deprecated; consider using the updated endpoint if possible.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["INITIATEEXPORTBACKFILL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["INITIATEEXPORTBACKFILL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["INITIATEEXPORTBACKFILL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/backfill/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["INITIATEEXPORTBACKFILL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_export_logs(
    context: ToolContext,
    batch_export_id: Annotated[str, "A UUID string to identify the batch export for log retrieval."],  # noqa: E501
    organization_id: Annotated[str, "A string representing the unique identifier of the organization. Required to retrieve specific batch export logs."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_logs_retrieve'."]:
    """Retrieve logs from a specific batch export.

    Use this tool to get logs from a specific batch export in an organization. Ideal for accessing logs related to specific export tasks."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def halt_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string that uniquely identifies the specific batch export to be paused.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "The UUID string that identifies the organization related to the batch export. Required for pausing the export.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_pause_create'."]:
    """Pause an ongoing BatchExport process.



    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["HALTBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["HALTBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["HALTBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/pause/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["HALTBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def run_batch_export_test_step(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_uuid: Annotated[str | None, "A UUID string that uniquely identifies the batch export to be tested.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "A string identifying the organization within Datadog for which the batch export test step is to be run.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_run_test_step_create'."]:  # noqa: E501
    """Run a test step for a batch export in Datadog.

    This tool triggers the execution of a test step within a batch export operation in a specified organization in Datadog. It is used to test batch export configurations before full deployment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTTESTSTEP"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_uuid:
        missing_params.append(("batch_export_uuid", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTTESTSTEP"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTTESTSTEP"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/run_test_step/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTTESTSTEP"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def resume_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the batch export to unpause.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A string representing the organization's unique identifier within Datadog. Required to specify which organization's BatchExport to unpause.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_unpause_create'."]:
    """Unpause a paused BatchExport for a given organization.

    Use this tool to resume a previously paused BatchExport for a specified organization. Ideal for situations where data export needs to be continued after a halt.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RESUMEBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RESUMEBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RESUMEBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/{id}/unpause/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RESUMEBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def run_test_step_new_for_batch_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_identifier: Annotated[str | None, "The unique identifier of the organization where the test step will be initiated. It is required to specify which organization's batch exports you want to test.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_run_test_step_new_create'."]:  # noqa: E501
    """Run a new test step for batch exports.

    Use this tool to initiate a new test step for batch exports within an organization on Datadog. Ideal for confirming export configurations and processes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RUNTESTSTEPNEWFORBATCHEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RUNTESTSTEPNEWFORBATCHEXPORTS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RUNTESTSTEPNEWFORBATCHEXPORTS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/run_test_step_new/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RUNTESTSTEPNEWFORBATCHEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_exports_test(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization to retrieve batch export test details."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_test_retrieve'."]:
    """Retrieve batch exports test details for an organization.

    Call this tool to obtain the details of a batch exports test for a specified organization in Datadog. It is useful to verify export configurations and ensure they are properly set up."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/batch_exports/test/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_organization_domains(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization whose domains are to be retrieved. This is required to specify which organization's domains you want to list."],  # noqa: E501
    initial_index_for_results: Annotated[int | None, "The starting index from which the domain results are returned, useful for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page. Use this to control pagination of domain listings."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_list'."]:
    """Retrieve a list of domains for a specified organization.

    Use this tool to get a comprehensive list of domains associated with a given organization. It helps in managing and inspecting domain information within an organization."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_index_for_results}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_domain_in_organization(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "The unique identifier for the organization to which the domain will be added.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_create'."]:
    """Add a new domain to an organization.

    Use this tool to create a new domain within a specific organization. It is useful for managing organizational domains.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDOMAININORGANIZATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDOMAININORGANIZATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDOMAININORGANIZATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDOMAININORGANIZATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_domain_details(
    context: ToolContext,
    domain_id: Annotated[str, "A UUID string identifying the specific domain."],
    organization_id: Annotated[str, "A string representing the unique identifier for the organization to which the domain belongs. Required to retrieve domain details."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_retrieve'."]:
    """Fetch details of a specific domain in an organization.

"""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=domain_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_domain(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    domain_uuid: Annotated[str | None, "The UUID string identifying the domain to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "The unique identifier for the organization whose domain needs to be updated. This should be a string.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_update'."]:
    """Update an organization's domain using Datadog's API.

    Call this tool to update the domain details of a specific organization in Datadog. Use it when domain information needs to be modified.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDOMAIN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not domain_uuid:
        missing_params.append(("domain_uuid", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDOMAIN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDOMAIN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=domain_uuid, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONDOMAIN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_domain_partial(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    domain_id: Annotated[str | None, "A UUID string that uniquely identifies the domain to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "The unique identifier for the organization whose domain is being partially updated. Expected to be a string.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_partial_update'."]:
    """Partially update domain information for an organization.

    Use this tool to update specific fields of a domain's information within an organization on Datadog. This is useful when you need to change only certain attributes without affecting others.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDOMAINPARTIAL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not domain_id:
        missing_params.append(("domain_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDOMAINPARTIAL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDOMAINPARTIAL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=domain_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDOMAINPARTIAL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_domain(
    context: ToolContext,
    domain_uuid: Annotated[str, "A UUID string that uniquely identifies the domain to be deleted."],
    organization_identifier: Annotated[str, "A string that uniquely identifies the organization from which the domain will be removed. This should be specified when calling the tool."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_destroy'."]:
    """Remove a domain from an organization.

    Use this tool to delete a domain from a specified organization in Datadog. It should be called when you need to remove an existing domain from the organization's configurations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=domain_uuid, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def verify_domain_for_org(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    domain_uuid: Annotated[str | None, "A UUID string identifying the domain to be verified for the organization.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A unique string ID representing the organization associated with the domain to verify.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'domains_verify_create'."]:
    """Verify a domain for a specified organization.

    This tool verifies a domain associated with a specified organization by creating a verification request for it. Useful when ensuring domain control and validation in organizational contexts.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["VERIFYDOMAINFORORG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not domain_uuid:
        missing_params.append(("domain_uuid", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["VERIFYDOMAINFORORG"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["VERIFYDOMAINFORORG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/domains/{id}/verify/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=domain_uuid, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["VERIFYDOMAINFORORG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_organization_invites(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization whose pending invites you want to retrieve."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page when listing organization invites."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The initial index from which to return the results. Use this for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'invites_list'."]:
    """Retrieve all pending invites for an organization.

    This tool retrieves a list of all pending invitations to join a specified organization. It should be called when you need to see who has been invited but not yet joined."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/invites/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_organization_invite(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "The unique identifier for the Datadog organization to which the invitation will be sent.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'invites_create'."]:
    """Send an invitation to join an organization.

    Use this tool to create and send an invitation email to a user for joining a specified organization on Datadog. It should be called when you want to add new members to an organization.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONINVITE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONINVITE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONINVITE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/invites/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONINVITE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_invitation(
    context: ToolContext,
    invite_identifier_uuid: Annotated[str, "A UUID string representing the invitation to be cancelled."],  # noqa: E501
    organization_id: Annotated[str, "A string identifier for the organization whose invitation is to be canceled."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'invites_destroy'."]:
    """Cancels an invitation to join an organization.

    This tool is used to cancel an invitation for someone to join an organization in Datadog. It should be called when you need to revoke an invite that has already been sent."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/invites/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=invite_identifier_uuid, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_bulk_invites(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_identifier: Annotated[str | None, "The unique string ID of the organization where you want to create bulk invites.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'invites_bulk_create'."]:
    """Create bulk invites for an organization.

    This tool facilitates the creation of multiple invites within an organization using Datadog's bulk invite endpoint. It should be called when there's a need to send several invites at once.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEBULKINVITES"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEBULKINVITES"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEBULKINVITES"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/invites/bulk/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEBULKINVITES"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_organization_members(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization whose members are to be listed. This ID determines which organization's members will be retrieved."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page when listing organization members."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index from which to return the results, for pagination purposes."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'members_list'."]:
    """Retrieve the list of members in an organization.

    Use this tool to obtain a list of members within a specified organization on Datadog. It should be called when you need comprehensive member details for an organization."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/members/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_member(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_identifier: Annotated[str | None, "A string representing the unique identifier of the organization in Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    user_uuid: Annotated[str | None, "The unique identifier (UUID) of the user to be updated in the organization.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'members_update'."]:
    """Update a member's information in an organization.

    Use this tool to update a member's information within a specified organization on Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBER"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBER"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBER"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/members/{user__uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier, user__uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBER"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_member_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_identifier: Annotated[str | None, "The unique identifier for the organization in Datadog. This is required to specify which organization's member is being updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    member_user_uuid: Annotated[str | None, "The unique user UUID of the organization member to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'members_partial_update'."]:
    """Update details of an organization member in Datadog.

    Use this tool to partially update the information of a member within an organization on Datadog. This should be called when changes to a member's profile or permissions are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBERDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))
    if not member_user_uuid:
        missing_params.append(("member_user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBERDETAILS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBERDETAILS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/members/{user__uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier, user__uuid=member_user_uuid),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONMEMBERDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_organization_member(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization from which the member is to be removed."],  # noqa: E501
    user_uuid: Annotated[str, "The unique identifier (UUID) of the user to be removed from the organization."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'members_destroy'."]:
    """Remove a member from an organization.

    Use this tool to delete a member from a specified organization by providing the organization ID and the user's UUID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/members/{user__uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id, user__uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_member_scoped_api_keys(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization whose member's scoped API keys are to be retrieved."],  # noqa: E501
    user_uuid: Annotated[str, "The unique identifier for the user within the organization. This is required to retrieve their scoped API keys."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'members_scoped_api_keys_retrieve'."]:  # noqa: E501
    """Retrieve scoped API keys for a member in an organization.

    This tool should be called to obtain the scoped API keys associated with a specific member within an organization on Datadog. It is useful for managing and auditing access permissions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/members/{user__uuid}/scoped_api_keys/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id, user__uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_current_org_projects(
    context: ToolContext,
    organization_identifier: Annotated[str, "A string representing the unique identifier of the current organization. Required to fetch projects."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The initial index from which to return the results. Use this to paginate results starting from a specific point."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'list_2'."]:
    """Retrieve projects for the current organization.

    Use this tool to get a list of projects associated with the current organization."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_for_organization(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_identifier: Annotated[str | None, "The unique identifier for the organization. Used to specify which organization's project is being created.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'create_2'."]:
    """Create a new project for the current organization.

    Use this tool to create a new project within the organization's current settings. It is suitable for managing and organizing projects under a specific organization's ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROJECTFORORGANIZATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROJECTFORORGANIZATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROJECTFORORGANIZATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROJECTFORORGANIZATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_organization_project_details(
    context: ToolContext,
    organization_identifier: Annotated[str, "A string representing the unique identifier for the organization whose project details are to be retrieved."],  # noqa: E501
    project_id: Annotated[int, "A unique identifier for the project. This is required to retrieve specific project details within an organization."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'retrieve_2'."]:
    """Fetch details of a specific project within an organization.

    Use this tool to obtain detailed information about a particular project within the specified organization by providing the organization's and project's IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_project_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "A unique integer identifying the project to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A unique string identifying the organization whose project details are to be updated. Required for specifying the target organization.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'update_2'."]:
    """Update project details for the current organization.

    This tool updates the project details for a specified organization. It should be called when modifications to an organization's project data are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROJECTDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROJECTDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROJECTDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROJECTDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_project(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "A unique integer value identifying the project to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A string representing the identifier of the organization. Required to update the project details.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'partial_update_2'."]:
    """Update a project's details within an organization.

    Use this tool to update specific details of a project within the current organization by providing the organization and project IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONPROJECT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONPROJECT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONPROJECT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONPROJECT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_project(
    context: ToolContext,
    organization_identifier: Annotated[str, "The unique identifier for the organization from which the project is to be deleted. Ensure this ID is correct to prevent errors."],  # noqa: E501
    project_id: Annotated[int, "A unique integer identifying the project to delete."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'destroy_2'."]:
    """Deletes a project from the current organization.

    Use this tool to delete a specific project within the current organization. Ensure you have the correct organization and project IDs before calling this tool."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_activity(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier of the organization for which to retrieve project activity."],  # noqa: E501
    project_id: Annotated[int, "A unique integer value identifying the specific project to retrieve activity for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'activity_retrieve'."]:
    """Retrieve project activity for a specific organization and project.

    Use this tool to get detailed activities for a specific project within a given organization on Datadog. It's useful for monitoring and analyzing project-related activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_project_product_intent(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "A unique integer value identifying the project to update within the organization.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "The unique identifier of the organization. Provide this to specify which organization's project is being updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'add_product_intent_partial_update'."]:  # noqa: E501
    """Update product intent for a specific project in an organization.

    This tool is used to partially update the product intent of a specific project within an organization. It is useful for making adjustments or corrections to product intent assignments in organizational projects.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROJECTPRODUCTINTENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROJECTPRODUCTINTENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROJECTPRODUCTINTENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/add_product_intent/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROJECTPRODUCTINTENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_organization_project(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_unique_id: Annotated[int | None, "An integer that uniquely identifies the project to be created for the organization.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A unique string that identifies the organization for which the project is being created.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'change_organization_create'."]:
    """Create a project for the current organization.

    Use this tool to create and associate a new project with the specified organization in Datadog. It returns the details of the newly created project, helping you manage organizational projects efficiently.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONPROJECT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_unique_id:
        missing_params.append(("project_unique_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONPROJECT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONPROJECT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/change_organization/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_unique_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEORGANIZATIONPROJECT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_project_onboarding_status(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "A unique integer identifying the specific project to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_identifier: Annotated[str | None, "A string representing the unique ID of the organization to update the project onboarding status within.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'complete_product_onboarding_partial_update'."]:  # noqa: E501
    """Update the onboarding status of a project in an organization.

    This tool updates the onboarding status of a specific project within the current organization. It should be called when there's a need to mark the completion or update the progress of a project's onboarding process.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROJECTONBOARDINGSTATUS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROJECTONBOARDINGSTATUS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROJECTONBOARDINGSTATUS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/complete_product_onboarding/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROJECTONBOARDINGSTATUS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_secret_token_backup(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "The unique ID of the project whose secret token backup is to be deleted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "A unique identifier for the organization. This is required to specify which organization's project the secret token backup belongs to.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'delete_secret_token_backup_partial_update'."]:  # noqa: E501
    """Deletes a secret token backup for a specified project.

    Call this tool to delete a secret token backup from a specific project within an organization. Use when you need to remove sensitive backup data to maintain security.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DELETESECRETTOKENBACKUP"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DELETESECRETTOKENBACKUP"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DELETESECRETTOKENBACKUP"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/delete_secret_token_backup/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DELETESECRETTOKENBACKUP"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def check_demo_data_generation_status(
    context: ToolContext,
    organization_identifier: Annotated[str, "A string that uniquely identifies the organization for the project."],  # noqa: E501
    project_identifier: Annotated[int, "An integer uniquely identifying the project to check demo data generation status for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'is_generating_demo_data_retrieve'."]:  # noqa: E501
    """Check if demo data is being generated for a project.

    Use this tool to determine whether demo data is currently being generated for a specific project within an organization."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/is_generating_demo_data/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_identifier, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reset_project_token(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "A unique identifier for the project whose token will be reset. This is required to specify which project's token needs to be reset.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "The unique identifier for the organization in which the project is located.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'reset_token_partial_update'."]:
    """Reset a project's token in the current organization.

    Use this tool to reset the token for a specific project within the current organization. It should be called when there's a need to update security or access settings for a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RESETPROJECTTOKEN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RESETPROJECTTOKEN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RESETPROJECTTOKEN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/reset_token/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RESETPROJECTTOKEN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def rotate_secret_token_for_project(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[int | None, "A unique integer identifying the project for which you want to rotate the secret token.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "The ID of the organization to which the project belongs. Required for token rotation.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'rotate_secret_token_partial_update'."]:  # noqa: E501
    """Rotate the secret token for a specific project.

    Use this tool to rotate the secret token for a project within the current organization. This can be useful when token regeneration is needed for security or access purposes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ROTATESECRETTOKENFORPROJECT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ROTATESECRETTOKENFORPROJECT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ROTATESECRETTOKENFORPROJECT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/projects/{id}/rotate_secret_token/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=project_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ROTATESECRETTOKENFORPROJECT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_proxy_records(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier of the organization for which to retrieve proxy records."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page when retrieving proxy records."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The initial index from which to begin returning results. Use this to paginate through the list of proxy records."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'proxy_records_list'."]:
    """Retrieve proxy records for a given organization.

    Call this tool to obtain a list of proxy records associated with a specific organization. Use it when needing detailed information on proxy configurations for oversight or management purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/proxy_records/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_proxy_records(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_identifier: Annotated[str | None, "A unique string identifier for the organization to which the proxy record will be added.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'proxy_records_create'."]:
    """Create a proxy record for an organization.

    This tool calls the Datadog API to create a new proxy record within a specified organization. Use this tool when you need to add proxy records for managing organizational network proxies.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROXYRECORDS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_identifier:
        missing_params.append(("organization_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROXYRECORDS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROXYRECORDS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/proxy_records/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROXYRECORDS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_proxy_record(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization whose proxy record you want to retrieve."],  # noqa: E501
    proxy_record_id: Annotated[str, "The unique identifier for the proxy record to be retrieved."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'proxy_records_retrieve'."]:
    """Retrieve details of a specific proxy record.

    Fetch detailed information about a specific proxy record within an organization using the organization ID and record ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/proxy_records/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=proxy_record_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_proxy_record(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    proxy_record_id: Annotated[str | None, "The unique identifier for the proxy record to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "A unique identifier for the organization whose proxy record is being updated. This must be a valid string representing the organization in Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'proxy_records_update'."]:
    """Update a proxy record within an organization.

    Use this tool to update details of a specific proxy record for a given organization in Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROXYRECORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not proxy_record_id:
        missing_params.append(("proxy_record_id", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROXYRECORD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROXYRECORD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/proxy_records/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=proxy_record_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROXYRECORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_proxy_record(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    proxy_record_id: Annotated[str | None, "The unique identifier for the proxy record to be updated. This is required to specify which record is being modified.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "The unique identifier for the organization. It determines the organization within which the proxy record needs to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'proxy_records_partial_update'."]:
    """Update partial details of a proxy record.

    Use this tool to partially update details of a proxy record within a specified organization. Suitable for modifying existing proxy records.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYPROXYRECORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not proxy_record_id:
        missing_params.append(("proxy_record_id", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYPROXYRECORD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYPROXYRECORD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/proxy_records/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=proxy_record_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYPROXYRECORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_proxy_record(
    context: ToolContext,
    organization_id: Annotated[str, "The unique identifier for the organization from which the proxy record will be deleted. This is required to specify the target organization."],  # noqa: E501
    proxy_record_id: Annotated[str, "The unique identifier of the proxy record to be deleted. Required for deletion."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'proxy_records_destroy'."]:
    """Deletes a proxy record for an organization.

    Use this tool to delete a specific proxy record within an organization in Datadog. It should be called when a record is no longer needed or requires removal."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/proxy_records/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=proxy_record_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_organization_roles(
    context: ToolContext,
    organization_identifier: Annotated[str, "The unique ID of the organization to fetch roles for. Must be a valid string identifier."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of roles to return per page."] = None,  # noqa: E501
    starting_result_index: Annotated[int | None, "The starting index from which to return role results for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_list'."]:
    """Fetches the list of roles for a specified organization.

"""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_result_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_role_in_organization(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "The unique identifier of the organization where the role will be created.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_create'."]:
    """Create a new role within an organization.

    Use this tool to add a new role to a specific organization. Appropriate when setting up roles for users within an organization.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEROLEINORGANIZATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEROLEINORGANIZATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEROLEINORGANIZATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEROLEINORGANIZATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_role_details(
    context: ToolContext,
    organization_identifier: Annotated[str, "A string that uniquely identifies the organization within which the role is being retrieved. Required to ensure that the role details correspond to the correct organization."],  # noqa: E501
    role_id: Annotated[str, "A UUID string to identify the specific role within the organization."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_retrieve'."]:
    """Retrieve details of a specific role within an organization.

    This tool retrieves detailed information about a specific role within an organization using the role ID. It should be called when you need to understand the responsibilities and permissions associated with a specific role."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=role_id, organization_id=organization_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_organization_role(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    role_uuid: Annotated[str | None, "A UUID string identifying the role to be updated in the organization.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "A unique identifier for the organization where the role will be updated. This is a required parameter.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_update'."]:
    """Update an organization's role details.

    Use this tool to update the details of a specific role within an organization, such as permissions and role information.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONROLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not role_uuid:
        missing_params.append(("role_uuid", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONROLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONROLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=role_uuid, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEORGANIZATIONROLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_role_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    role_uuid: Annotated[str | None, "A UUID string identifying the role to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    organization_id: Annotated[str | None, "A string representing the identifier of the organization. Required for role updates.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_partial_update'."]:
    """Partially update organization role details.

    Use this tool to modify specific attributes of a role within an organization on Datadog. Ideal for updating permissions or changing role configurations without affecting the entire role setup.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEROLEDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not role_uuid:
        missing_params.append(("role_uuid", "path"))
    if not organization_id:
        missing_params.append(("organization_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEROLEDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEROLEDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=role_uuid, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEROLEDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_role_in_organization(
    context: ToolContext,
    organization_id: Annotated[str, "The ID of the organization from which the role will be deleted. This should be a string."],  # noqa: E501
    role_id: Annotated[str, "A UUID string identifying the role to be deleted."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_destroy'."]:
    """Delete a specific role within an organization.

    Use this tool to delete a role from an organization by providing the organization ID and role ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=role_id, organization_id=organization_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_role_memberships(
    context: ToolContext,
    organization_id: Annotated[str, "A unique identifier for the organization within Datadog."],
    role_identifier: Annotated[str, "The unique identifier of the role for which memberships are to be retrieved within an organization."],  # noqa: E501
    result_start_index: Annotated[int | None, "The initial index from which to return the role membership results."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page when listing role memberships."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_role_memberships_list'."]:
    """Retrieve role memberships for a specified role within an organization.

    This tool should be called to access a list of role memberships for a specific role in an organization. It helps in managing and viewing role assignments within Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{role_id}/role_memberships/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id, role_id=role_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_role_membership(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    organization_id: Annotated[str | None, "The unique identifier for the organization in which the role membership is to be created. This is required to specify the targeted organization within Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    role_identifier: Annotated[str | None, "The unique identifier of the role to which the user will be assigned. It should be a string that matches the specific role in Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_role_memberships_create'."]:
    """Create a role membership in an organization.

    Use this tool to assign a user to a specific role within an organization in Datadog. This is useful for managing user permissions and access within your organization.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEROLEMEMBERSHIP"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not organization_id:
        missing_params.append(("organization_id", "path"))
    if not role_identifier:
        missing_params.append(("role_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEROLEMEMBERSHIP"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEROLEMEMBERSHIP"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{role_id}/role_memberships/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), organization_id=organization_id, role_id=role_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEROLEMEMBERSHIP"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_role_membership(
    context: ToolContext,
    organization_identifier: Annotated[str, "A string representing the unique identifier of the organization. Required to specify which organization the role membership belongs to."],  # noqa: E501
    role_id: Annotated[str, "The unique identifier for the role from which membership will be removed. It should be a valid UUID string."],  # noqa: E501
    role_membership_id: Annotated[str, "A UUID string identifying the specific role membership to be removed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'roles_role_memberships_destroy'."]:
    """Remove a role membership from an organization.

    Use this tool to delete a specific role membership for a user within an organization in Datadog. It should be called when you need to remove a user's membership from a particular role."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/organizations/{organization_id}/roles/{role_id}/role_memberships/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=role_membership_id, organization_id=organization_identifier, role_id=role_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_actions(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID to access specific project actions. Obtain via /api/projects/ if unknown."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format for the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The initial index from which results should start when retrieving project actions."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'actions_list'."]:
    """Retrieve and log actions for a specific project.

    Use this tool to get the list of actions performed within a specified project. Every call to this endpoint logs a new view of the project actions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/actions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format, "limit": results_per_page, "offset": starting_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def log_track_filesystem_views(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Call /api/projects/ to obtain it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Valid options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'actions_create'."]:
    """Log a new view for file system access tracking.

    Use this tool to log a new view every time a file system resource is accessed via GET, helping track file system views for monitoring or analytics purposes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["LOGTRACKFILESYSTEMVIEWS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["LOGTRACKFILESYSTEMVIEWS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["LOGTRACKFILESYSTEMVIEWS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/actions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["LOGTRACKFILESYSTEMVIEWS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_action(
    context: ToolContext,
    action_id: Annotated[int, "Unique integer identifying the specific action to retrieve logs for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format for the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'actions_retrieve'."]:
    """Retrieve logs for a specific project action.

    Use this tool to obtain logs for a specific action within a project. Each retrieval provides a log of the file system views related to that action."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/actions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=action_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_project_action(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    action_id: Annotated[int | None, "The unique integer to identify the action within the project for updating.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "ID of the project to access. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specifies the format of the data response. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'actions_update'."]:
    """Update and track views for a project action in Datadog.

    Use this tool to update details of a specific action within a project in Datadog and log a new view of the resource.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROJECTACTION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not action_id:
        missing_params.append(("action_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROJECTACTION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROJECTACTION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/actions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=action_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROJECTACTION"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_action_partial(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    action_id: Annotated[int | None, "A unique integer value identifying the action to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you want to access. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format for the output data. Choose between 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'actions_partial_update'."]:
    """Partially update an action in a project to track views.

    Use this tool to partially update an action within a project, logging each accessed view of the resource.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEACTIONPARTIAL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not action_id:
        missing_params.append(("action_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEACTIONPARTIAL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEACTIONPARTIAL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/actions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=action_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEACTIONPARTIAL"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def mark_action_as_deleted(
    context: ToolContext,
    action_id: Annotated[int, "A unique integer identifying the action you want to mark as deleted in the project."],  # noqa: E501
    project_identifier: Annotated[str, "The unique Project ID to access the specific project. Retrieve this by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response, either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'actions_destroy'."]:
    """Mark an action as deleted in a specific project.

    Use this tool to mark an action as deleted within a specific project in Datadog. This does not hard delete the action but updates its status to deleted."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/actions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=action_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_activity_log(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project you want to access the activity log for. Retrieve by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'activity_log_list'."]:
    """Fetch the activity log for a specific project.

    Use this tool to retrieve the activity log of a specified project, providing insights into recent activities and changes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/activity_log/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_available_agents(
    context: ToolContext,
    project_identification: Annotated[str, "The ID of the project you want to access. Obtain the ID by calling /api/projects/."],  # noqa: E501
    result_start_index: Annotated[int | None, "The initial index to begin returning agent definitions from the list."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of agent definitions to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'agents_list'."]:
    """Retrieve a list of agent definitions for tasks.

    Use this tool to obtain a list of available agent definitions that can be assigned to tasks within a specific project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/agents/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identification),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": result_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_agent_definition(
    context: ToolContext,
    agent_id: Annotated[str, "The unique identifier of the agent to retrieve. This ID specifies which agent's details to fetch."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project you want to access. Use the API call /api/projects/ to find the project ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'agents_retrieve'."]:
    """Retrieve a specific agent definition by ID.

    Use this tool to obtain detailed information about a specific agent by providing its ID and the associated project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/agents/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=agent_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_annotations_for_project(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain by calling /api/projects/."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The starting index for the results to return in pagination."] = None,  # noqa: E501
    results_limit_per_page: Annotated[int | None, "Specify the number of results to return per page when retrieving annotations for a project."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A search term to filter the annotations. Can be a keyword or phrase."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'annotations_list'."]:
    """Retrieve annotations for a specific project.

    Use this tool to get a list of annotations for a specified project in Datadog."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/annotations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_limit_per_page, "offset": initial_result_index, "search": search_term}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_annotation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project where the annotation will be created. Obtain it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'annotations_create'."]:
    """Create a new annotation for a project.

    Use this tool to create a new annotation within a specified project in Datadog. This can be used to track important events or notes related to project data.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEANNOTATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEANNOTATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEANNOTATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/annotations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEANNOTATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_annotation(
    context: ToolContext,
    annotation_id: Annotated[int, "A unique integer identifying the specific annotation to retrieve from a project."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the desired project in Datadog. Obtainable via `/api/projects/`."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'annotations_retrieve'."]:
    """Retrieve details of a specific annotation by ID.

    Call this tool to get detailed information about an annotation in a specific project on Datadog. This can be useful to view or verify the details of annotations used in project analysis."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/annotations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=annotation_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_annotation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    annotation_id: Annotated[int | None, "A unique integer identifying the annotation to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID for accessing the desired project. Retrieve ID with /api/projects/ call.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'annotations_update'."]:
    """Update an existing annotation by ID.

    This tool allows updating of an existing annotation in a specified project by providing the annotation ID and project ID. Useful for modifying details related to an annotation.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEANNOTATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not annotation_id:
        missing_params.append(("annotation_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEANNOTATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEANNOTATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/annotations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=annotation_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEANNOTATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_annotation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    annotation_id: Annotated[int | None, "A unique integer to identify the specific annotation to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'annotations_partial_update'."]:
    """Update specific details of an annotation in a project.

    This tool is used to update specific information of an existing annotation within a project on Datadog. It should be called when you need to modify details of an annotation by specifying the project and annotation IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYANNOTATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not annotation_id:
        missing_params.append(("annotation_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYANNOTATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYANNOTATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/annotations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=annotation_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYANNOTATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_annotation(
    context: ToolContext,
    annotation_id: Annotated[int, "A unique integer identifier for the annotation to be marked as deleted."],  # noqa: E501
    project_id_for_annotation: Annotated[str, "The ID of the project where the annotation should be marked as deleted. Use /api/projects/ to find the correct ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'annotations_destroy'."]:
    """Mark an annotation as deleted in a project.

    Use this tool to mark an annotation as deleted by setting the \"deleted\" field to true in a specific project. This action uses a patch call rather than a hard delete."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/annotations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=annotation_id, project_id=project_id_for_annotation),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_app_metrics(
    context: ToolContext,
    plugin_config_id: Annotated[int, "A unique integer identifying the plugin configuration."],
    project_id_for_app_metrics: Annotated[str, "The Project ID for the project whose app metrics you want to retrieve. Find the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'app_metrics_retrieve'."]:
    """Retrieve application metrics for a specific project and ID.

    Call this tool to obtain the metrics of a specific application within a given project. Ideal for monitoring and analyzing app performance through Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/app_metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=plugin_config_id, project_id=project_id_for_app_metrics),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_error_details_for_app_metrics(
    context: ToolContext,
    plugin_config_id: Annotated[int, "A unique integer identifying the plugin configuration to retrieve error details for."],  # noqa: E501
    project_identifier: Annotated[str, "The unique Project ID for accessing specific app metrics error details. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'app_metrics_error_details_retrieve'."]:  # noqa: E501
    """Retrieve error details for specific app metrics.

    This tool retrieves detailed error information for a specific app metric of a project. It should be called when you need to understand the nature of errors related to app metrics."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/app_metrics/{id}/error_details/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=plugin_config_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_metrics_history(
    context: ToolContext,
    plugin_configuration_identifier: Annotated[str, "The ID of the plugin configuration for which historical metrics exports are being fetched."],  # noqa: E501
    project_identifier: Annotated[str, "The Project ID required to access the desired project's historical data. Obtainable via a /api/projects/ call."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'app_metrics_historical_exports_retrieve'."]:  # noqa: E501
    """Retrieve historical exports of app metrics.

    This tool retrieves historical app metrics exports for a specified project and plugin configuration. Useful for analyzing past performance data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/app_metrics/{plugin_config_id}/historical_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), plugin_config_id=plugin_configuration_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_app_metrics_historical_exports(
    context: ToolContext,
    export_id: Annotated[str, "The unique identifier for the specific app metrics export record to retrieve."],  # noqa: E501
    plugin_configuration_id: Annotated[str, "The ID for the plugin configuration to be used when retrieving app metrics. This is required to specify the context of the metrics data."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the targeted project. Retrieve the ID using the /api/projects/ endpoint if needed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'app_metrics_historical_exports_retrieve_2'."]:  # noqa: E501
    """Retrieve historical export data for app metrics.

    This tool retrieves historical export data for app metrics using specified project and plugin configuration IDs. It should be called when detailed historical app metrics are needed for analysis or reporting."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/app_metrics/{plugin_config_id}/historical_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=export_id, plugin_config_id=plugin_configuration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_batch_exports(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project for which to access batch exports. Obtain this by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page when retrieving batch exports."] = None,  # noqa: E501
    starting_index: Annotated[int | None, "The initial index from which to return the results in the list of batch exports."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_list_2'."]:
    """Retrieve a list of batch exports for a specific project.

    Call this tool to obtain a detailed list of all batch exports associated with a specified project ID in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project you want to access for batch export. Retrieve from /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_create_2'."]:
    """Initiate a batch export for a project.

    Use this tool to start a new batch export for a specified project within Datadog. Ideal for scenarios needing data extraction or export management.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_backfill_exports(
    context: ToolContext,
    batch_export_identifier: Annotated[str, "The unique identifier for the batch export to retrieve backfills for. Required to specify which export's backfills are listed."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtainable via /api/projects/ call."],  # noqa: E501
    ordering_field_for_results: Annotated[str | None, "Specify the field to use for ordering the backfill export results."] = None,  # noqa: E501
    pagination_cursor: Annotated[str | None, "The pagination cursor value used to navigate through paginated results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_backfills_list'."]:
    """Retrieve list of batch export backfills for a project.

    This tool retrieves a list of batch export backfills for a specified project and batch export ID within Datadog. It allows viewing of backfills but does not support updating or deleting them."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/backfills/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"cursor": pagination_cursor, "ordering": ordering_field_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_batch_export_backfill(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_identifier: Annotated[str | None, "The unique identifier for the batch export to be backfilled. This ID determines which specific export the backfill will apply to.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project to access. Retrieve this via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_backfills_create'."]:
    """Create a new backfill for a batch export.

    This tool is used to initiate a new backfill process for a specific BatchExport within a project, allowing for data replenishment or correction in Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTBACKFILL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_identifier:
        missing_params.append(("batch_export_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTBACKFILL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTBACKFILL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/backfills/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEBATCHEXPORTBACKFILL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_batch_export_backfill(
    context: ToolContext,
    batch_export_backfill_id: Annotated[str, "A UUID string identifying the specific batch export backfill to retrieve."],  # noqa: E501
    batch_export_identifier: Annotated[str, "A string representing the batch export backfill ID to retrieve details."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve the project ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_backfills_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific batch export backfill.

    Use this tool to obtain information about a specific batch export backfill in Datadog. Ideal for viewing backfill details without making updates or deletions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/backfills/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_backfill_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def terminate_batch_export_backfill(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_identifier: Annotated[str | None, "A unique identifier for the batch export backfill to be canceled. This ID specifies which batch export backfill is targeted for termination.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    backfill_id: Annotated[str | None, "A UUID string identifying this batch export backfill in Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID to access. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_backfills_cancel_create'."]:  # noqa: E501
    """Cancel a batch export backfill in Datadog.

    Use this tool to cancel an ongoing batch export backfill process for a specific project in Datadog, identified by the project, batch export, and backfill IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["TERMINATEBATCHEXPORTBACKFILL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_identifier:
        missing_params.append(("batch_export_identifier", "path"))
    if not backfill_id:
        missing_params.append(("backfill_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["TERMINATEBATCHEXPORTBACKFILL"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["TERMINATEBATCHEXPORTBACKFILL"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/backfills/{id}/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=backfill_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["TERMINATEBATCHEXPORTBACKFILL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_batch_export_runs(
    context: ToolContext,
    batch_export_identifier: Annotated[str, "The unique identifier for the batch export. Used to specify which export runs to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the ID."],  # noqa: E501
    pagination_cursor: Annotated[str | None, "The pagination cursor value used to fetch the next page of results."] = None,  # noqa: E501
    results_ordering_field: Annotated[str | None, "Specify the field for ordering the results of the batch export runs. Common fields might include date, status, or name."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_runs_list'."]:
    """Retrieve batch export runs for a specific project and export.

    Fetches a list of runs associated with a particular batch export for a given project in Datadog. Use this tool to monitor or analyze batch export activities."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/runs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"cursor": pagination_cursor, "ordering": results_ordering_field}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_export_run(
    context: ToolContext,
    batch_export_id: Annotated[str, "A unique string to identify the batch export run you want to retrieve details for."],  # noqa: E501
    batch_export_run_uuid: Annotated[str, "A UUID string identifying the specific batch export run for detailed retrieval."],  # noqa: E501
    project_id: Annotated[str, "Provide the Project ID to access the specific project. Use /api/projects/ to obtain the ID if unknown."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_runs_retrieve'."]:
    """Retrieve details of a specific batch export run.

    Use this tool to get detailed information about a specific batch export run within a project. It should be called when you need to analyze or review the results of a batch export operation in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/runs/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_id, id=batch_export_run_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def stop_batch_export_run(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_run_identifier: Annotated[str | None, "A UUID string uniquely identifying the batch export run to be canceled.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    batch_export_run_id: Annotated[str | None, "A UUID string that uniquely identifies the batch export run to be canceled.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access. Use /api/projects/ to find the correct ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_runs_cancel_create'."]:  # noqa: E501
    """Cancel an ongoing batch export run in a specific project.

    Use this tool to cancel a currently running batch export task in a Datadog project. It should be called when a batch export run needs to be stopped before completion.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["STOPBATCHEXPORTRUN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_run_identifier:
        missing_params.append(("batch_export_run_identifier", "path"))
    if not batch_export_run_id:
        missing_params.append(("batch_export_run_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["STOPBATCHEXPORTRUN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["STOPBATCHEXPORTRUN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/runs/{id}/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_run_identifier, id=batch_export_run_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["STOPBATCHEXPORTRUN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_export_run_logs(
    context: ToolContext,
    batch_export_identifier: Annotated[str, "A unique identifier for the batch export. Necessary for retrieving logs for that specific export run."],  # noqa: E501
    batch_export_run_id: Annotated[str, "A UUID string identifying this specific batch export run in Datadog."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project you want to access. Retrieve it by calling `/api/projects/`."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_runs_logs_retrieve'."]:  # noqa: E501
    """Retrieve logs for a specific batch export run.

    Use this tool to access logs associated with a specific run of a batch export in Datadog. Useful for monitoring and debugging batch export processes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/runs/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_run_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retry_export_run(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_identifier: Annotated[str | None, "The unique identifier for the batch export run to retry. It should be provided as a string.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    batch_export_run_id: Annotated[str | None, "A UUID string that identifies the specific batch export run to retry in Datadog.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The Project ID you want to access in Datadog. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_runs_retry_create'."]:
    """Retry a batch export run in Datadog.

    Use this tool to retry a batch export run in Datadog. It leverages the same mechanism as backfilling, effectively retrying a single run.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RETRYEXPORTRUN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_identifier:
        missing_params.append(("batch_export_identifier", "path"))
    if not batch_export_run_id:
        missing_params.append(("batch_export_run_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RETRYEXPORTRUN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RETRYEXPORTRUN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{batch_export_id}/runs/{id}/retry/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), batch_export_id=batch_export_identifier, id=batch_export_run_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RETRYEXPORTRUN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_posthog_batch_exports(
    context: ToolContext,
    batch_export_id: Annotated[str, "A UUID string that uniquely identifies the batch export in Datadog."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Call /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_retrieve_2'."]:
    """Retrieve specific Datadog batch export details.

    Use this tool to retrieve details of a specific batch export from Datadog by providing the project and export IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the batch export to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_update_2'."]:
    """Update an existing batch export in a project.

    Use this tool to update the settings of an existing batch export for a specified project. Suitable for modifying export configurations within Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def edit_batch_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the batch export to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you're accessing. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_partial_update_2'."]:
    """Update specific details of batch exports.

    This tool updates details of batch exports for a project. Use it when you need to modify existing batch export configurations in a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EDITBATCHEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EDITBATCHEXPORTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EDITBATCHEXPORTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EDITBATCHEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def destroy_batch_export(
    context: ToolContext,
    batch_export_uuid: Annotated[str, "A UUID string identifying the batch export to be deleted."],
    project_id: Annotated[str, "The unique identifier for the project to access. Use /api/projects/ to retrieve it."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_destroy_2'."]:
    """Deletes a specific batch export in a project.

    This tool deletes a batch export for a specified project using the project ID and batch export ID. It should be called to remove unwanted or completed batch exports from a project in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def start_batch_export_backfill(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string identifying the specific batch export.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_backfill_create_2'."]:
    """Initiate a backfill process for a BatchExport.

    This tool triggers a backfill for a specific BatchExport in a project. It is used to ensure that historical data is processed correctly. Note that this endpoint is deprecated, so consider using the updated endpoint if available.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["STARTBATCHEXPORTBACKFILL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["STARTBATCHEXPORTBACKFILL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["STARTBATCHEXPORTBACKFILL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/backfill/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["STARTBATCHEXPORTBACKFILL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_log_exports(
    context: ToolContext,
    batch_export_id: Annotated[str, "A UUID specifying the batch export to retrieve logs from."],
    project_id: Annotated[str, "Project ID for accessing the specific project. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_logs_retrieve_2'."]:
    """Retrieve logs from batch exports by project and export ID.

    Use this tool to retrieve logs from batch exports by specifying the project ID and export ID. Ideal for monitoring and reviewing log outputs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def suspend_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_uuid: Annotated[str | None, "A UUID identifying the batch export to pause.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID for accessing the specific project. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_pause_create_2'."]:
    """Pause an ongoing batch export process in a project.

    Allows pausing a specific batch export process identified by project and export IDs. Use this when you need to temporarily halt data exports in the Datadog platform.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["SUSPENDBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_uuid:
        missing_params.append(("batch_export_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["SUSPENDBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["SUSPENDBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/pause/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["SUSPENDBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def run_test_step_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_id: Annotated[str | None, "A UUID string used to identify the specific batch export for the test step.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access for batch export testing. Retrieve this ID via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_run_test_step_create_2'."]:  # noqa: E501
    """Initiate a test step for batch exports.

    This tool triggers a test step for batch exports within a specified project. It should be called when testing the batch export process for a given ID is needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RUNTESTSTEPBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_id:
        missing_params.append(("batch_export_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RUNTESTSTEPBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RUNTESTSTEPBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/run_test_step/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RUNTESTSTEPBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reactivate_batch_export(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    batch_export_uuid: Annotated[str | None, "A UUID string identifying this batch export to be unpaused.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access for unpausing the BatchExport. Make a call to /api/projects/ to find the project ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_unpause_create_2'."]:
    """Unpause a paused BatchExport in a project.

    This tool is used to unpause a previously paused BatchExport within a specified project. Call it to resume data export processes when needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REACTIVATEBATCHEXPORT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not batch_export_uuid:
        missing_params.append(("batch_export_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REACTIVATEBATCHEXPORT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REACTIVATEBATCHEXPORT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/{id}/unpause/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=batch_export_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REACTIVATEBATCHEXPORT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def run_batch_exports_test_step(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project you want to access for the batch export test step. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_run_test_step_new_create_2'."]:  # noqa: E501
    """Triggers a test step for batch exports in a specified project.

    Use this tool to initiate a test step for batch exports within a given project. This can be helpful to verify configurations or test export processes without executing a full batch export.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTSTESTSTEP"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTSTESTSTEP"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTSTESTSTEP"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/run_test_step_new/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RUNBATCHEXPORTSTESTSTEP"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_batch_export_tests(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Use the /api/projects/ endpoint to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'batch_exports_test_retrieve_2'."]:
    """Retrieve batch export test details for a project.

    Use this tool to get information on batch export tests for a specific project by providing the project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/batch_exports/test/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_cohorts(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project to access. To obtain this ID, call /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index from which to return the results. Use this to paginate through larger sets of data."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_list'."]:
    """Retrieve a list of cohorts for a given project.

    Use this tool to get a list of cohort views within a specified project. It is useful when tracking or analyzing different cohort data associated with a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_cohort_tracking(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project you wish to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_create'."]:
    """Logs a new view on the resource for tracking purposes.

    Use this tool to track file system views by logging a new view each time the resource is accessed. It is useful for monitoring and analyzing access patterns.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATECOHORTTRACKING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATECOHORTTRACKING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATECOHORTTRACKING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATECOHORTTRACKING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_cohorts_data(
    context: ToolContext,
    cohort_identifier: Annotated[int, "A unique integer that identifies the specific cohort you wish to retrieve data for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_retrieve'."]:
    """Retrieve cohort details and access logs for a project.

    This tool retrieves details about cohorts and logs each system view access within a specified project. It should be called when you need to track file system interactions and get specific cohort data for analysis."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_cohort_views(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    cohort_identifier: Annotated[int | None, "A unique integer identifying the specific cohort to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project being accessed. Call /api/projects/ to obtain this ID if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_update'."]:
    """Update cohort views to track new file system accesses.

    This tool updates the views of a specified cohort within a project. It logs a new file system access each time the resource is accessed, helping to track usage.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYCOHORTVIEWS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not cohort_identifier:
        missing_params.append(("cohort_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYCOHORTVIEWS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYCOHORTVIEWS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYCOHORTVIEWS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_cohort_views(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    cohort_id: Annotated[int | None, "A unique integer identifier for the cohort.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you're trying to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_partial_update'."]:
    """Update and track cohort file system views.

    This tool updates the cohort's file system views, logging each GET request as a new view. It is useful for tracking how frequently a cohort is accessed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATECOHORTVIEWS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not cohort_id:
        missing_params.append(("cohort_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATECOHORTVIEWS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATECOHORTVIEWS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATECOHORTVIEWS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def set_cohort_deleted(
    context: ToolContext,
    cohort_id: Annotated[int, "A unique integer used to identify the cohort to be marked as deleted."],  # noqa: E501
    project_id: Annotated[str, "The ID of the Datadog project you want to mark the cohort as deleted in. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_destroy'."]:
    """Mark a cohort as deleted in the Datadog project.

    Use this tool to mark a specific cohort as deleted by setting its \"deleted\" attribute to true. This approach is used instead of a hard delete."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_cohort_activity(
    context: ToolContext,
    cohort_id: Annotated[int, "A unique integer value identifying the specific cohort whose file system view logs are to be retrieved."],  # noqa: E501
    project_id: Annotated[str, "The identifier of the project to access. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_activity_retrieve_2'."]:
    """Retrieve logs of file system views for a cohort.

    This tool retrieves logs of each view on the file system for a specific cohort in a project. It should be called when there's a need to track or review the activity of a cohort by fetching the logged view data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_persons_to_static_cohort(
    context: ToolContext,
    cohort_id: Annotated[int, "A unique integer that identifies the cohort to update."],
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve it via /api/projects/."],  # noqa: E501
    person_uuids_to_add: Annotated[list[str] | None, "List of person UUIDs to add to the cohort."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_add_persons_to_static_cohort_partial_update'."]:  # noqa: E501
    """Add persons to a static cohort in Datadog.

    This tool updates a static cohort by adding new persons to it in a specified project within Datadog."""  # noqa: E501
    request_data: Any = {"person_ids": person_uuids_to_add}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/add_persons_to_static_cohort/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_cohort_calculation_history(
    context: ToolContext,
    cohort_id: Annotated[int, "A unique integer identifying the cohort to retrieve calculation history for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you are accessing. Use /api/projects/ to find IDs."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_calculation_history_retrieve'."]:  # noqa: E501
    """Retrieve calculation history for a specific cohort.

    Use this tool to access the calculation history for a given cohort within a specific project. It helps track changes and updates over time."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/calculation_history/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_static_cohort_copy(
    context: ToolContext,
    cohort_identifier: Annotated[int, "A unique integer identifying the dynamic cohort to be duplicated as a static cohort."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_duplicate_as_static_cohort_retrieve'."]:  # noqa: E501
    """Create a static copy of a dynamic cohort.

    This tool should be called when you need to turn a dynamic cohort into a static one for a specified project. It duplicates the cohort, preserving its current state as a static cohort."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/duplicate_as_static_cohort/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_cohort_persons(
    context: ToolContext,
    cohort_id: Annotated[int, "A unique integer value identifying this cohort. Required to retrieve the list of persons associated with it."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Obtain this via the /api/projects/ endpoint."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the format of the returned data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_persons_retrieve'."]:
    """Retrieve a list of persons in a specific project cohort.

    Use this tool to get a list of persons associated with a specific cohort in a project. Useful for tracking and managing cohort membership."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/persons/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_person_from_static_cohort(
    context: ToolContext,
    cohort_id: Annotated[int, "Unique integer ID for the specific cohort from which to remove the person."],  # noqa: E501
    project_id: Annotated[str, "The Project ID you want to access. Obtain it by calling /api/projects/."],  # noqa: E501
    person_uuid_to_remove: Annotated[str | None, "Provide the UUID of the person to remove from the cohort."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_remove_person_from_static_cohort_partial_update'."]:  # noqa: E501
    """Removes a person from a static cohort in a project.

    Use this tool to remove a person from a specific static cohort within a project. Useful for managing cohorts by updating their membership."""  # noqa: E501
    request_data: Any = {"person_id": person_uuid_to_remove}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/{id}/remove_person_from_static_cohort/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=cohort_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_cohort_activity(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access specific cohort activity logs. Retrieve the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'cohorts_activity_retrieve'."]:
    """Retrieve logs of cohort activity views.

    Fetches records of file system views on cohort data for a given project, logging each view as a GET request is made."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/cohorts/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_dashboard_templates(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the specific project for which you want to retrieve dashboard templates. This ID can be obtained by calling the `/api/projects/` endpoint."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of dashboard templates to return per page."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The index from which to start returning results, useful for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_list'."]:
    """Retrieve a list of dashboard templates for a project.

    Use this tool to get all available dashboard templates within a specified project. It's useful for identifying templates you can use to set up dashboards in your project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dashboard_template(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the Datadog project where you want to create the dashboard template. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_create'."]:
    """Create a new dashboard template in a Datadog project.

    This tool allows you to create a new dashboard template within a specified Datadog project. Use it when you need to set up a new dashboard template using the project's ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDASHBOARDTEMPLATE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDASHBOARDTEMPLATE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDASHBOARDTEMPLATE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDASHBOARDTEMPLATE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_dashboard_template(
    context: ToolContext,
    dashboard_template_uuid: Annotated[str, "A UUID string identifying the dashboard template to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "A string representing the ID of the project you want to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_retrieve'."]:
    """Retrieve a specific dashboard template by ID.

    Use this tool to get information about a specific dashboard template in a project. This is helpful when you need details about how dashboards are set up or to confirm template configurations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_template_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_dashboard_template(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_template_uuid: Annotated[str | None, "A UUID string that identifies the dashboard template to be modified.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique Project ID for accessing a specific Datadog project. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_update'."]:
    """Update a Datadog dashboard template.

    Call this tool to update an existing dashboard template within a specified Datadog project. Use this when you need to modify the details or configuration of a dashboard template.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYDASHBOARDTEMPLATE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_template_uuid:
        missing_params.append(("dashboard_template_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYDASHBOARDTEMPLATE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYDASHBOARDTEMPLATE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_template_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYDASHBOARDTEMPLATE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dashboard_template(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_template_id: Annotated[str | None, "A UUID string identifying the dashboard template to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    dashboard_project_id: Annotated[str | None, "Project ID to access a specific dashboard. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_partial_update'."]:  # noqa: E501
    """Partially update a dashboard template in Datadog.

    Use this tool to apply partial updates to a specific dashboard template in Datadog. This is useful for modifying specific attributes of an existing dashboard template without updating it entirely.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTEMPLATE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_template_id:
        missing_params.append(("dashboard_template_id", "path"))
    if not dashboard_project_id:
        missing_params.append(("dashboard_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTEMPLATE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTEMPLATE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_template_id, project_id=dashboard_project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTEMPLATE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_dashboard_template(
    context: ToolContext,
    dashboard_template_id: Annotated[str, "A UUID string uniquely identifying the Datadog dashboard template to be marked as deleted."],  # noqa: E501
    project_identifier: Annotated[str, "The Project ID needed to access the specific project. Obtainable via the \"/api/projects/\" endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_destroy'."]:
    """Mark a Datadog dashboard template as deleted.

    This tool marks a specified Datadog dashboard template as deleted, using a DELETE request to update its status. It's useful when you need to remove a dashboard template without hard deleting it from the Datadog system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_template_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_dashboard_template_schema(
    context: ToolContext,
    project_id: Annotated[str, "Specify the Project ID for accessing the relevant dashboard template schema. Obtain the ID via the /api/projects/ endpoint if unknown."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboard_templates_json_schema_retrieve'."]:  # noqa: E501
    """Retrieve JSON schema for dashboard templates.

    Call this tool to get the JSON schema details for dashboard templates in a specified project."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboard_templates/json_schema/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_available_dashboards(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response. Accepted values are 'json' or 'txt'."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of dashboards to return per page. This controls pagination for the results."] = None,  # noqa: E501
    start_index_for_results: Annotated[int | None, "The starting index for returning the list of dashboards, used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_list'."]:
    """Retrieve a list of dashboards for a specific project.

    This tool should be called to get information about all the dashboards available in a given project. It's useful when a user needs to see an overview of dashboards or wants to select a specific dashboard to view or edit."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format, "limit": results_per_page, "offset": start_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project for which you want to create the dashboard. Retrieve this ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the format of the dashboard creation response. Options are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_create'."]:
    """Create a new dashboard for a specified project.

    Use this tool to create a new dashboard in a specified project. This can be helpful when you need to set up dashboards to monitor or visualize project data.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDASHBOARD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDASHBOARD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDASHBOARD"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_dashboard_collaborators(
    context: ToolContext,
    dashboard_identifier: Annotated[int, "The integer ID of the dashboard for which to retrieve the list of collaborators. This ID is unique for each dashboard."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the Datadog project to access. Retrieve this by calling /api/projects."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_collaborators_list'."]:
    """Retrieve the list of collaborators for a dashboard.

    Use this tool to get a list of collaborators associated with a specific dashboard within a project on Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/collaborators/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dashboard_collaborator(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_identifier: Annotated[int | None, "The unique integer ID of the dashboard to which you want to add a collaborator.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID for accessing the project. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_collaborators_create'."]:
    """Add a collaborator to a specified dashboard.

    Use this tool to invite a new collaborator to an existing dashboard in a project. Provide the necessary project and dashboard identifiers to complete the task.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDASHBOARDCOLLABORATOR"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_identifier:
        missing_params.append(("dashboard_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDASHBOARDCOLLABORATOR"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDASHBOARDCOLLABORATOR"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/collaborators/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDASHBOARDCOLLABORATOR"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_collaborator_from_dashboard(
    context: ToolContext,
    dashboard_id: Annotated[int, "The unique identifier for the dashboard from which you want to remove the collaborator. It's required to specify which dashboard the action pertains to."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project for accessing the dashboard. Obtainable via /api/projects/."],  # noqa: E501
    user_uuid: Annotated[str, "The unique identifier of the user to be removed from the dashboard."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_collaborators_destroy'."]:  # noqa: E501
    """Remove a collaborator from a specific dashboard.

    Use this tool to remove a specific collaborator from a dashboard within a project. It is useful when managing dashboard access and permissions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/collaborators/{user__uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_id, project_id=project_id, user__uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_dashboard_shares(
    context: ToolContext,
    dashboard_identifier: Annotated[int, "The unique integer identifier for the dashboard whose sharing information is being requested."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_sharing_list'."]:
    """Retrieve information about how dashboards are shared.

    This tool provides details on the sharing settings of a specific dashboard in a project. It should be called when you need to know how a dashboard is being shared."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/sharing/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def set_dashboard_sharing_password(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_identifier: Annotated[int | None, "The identifier for the dashboard you want to configure with sharing passwords.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. To retrieve this ID, use the endpoint /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_sharing_passwords_create'."]:  # noqa: E501
    """Create a new password for dashboard sharing configuration.

    Use this tool to set a new password for sharing a specific dashboard in a project. Ideal for securing shared dashboard access in a Datadog project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["SETDASHBOARDSHARINGPASSWORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_identifier:
        missing_params.append(("dashboard_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["SETDASHBOARDSHARINGPASSWORD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["SETDASHBOARDSHARINGPASSWORD"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/sharing/passwords/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["SETDASHBOARDSHARINGPASSWORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_dashboard_sharing_password(
    context: ToolContext,
    dashboard_identifier: Annotated[int, "The unique identifier for the dashboard from which the password should be deleted. This is an integer value."],  # noqa: E501
    password_identifier: Annotated[str, "The unique identifier of the password to delete from the sharing configuration."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project you're trying to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_sharing_passwords_destroy'."]:  # noqa: E501
    """Remove a password from a dashboard's sharing configuration.

    This tool deletes a password used in the sharing configuration of a specified dashboard within a project. Call this tool to manage access by removing an existing password."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/sharing/passwords/{password_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identifier, password_id=password_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def refresh_dashboard_sharing_link(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_identification_number: Annotated[int | None, "An integer representing the specific dashboard to refresh the sharing link for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project. Retrieve it via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_sharing_refresh_create'."]:  # noqa: E501
    """Refresh the sharing link for a specific dashboard.

    This tool is used to refresh the sharing link of a dashboard within a project. It should be called when a user wants to update an existing dashboard's sharing link to extend its validity or ensure it's up to date.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARINGLINK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_identification_number:
        missing_params.append(("dashboard_identification_number", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARINGLINK"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARINGLINK"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{dashboard_id}/sharing/refresh/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), dashboard_id=dashboard_identification_number, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REFRESHDASHBOARDSHARINGLINK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_dashboard_details(
    context: ToolContext,
    dashboard_id: Annotated[int, "A unique integer value identifying the specific dashboard to retrieve details for."],  # noqa: E501
    project_id: Annotated[str, "Project ID to specify which project to access. Obtain from /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "The format in which the dashboard details should be returned. Accepted values are 'json' or 'txt'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_retrieve'."]:
    """Retrieve details of a specific dashboard.

    This tool retrieves information about a specific dashboard within a given project by its ID. It is useful for accessing details and configurations of dashboards in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "A unique integer value identifying the specific Datadog dashboard to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The Project ID to access the relevant dashboard. Use the '/api/projects/' endpoint to retrieve the ID if necessary.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format for the response, either 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_update'."]:
    """Update a specific Datadog dashboard.

    Use this tool to update the details of a specific Datadog dashboard by providing the project and dashboard IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDASHBOARD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDASHBOARD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDASHBOARD"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dashboard_partial(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "A unique integer identifying the dashboard to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you're trying to access. Use an API call to /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Defines the format of the response returned by the API. Options are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_partial_update'."]:
    """Partially update a dashboard's details.

    Use this tool to update specific fields of an existing dashboard within a project. It is suitable for cases where only certain aspects of the dashboard need modification without updating the entire dashboard's details.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDPARTIAL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDPARTIAL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDPARTIAL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDPARTIAL"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_dashboard(
    context: ToolContext,
    dashboard_id: Annotated[int, "A unique integer identifying the dashboard to delete. Specify the ID for the target dashboard."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project for accessing its dashboards. Retrieve it via /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response. Options are 'json' or 'txt'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_destroy'."]:
    """Request the deletion of a specified dashboard.

    This tool triggers the deletion process for a specified dashboard in Datadog. Although it cannot hard delete, it sets the dashboard's status to 'deleted' using a PATCH request. Use when needing to deactivate or remove a dashboard."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dashboard_tile_position(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dashboard_id: Annotated[int | None, "A unique integer value identifying the specific dashboard to update the tile position.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Obtainable via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the desired format of the response. Choose between 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_move_tile_partial_update'."]:  # noqa: E501
    """Repositions a tile on a Datadog dashboard.

    Use this tool to update the position of a tile within a specific Datadog dashboard. Ideal for organizing dashboard layouts or rearranging tiles based on preference or need.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTILEPOSITION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dashboard_id:
        missing_params.append(("dashboard_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTILEPOSITION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTILEPOSITION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{id}/move_tile/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDASHBOARDTILEPOSITION"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_dashboard_tiles(
    context: ToolContext,
    dashboard_id: Annotated[int, "A unique integer identifying the dashboard to stream metadata and tiles from."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the streamed data. Options include 'json' and 'txt'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_stream_tiles_retrieve'."]:  # noqa: E501
    """Stream metadata and tiles of a dashboard.

    Stream dashboard metadata and tiles via Server-Sent Events, starting with metadata followed by tiles as they are rendered."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/{id}/stream_tiles/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dashboard_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dashboard_from_template(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format for the response. Options are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dashboards_create_from_template_json_create'."]:  # noqa: E501
    """Create a dashboard from a template JSON.

    Use this tool to create a new dashboard in Datadog using a provided template JSON. Ideal for setting up dashboards quickly based on predefined templates.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDASHBOARDFROMTEMPLATE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDASHBOARDFROMTEMPLATE"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDASHBOARDFROMTEMPLATE"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dashboards/create_from_template_json/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDASHBOARDFROMTEMPLATE"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_data_color_themes(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project to access color themes. Retrieve the ID via /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of data color themes to return per page."] = None,  # noqa: E501
    starting_index: Annotated[int | None, "The initial index from which to start returning the results for data color themes."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'data_color_themes_list'."]:
    """Retrieve a list of data color themes for a project.

    This tool is used to fetch a list of data color themes associated with a specific project in Datadog. It should be called when users need to know the available color themes for visualizing their data under a particular project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/data_color_themes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_data_color_theme(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier of the project for which you want to create a data color theme. Retrieve this ID with a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'data_color_themes_create'."]:
    """Create a new data color theme for a project.

    Use this tool to create a new data color theme within a specified project on Datadog. This is useful when you need to apply customized color visualizations to data within a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ADDDATACOLORTHEME"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ADDDATACOLORTHEME"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ADDDATACOLORTHEME"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/data_color_themes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ADDDATACOLORTHEME"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_data_color_theme(
    context: ToolContext,
    data_color_theme_id: Annotated[int, "A unique integer value identifying the specific data color theme to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'data_color_themes_retrieve'."]:
    """Retrieve details of a specific data color theme.

    Use this tool to get detailed information about a specific data color theme for a given project. This is useful when you need to display or manage color themes within an application."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=data_color_theme_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_data_color_theme(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    color_theme_id: Annotated[int | None, "A unique integer identifying the data color theme to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you want to access. Retrieve the ID by querying /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'data_color_themes_update'."]:
    """Update the color theme for a specific project.

    This tool updates the color theme settings for a given project in Datadog. Use this when you need to change the visual representation of data by altering the color theme.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDATACOLORTHEME"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not color_theme_id:
        missing_params.append(("color_theme_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDATACOLORTHEME"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDATACOLORTHEME"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=color_theme_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDATACOLORTHEME"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_data_theme(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    theme_id: Annotated[int | None, "A unique integer value identifying the data color theme to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'data_color_themes_partial_update'."]:  # noqa: E501
    """Update a specific data color theme for a project.

    This tool updates the properties of a specific data color theme within a project. Use it to change settings or customize the appearance of data visuals by specifying the project and theme IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYDATATHEME"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not theme_id:
        missing_params.append(("theme_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYDATATHEME"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYDATATHEME"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=theme_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYDATATHEME"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_data_color_theme(
    context: ToolContext,
    data_color_theme_id: Annotated[int, "A unique integer identifying the data color theme to delete."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project containing the data color theme to delete. Retrieve this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'data_color_themes_destroy'."]:
    """Delete a data color theme from a project.

    Use this tool to delete a specific data color theme from a given project in Datadog."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/data_color_themes/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=data_color_theme_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_dataset_items(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project whose dataset items you want to retrieve. Obtainable via /api/projects/."],  # noqa: E501
    filter_by_dataset_id: Annotated[str | None, "A string representing the dataset ID to filter the results by."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of dataset items to return per page."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The initial index from which to return the dataset items, used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dataset_items_list'."]:
    """Retrieve dataset items for a specific project in Datadog.

    Use this tool to get a list of dataset items from a specific project by providing the project ID. Useful for accessing or viewing datasets associated with a particular project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dataset_items/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"dataset": filter_by_dataset_id, "limit": results_per_page, "offset": start_index}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dataset_item(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID for the target project. Obtain by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dataset_items_create'."]:
    """Create a new dataset item in a specified project.

    Use this tool to add a new dataset item to a specific project within Datadog. Call this when you need to insert data into a project's dataset.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDATASETITEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDATASETITEM"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDATASETITEM"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dataset_items/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDATASETITEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_dataset_item(
    context: ToolContext,
    dataset_item_id: Annotated[str, "The UUID identifying the specific dataset item to retrieve."],
    project_id: Annotated[str, "The ID of the project to access. Use '/api/projects/' to find this ID if needed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dataset_items_retrieve'."]:
    """Retrieve details of a specific dataset item.

    Use this tool to obtain information about a particular dataset item within a project. Useful for accessing specific data insights or details needed from Datadog's datasets."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dataset_item(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_item_id: Annotated[str | None, "A UUID string identifying the dataset item to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID of the project to access. You can find this ID by making a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dataset_items_update'."]:
    """Update an existing dataset item with new information.

    This tool updates an existing dataset item identified by project and item IDs. Use it when you need to modify details or correct information in a dataset.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDATASETITEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_item_id:
        missing_params.append(("dataset_item_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDATASETITEM"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDATASETITEM"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDATASETITEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_dataset_item(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_item_uuid: Annotated[str | None, "A UUID string identifying the dataset item to be modified.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project where the dataset item is located. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dataset_items_partial_update'."]:
    """Update specific details of a dataset item.

    Use this tool to partially update attributes of a dataset item within a project. The tool should be called when you need to modify existing data associated with a dataset item.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYDATASETITEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_item_uuid:
        missing_params.append(("dataset_item_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYDATASETITEM"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYDATASETITEM"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYDATASETITEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def set_dataset_item_deleted(
    context: ToolContext,
    dataset_item_uuid: Annotated[str, "A UUID string identifying the specific dataset item to mark as deleted."],  # noqa: E501
    project_identifier: Annotated[str, "ID of the project to access. To find this, call /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'dataset_items_destroy'."]:
    """Mark a dataset item as deleted in a project.

    This tool sets a dataset item's \"deleted\" status to true for a specific project. A hard delete is not permitted, so use this tool to logically delete an item instead."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/dataset_items/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_item_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_datasets(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access datasets for. Use /api/projects/ to find this ID."],  # noqa: E501
    dataset_ids: Annotated[list[str] | None, "A list of dataset IDs. Can include multiple IDs separated by commas."] = None,  # noqa: E501
    initial_result_index: Annotated[int | None, "The initial index from which to return the results."] = None,  # noqa: E501
    order_datasets_by: Annotated[list[str] | None, "Specify the order of dataset results. Options: 'created_at', '-created_at', 'updated_at', '-updated_at'."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results returned per page. This determines how many datasets are retrieved in one API call."] = None,  # noqa: E501
    search_query: Annotated[str | None, "Search within dataset name, description, or metadata using a keyword or phrase."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'datasets_list'."]:
    """Retrieve a list of datasets for a specific project.

    Use this tool to get all datasets associated with a particular project by providing the project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/datasets/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"id__in": dataset_ids, "limit": results_per_page, "offset": initial_result_index, "order_by": order_datasets_by, "search": search_query}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_dataset_project(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project where the dataset will be created. Obtainable via the /api/projects/ call.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'datasets_create'."]:
    """Create a new dataset within a specified project.

    This tool is used to create a new dataset for a specified project in Datadog. It should be called when you need to add a dataset to an existing project, identified by its project ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDATASETPROJECT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDATASETPROJECT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDATASETPROJECT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/datasets/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDATASETPROJECT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_dataset_info(
    context: ToolContext,
    dataset_identifier: Annotated[str, "A UUID string identifying the specific dataset to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Use /api/projects/ to retrieve project IDs."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'datasets_retrieve'."]:
    """Retrieve details of a specific dataset in a project.

    This tool fetches detailed information about a specific dataset within a given project when the project ID and dataset ID are provided."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dataset(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_identifier: Annotated[str | None, "A UUID string identifying the dataset to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'datasets_update'."]:
    """Update a specific dataset within a project.

    Use this tool to update the details of a specific dataset within a given project in Datadog. Useful for modifying existing datasets when changes are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDATASET"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_identifier:
        missing_params.append(("dataset_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDATASET"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDATASET"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDATASET"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_dataset_info(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    dataset_uuid: Annotated[str | None, "A UUID string that uniquely identifies the dataset to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to be accessed. Retrieve using a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'datasets_partial_update'."]:
    """Update specific dataset information in a project.

    Call this tool to update specific details of a dataset within a project in Datadog. Useful for modifying metadata or configurations of existing datasets.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDATASETINFO"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not dataset_uuid:
        missing_params.append(("dataset_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDATASETINFO"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDATASETINFO"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDATASETINFO"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_dataset_by_id(
    context: ToolContext,
    dataset_uuid: Annotated[str, "A UUID string that uniquely identifies the dataset to be marked as deleted within the project."],  # noqa: E501
    project_identifier: Annotated[str, "Provide the Project ID for accessing the desired project. Use the /api/projects/ endpoint to locate the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'datasets_destroy'."]:
    """Facilitates marking a dataset as deleted in a project.

    Use this tool to effectively mark a dataset as deleted within a project by utilizing a patch API call to set \"deleted\" to true, aligning with the Datadog API constraints."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/datasets/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=dataset_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_early_access_features(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to retrieve early access features for. Obtainable via /api/projects/."],  # noqa: E501
    number_of_results_per_page: Annotated[int | None, "Specify the number of results to return per page for early access features."] = None,  # noqa: E501
    result_start_index: Annotated[int | None, "The initial index from which to return the results when paginating through early access features."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'early_access_feature_list'."]:
    """Retrieve a list of early access features for a project.

    This tool retrieves a list of early access features available for a specific project on Datadog. It should be called when users want to see what early access features they can enable or explore for their project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/early_access_feature/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": number_of_results_per_page, "offset": result_start_index}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_early_access_feature_tracking(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID to access specific project features. Retrieve this ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'early_access_feature_create'."]:
    """Create tracking for early access feature views.

    Use this tool to create tracking for views on an early access feature within a project. Each GET request on the feature resource logs a new view.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEARLYACCESSFEATURETRACKING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEARLYACCESSFEATURETRACKING"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEARLYACCESSFEATURETRACKING"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/early_access_feature/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEARLYACCESSFEATURETRACKING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_early_access_feature(
    context: ToolContext,
    feature_uuid: Annotated[str, "A UUID string identifying the early access feature to retrieve."],
    project_identifier: Annotated[str, "The unique ID of the project you want to access. Retrieve this by calling the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'early_access_feature_retrieve'."]:
    """Retrieve information about an early access feature.

    Call this tool to get details about a specific early access feature in a project. Useful for tracking file system views related to the feature."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/early_access_feature/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_early_access_feature(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    early_access_feature_id: Annotated[str | None, "A UUID string identifying the early access feature to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique identifier for the project. Fetch it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'early_access_feature_update'."]:
    """Update early access feature for a project.

    Use this tool to update the details of an early access feature in a specified project. It logs each update operation.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYEARLYACCESSFEATURE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not early_access_feature_id:
        missing_params.append(("early_access_feature_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYEARLYACCESSFEATURE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYEARLYACCESSFEATURE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/early_access_feature/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=early_access_feature_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYEARLYACCESSFEATURE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_early_access_feature(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    early_access_feature_id: Annotated[str | None, "A UUID string identifying the specific early access feature.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Retrieve this from the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'early_access_feature_partial_update'."]:  # noqa: E501
    """Update an early access feature for a project.

    This tool updates an early access feature for a specific project by partially modifying its properties. When a GET request is made on the resource, it logs a new view, facilitating tracking of file system views for the project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEEARLYACCESSFEATURE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not early_access_feature_id:
        missing_params.append(("early_access_feature_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEEARLYACCESSFEATURE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEEARLYACCESSFEATURE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/early_access_feature/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=early_access_feature_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEEARLYACCESSFEATURE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_early_access_feature(
    context: ToolContext,
    early_access_feature_id: Annotated[str, "A UUID string that identifies the specific early access feature to be removed."],  # noqa: E501
    project_id_for_removal: Annotated[str, "Project ID to identify the project for accessing or removing the early access feature. Use the /api/projects/ endpoint to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'early_access_feature_destroy'."]:
    """Remove an early access feature from a project.

    Use this tool to delete an early access feature from a specific project. Useful for managing and updating project features."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/early_access_feature/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=early_access_feature_id, project_id=project_id_for_removal),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_posthog_endpoint_run(
    context: ToolContext,
    endpoint_name: Annotated[str, "The name of the Datadog endpoint to retrieve details for. This specifies which endpoint's run details you want to access."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'endpoints_run_retrieve'."]:
    """Retrieve details of a specific Datadog endpoint run.

    This tool retrieves information about a specific run of a Datadog endpoint for a given project and endpoint name. It should be called when you need to access details of an endpoint run using project and endpoint identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/endpoints/{name}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), name=endpoint_name, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_endpoint(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    endpoint_name: Annotated[str | None, "The name of the endpoint to be updated. This is a required string parameter.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID to access the specific project. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'endpoints_run_create'."]:
    """Update an existing endpoint run in a project.

    Use this tool to update an existing endpoint run in a specified project with optional parameters.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEENDPOINT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not endpoint_name:
        missing_params.append(("endpoint_name", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEENDPOINT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEENDPOINT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/endpoints/{name}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), name=endpoint_name, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEENDPOINT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_recent_execution_times(
    context: ToolContext,
    endpoint_names: Annotated[list[str], "An array of endpoint names to retrieve execution times for, within the specified project."],  # noqa: E501
    project_id: Annotated[str, "The Project ID you want to access. Retrieve it using /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'endpoints_last_execution_times_create'."]:  # noqa: E501
    """Fetch the last 6 months of execution times for endpoints.

    Use this tool to obtain the last execution times for multiple endpoints within a specified project over the past 6 months."""  # noqa: E501
    request_data: Any = {"names": endpoint_names}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/endpoints/last_execution_times/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_environments(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project whose environments you want to list. Retrieve this by calling `/api/projects/`."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The initial index from which to return the results, used to paginate."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "The number of environments to return on each page of results. Specify an integer value."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_list'."]:
    """Get a list of environments for a specific project.

    Use this tool to retrieve all environments within a given project for your organization."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_result_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it by calling `/api/projects/`.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_create'."]:
    """Create a new environment for a specific project.

    Use this tool to create a new environment within a specified project in the current organization. Ideal for setting up workspaces for development, testing, or production phases.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROJECTENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROJECTENVIRONMENT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROJECTENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROJECTENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_environment_details(
    context: ToolContext,
    environment_id: Annotated[int, "Unique integer identifying the environment (or team) to retrieve details for."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access specific project details. Retrieve this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_retrieve'."]:
    """Retrieve details of a specific environment within a project.

    Call this tool to fetch detailed information about an environment in a specific project. This is useful when you need to access or display data about a particular environment setup in the organization's projects."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def edit_project_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_identifier: Annotated[int | None, "A unique integer identifying the environment (aka team) for modification.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "String ID of the project to access. Obtain ID via /api/projects/ call.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_update'."]:
    """Update environment settings for a specified project.

    This tool updates the environment configuration for a specific project within the current organization on Datadog. It should be called when modifying environment details like settings or parameters in a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EDITPROJECTENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_identifier:
        missing_params.append(("environment_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EDITPROJECTENVIRONMENT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EDITPROJECTENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EDITPROJECTENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_project_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_identifier: Annotated[int | None, "A unique integer identifying the environment or team to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access. Use /api/projects/ to find the Project ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_partial_update'."]:
    """Update a specific environment of a project.

    Use this tool to update the details of a specific environment within a project for the current organization. Ideal for modifying environment configurations or settings.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYPROJECTENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_identifier:
        missing_params.append(("environment_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYPROJECTENVIRONMENT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYPROJECTENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYPROJECTENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_environment(
    context: ToolContext,
    environment_id: Annotated[int, "A unique integer identifying the environment to delete."],
    project_identifier: Annotated[str, "The ID of the project you're trying to access. Find this by calling the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_destroy'."]:
    """Delete a specific environment from a project.

    Use this tool to delete an environment from a specific project in the current organization. Call this tool when you need to remove an existing environment by specifying the project and environment IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_environment_activity(
    context: ToolContext,
    environment_id: Annotated[int, "A unique integer identifying the environment (aka team)."],
    project_identifier: Annotated[str, "The unique identifier for the project you wish to access. Obtainable by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_activity_retrieve'."]:
    """Retrieve project environment activity details.

    Fetches the activity details for a specific environment within a given project in the current organization."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_project_environment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_identifier: Annotated[int | None, "A unique integer that identifies the environment or team.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to be accessed. Obtainable via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_add_product_intent_partial_update'."]:  # noqa: E501
    """Update product intent for a project environment.

    Use this tool to update or modify the product intent for a specific environment within a project in the current organization.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROJECTENVIRONMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_identifier:
        missing_params.append(("environment_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROJECTENVIRONMENT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROJECTENVIRONMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/add_product_intent/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROJECTENVIRONMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def complete_project_onboarding(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_id: Annotated[int | None, "A unique integer value identifying this environment (aka team).  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve this by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_complete_product_onboarding_partial_update'."]:  # noqa: E501
    """Mark a project's product onboarding as complete in an organization.

    Use this tool to update and complete the product onboarding process for a specific project within the current organization. It is applicable when an onboarding process needs to be marked as finished.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["COMPLETEPROJECTONBOARDING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_id:
        missing_params.append(("environment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["COMPLETEPROJECTONBOARDING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["COMPLETEPROJECTONBOARDING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/complete_product_onboarding/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["COMPLETEPROJECTONBOARDING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_default_evaluation_tags(
    context: ToolContext,
    environment_id: Annotated[int, "A unique integer value identifying the environment or team for tag retrieval."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project. Retrieve the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_default_evaluation_tags_retrieve'."]:  # noqa: E501
    """Retrieve default evaluation tags for a project environment.

    Fetches the default evaluation tags associated with a specified project environment in Datadog. Useful for managing and reviewing tags related to evaluations for team environments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/default_evaluation_tags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_default_evaluation_tags(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_id: Annotated[int | None, "A unique integer value identifying the environment (team) for which to manage evaluation tags.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access for managing evaluation tags. Retrieve using /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_default_evaluation_tags_create'."]:  # noqa: E501
    """Manage default evaluation tags for a team environment.

    Use this tool to create or manage default evaluation tags for a specific team environment in a Datadog project. Call this tool when you need to set tags that will be applied by default to the evaluations within an environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEDEFAULTEVALUATIONTAGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_id:
        missing_params.append(("environment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEDEFAULTEVALUATIONTAGS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEDEFAULTEVALUATIONTAGS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/default_evaluation_tags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEDEFAULTEVALUATIONTAGS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_default_evaluation_tags(
    context: ToolContext,
    environment_identifier: Annotated[int, "A unique integer identifying the environment (or team) for tag management."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access. Find this ID through a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_default_evaluation_tags_destroy'."]:  # noqa: E501
    """Delete default evaluation tags for a project environment.

    Use this tool to remove default evaluation tags associated with a specified project environment. It's useful when tags need to be cleaned up or updated for project management."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/default_evaluation_tags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_env_secret_token_backup(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_id: Annotated[int | None, "A unique integer identifying the environment (aka team) to target for deletion.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The Project ID to access for managing secret token backups. Retrieve IDs via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_delete_secret_token_backup_partial_update'."]:  # noqa: E501
    """Deletes a secret token backup in a project environment.

    Use this tool to delete a secret token backup for a specified project environment in Datadog. It should be called when needing to manage secret backups within a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DELETEENVSECRETTOKENBACKUP"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_id:
        missing_params.append(("environment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DELETEENVSECRETTOKENBACKUP"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DELETEENVSECRETTOKENBACKUP"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/delete_secret_token_backup/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DELETEENVSECRETTOKENBACKUP"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_event_restrictions(
    context: ToolContext,
    environment_identifier: Annotated[int, "A unique integer identifying the environment (team) for which to retrieve event restrictions."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve it via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_event_ingestion_restrictions_retrieve'."]:  # noqa: E501
    """Retrieve event ingestion restrictions for a project environment.

    Call this tool to get information about event ingestion restrictions for a specific environment within a project. Useful for understanding data handling limits or constraints in your organization's projects."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/event_ingestion_restrictions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def demo_data_status(
    context: ToolContext,
    environment_id: Annotated[int, "A unique integer value identifying the environment (aka team) for which you want to check demo data status."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project to access. Retrieve ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_is_generating_demo_data_retrieve'."]:  # noqa: E501
    """Check if an environment is generating demo data.

    Retrieve the status of demo data generation for a specific environment within a project for the current organization. Use this to determine if demo data is being generated in a specific environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/is_generating_demo_data/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reset_project_environment_token(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_identifier: Annotated[int | None, "A unique integer value identifying the environment or team.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_reset_token_partial_update'."]:  # noqa: E501
    """Resets the token for a specified project environment.

    Use this tool to reset the token for a specific environment within a project in the current organization. This is useful for refreshing security credentials or regenerating authentication tokens.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RESETPROJECTENVIRONMENTTOKEN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_identifier:
        missing_params.append(("environment_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RESETPROJECTENVIRONMENTTOKEN"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RESETPROJECTENVIRONMENTTOKEN"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/reset_token/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RESETPROJECTENVIRONMENTTOKEN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def rotate_environment_secret_token(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    environment_id: Annotated[int | None, "A unique integer identifying the environment or team to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID for the environment. Obtainable by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'environments_rotate_secret_token_partial_update'."]:  # noqa: E501
    """Rotate the secret token for a project environment.

    Use this tool to rotate the secret token of a specified project environment. It is typically called when token renewal is required for security or operational reasons.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ROTATEENVIRONMENTSECRETTOKEN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not environment_id:
        missing_params.append(("environment_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ROTATEENVIRONMENTSECRETTOKEN"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ROTATEENVIRONMENTSECRETTOKEN"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/environments/{id}/rotate_secret_token/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=environment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ROTATEENVIRONMENTSECRETTOKEN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_event_definitions(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access event definitions. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'event_definitions_retrieve'."]:
    """Retrieve event definitions for a specified project.

    This tool is used to retrieve all event definitions associated with a given project ID from Datadog. It is helpful for monitoring or managing project events."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/event_definitions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_event_definition(
    context: ToolContext,
    event_definition_id: Annotated[str, "A UUID string identifying the specific event definition to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Find this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'event_definitions_retrieve_2'."]:
    """Retrieve details of a specific event definition by ID.

    Use this tool to get detailed information about a specific event definition in a project by providing the project ID and event definition ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/event_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_definition_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_event_definition(
    context: ToolContext,
    event_definition_id: Annotated[str, "A UUID string identifying the event definition to update."],  # noqa: E501
    project_id: Annotated[str, "Project ID of the project you're trying to access. Retrieve the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'event_definitions_update'."]:
    """Update an existing event definition in a project.

    This tool updates an existing event definition within a specified project. Call this tool when you need to modify the details of an event definition on Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/event_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_definition_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_event_definition(
    context: ToolContext,
    event_definition_uuid: Annotated[str, "A UUID string identifying the event definition to be updated."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the specific project in Datadog. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'event_definitions_partial_update'."]:  # noqa: E501
    """Update an event definition in a project.

    Use this tool to partially update event definitions within a specified project in Datadog. It modifies details of an existing event definition using a PATCH request."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/event_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_definition_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_event_definition(
    context: ToolContext,
    event_definition_id: Annotated[str, "A UUID string that uniquely identifies the event definition to be deleted."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID of the target project. Retrieve this ID via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'event_definitions_destroy'."]:
    """Delete an event definition by ID and project.

    This tool deletes a specific event definition within a given project based on the provided IDs. It should be called when you need to permanently remove an event definition from a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/event_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_definition_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_event_definition_metrics(
    context: ToolContext,
    event_definition_id: Annotated[str, "A UUID string identifying the specific event definition."],
    project_identifier: Annotated[str, "The unique ID of the project to access. Retrieve this via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'event_definitions_metrics_retrieve'."]:  # noqa: E501
    """Retrieve metrics for a specific event definition.

    This tool retrieves metrics associated with a specific event definition within a project. It is useful for analyzing or monitoring event-related data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/event_definitions/{id}/metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_definition_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_event_details(
    context: ToolContext,
    event_id: Annotated[str, "The unique identifier for the event you want to retrieve details about."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtain it with a call to /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'events_retrieve'."]:
    """Retrieve details of a specific event.

    Use this tool to get detailed information about a particular event by providing the project and event identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/events/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=event_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_event_values(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access specific event data. Obtain by calling /api/projects/."],  # noqa: E501
    output_format: Annotated[str | None, "Specifies the format of the retrieved event values. Acceptable values are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'events_values_retrieve'."]:
    """Retrieve event values for a specified project.

    This tool retrieves the event values for a specific project in DataDog. Call this tool when you need to access or analyze event-related data within a particular project context."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/events/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_experiment_holdouts(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project for which you want to retrieve experiment holdouts. Obtain this ID by calling the `/api/projects/` endpoint."],  # noqa: E501
    initial_index: Annotated[int | None, "The initial index from which to return the results. Used for pagination in retrieving experiment holdouts."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page for the query."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_holdouts_list'."]:
    """Retrieve the list of experiment holdouts for a project.

    Use this tool to get a list of experiment holdouts associated with a specific project in Datadog. Ideal for when you need to analyze or review holdout data for experiments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_holdouts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_experiment_holdout(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project you want to access. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_holdouts_create'."]:
    """Create a new experiment holdout within a project.

    Use this tool to create a new holdout for an experiment within a specified project in DataDog. This is useful for setting aside a portion of data for control group purposes during experimentation.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTHOLDOUT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTHOLDOUT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTHOLDOUT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_holdouts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTHOLDOUT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_experiment_holdout(
    context: ToolContext,
    experiment_holdout_id: Annotated[int, "A unique integer value identifying the specific experiment holdout."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project you want to access. Retrieve this ID using a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_holdouts_retrieve'."]:
    """Retrieve details of a specific experiment holdout from a project.

    Use this tool to obtain detailed information about a particular experiment holdout within a specified project, identified by project and experiment holdout IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_holdouts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_holdout_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_experiment_holdout(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_holdout_id: Annotated[int | None, "Unique integer identifying the specific experiment holdout to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access for updating the experiment holdout. Retrieve this by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_holdouts_update'."]:
    """Update an experiment holdout in a specific project.

    Use this tool to modify the details of an existing experiment holdout in a project. This action is performed within the Datadog platform using a specific project and holdout ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTHOLDOUT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_holdout_id:
        missing_params.append(("experiment_holdout_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTHOLDOUT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTHOLDOUT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_holdouts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_holdout_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTHOLDOUT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_experiment_holdout(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_holdout_id: Annotated[int | None, "The unique integer identifier for the experiment holdout you wish to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    target_project_id: Annotated[str | None, "Specify the ID of the project you want to access. Retrieve the ID using /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_holdouts_partial_update'."]:  # noqa: E501
    """Update the details of an experiment holdout.

    Use this tool to partially update the details of an experiment holdout within a specified project in Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYEXPERIMENTHOLDOUT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_holdout_id:
        missing_params.append(("experiment_holdout_id", "path"))
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYEXPERIMENTHOLDOUT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYEXPERIMENTHOLDOUT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_holdouts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_holdout_id, project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYEXPERIMENTHOLDOUT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_experiment_holdout(
    context: ToolContext,
    experiment_holdout_id: Annotated[int, "A unique integer identifying the experiment holdout to be deleted."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project from which to delete the experiment holdout. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_holdouts_destroy'."]:
    """Delete an experiment holdout from a project.

    Use this tool to delete a specific experiment holdout from a given project in Datadog. This can be useful when you need to manage or update experiments and wish to remove outdated or unnecessary holdouts."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_holdouts/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_holdout_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_experiment_saved_metrics(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain the ID by calling /api/projects/."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The starting index for returning results, used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of metric results to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_saved_metrics_list'."]:
    """Retrieve saved metrics for an experiment in a project.

    Use this tool to get a list of saved metrics from an experiment within a specified project. This helps in analyzing experiment results and performance."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_saved_metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_result_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_experiment_saved_metrics(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project for which you want to create and save experiment metrics. Obtain from /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_saved_metrics_create'."]:
    """Create and save metrics for an experiment in a project.

    Use this tool to create and save experiment metrics within a specified project. It is useful when you need to add new metrics to an experiment's saved data.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTSAVEDMETRICS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTSAVEDMETRICS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTSAVEDMETRICS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_saved_metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTSAVEDMETRICS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_experiment_metrics(
    context: ToolContext,
    experiment_metric_id: Annotated[int, "A unique integer value identifying the experiment's saved metric to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project for which you want to retrieve saved experiment metrics. Obtain this by making a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_saved_metrics_retrieve'."]:  # noqa: E501
    """Retrieve saved experiment metrics from a project.

    Use this tool to fetch saved metrics for a specific experiment within a project. It is called when there's a need to obtain details about experiment metrics stored in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_saved_metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_metric_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_experiment_saved_metrics(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_metric_id: Annotated[int | None, "A unique integer identifying the specific experiment saved metric to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the Datadog project containing the experiment whose metrics you wish to update. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_saved_metrics_update'."]:
    """Update saved metrics for a specific experiment in Datadog.

    Use this tool to update the saved metrics for a specific experiment in a Datadog project. It requires the project ID and metric ID to identify the correct records to update.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTSAVEDMETRICS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_metric_id:
        missing_params.append(("experiment_metric_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTSAVEDMETRICS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTSAVEDMETRICS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_saved_metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_metric_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTSAVEDMETRICS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_experiment_metrics(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_metric_id: Annotated[int | None, "A unique integer identifying the experiment saved metric to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Obtain it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_saved_metrics_partial_update'."]:  # noqa: E501
    """Update saved metrics for a specific experiment.

    This tool updates specific saved metrics for an experiment within a given project. Use this tool when you need to modify the details of already saved metrics for an experiment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTMETRICS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_metric_id:
        missing_params.append(("experiment_metric_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTMETRICS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTMETRICS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_saved_metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_metric_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTMETRICS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_saved_metric(
    context: ToolContext,
    experiment_metric_id: Annotated[int, "A unique integer identifying the experiment saved metric to delete."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project containing the saved metric to delete. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiment_saved_metrics_destroy'."]:  # noqa: E501
    """Deletes a saved experimental metric.

    Use this tool to delete an experimental saved metric from a specific project. It ensures that the specified metric entry is fully removed."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiment_saved_metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_metric_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_posthog_experiments(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the Datadog project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
    page_result_limit: Annotated[int | None, "The number of experiment results to return per page. Specify as an integer."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The index from which to start returning results. Used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_list'."]:
    """Retrieve a list of experiments from a Datadog project.

    Use this tool to get a list of all experiments associated with a specific Datadog project. It should be called when you need to access experiment data for a particular project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": page_result_limit, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_experiment_in_project(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id_for_experiment_creation: Annotated[str | None, "The ID of the project where the experiment will be created. Obtain this by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_create'."]:
    """Create a new experiment within a specified project.

    This tool allows you to create a new experiment within a specified project using the Datadog API. It should be called when you want to set up and organize a new experiment under a particular project ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTINPROJECT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id_for_experiment_creation:
        missing_params.append(("project_id_for_experiment_creation", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTINPROJECT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTINPROJECT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_experiment_creation),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTINPROJECT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_experiment_details(
    context: ToolContext,
    experiment_id: Annotated[int, "A unique integer identifying the experiment to retrieve details for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_retrieve'."]:
    """Retrieve details of a specific experiment within a project.

    Use this tool to get detailed information about a specific experiment within a given project in Datadog. Useful for monitoring, analysis, or troubleshooting purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_experiment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_id: Annotated[int | None, "A unique integer that identifies the experiment to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique string ID of the project to be accessed. Retrieve by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_update'."]:
    """Update details of a specific experiment in a project.

    This tool updates the settings or details of an existing experiment within a specified project on Datadog. It is triggered when a user needs to change experiment parameters or information.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_id:
        missing_params.append(("experiment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_experiment_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_id: Annotated[int | None, "A unique integer value identifying the experiment to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Provide the ID of the project you want to access. Use the /api/projects/ endpoint to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_partial_update'."]:
    """Partially update experiment details in a project.

    Use this tool to update specific details of an experiment within a project. Provide the project ID and the experiment ID to apply partial updates.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_id:
        missing_params.append(("experiment_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEEXPERIMENTDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_experiment(
    context: ToolContext,
    experiment_id: Annotated[int, "A unique integer value used to identify the experiment to be marked as deleted."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project containing the experiment to be deleted. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_destroy'."]:
    """Delete an experiment by setting it as deleted.

    This tool is used to mark an experiment as deleted in a project. Hard deletion is not allowed, so this tool performs a soft delete by setting the experiment's \"deleted\" status to true."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_exposure_cohort_for_experiment(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_id: Annotated[int | None, "A unique integer used to identify the specific experiment.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique identifier for the project you're accessing. Obtain this via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_create_exposure_cohort_for_experiment_create'."]:  # noqa: E501
    """Create an exposure cohort for an experiment.

    This tool is used to create an exposure cohort for a specific experiment within a project on Datadog. It is suitable for users who need to assign a new group for exposure in their experiment workflow.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEXPOSURECOHORTFOREXPERIMENT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_id:
        missing_params.append(("experiment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEXPOSURECOHORTFOREXPERIMENT"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEXPOSURECOHORTFOREXPERIMENT"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/create_exposure_cohort_for_experiment/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEXPOSURECOHORTFOREXPERIMENT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def duplicate_experiment_posthog(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_id: Annotated[int | None, "Unique integer to identify the experiment to duplicate.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access in Datadog. Obtain this by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_duplicate_create'."]:
    """Create a duplicate of a specific experiment.

    Use this tool to duplicate an existing experiment within a specified Datadog project. It helps in creating a copy of an experiment for further testing or analysis.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DUPLICATEEXPERIMENTPOSTHOG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_id:
        missing_params.append(("experiment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DUPLICATEEXPERIMENTPOSTHOG"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DUPLICATEEXPERIMENTPOSTHOG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/duplicate/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DUPLICATEEXPERIMENTPOSTHOG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_experiment_timeseries_recalculation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    experiment_id: Annotated[int | None, "A unique integer value identifying this experiment for recalculation.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique identifier of the project you want to access for the recalculation. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_recalculate_timeseries_create'."]:  # noqa: E501
    """Initiate recalculation of experiment timeseries data.

    Use this tool to create a recalculation request for experiment timeseries data by providing the necessary metric object and its fingerprint. Useful for updating and analyzing experiment data metrics.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTTIMESERIESRECALCULATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not experiment_id:
        missing_params.append(("experiment_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTTIMESERIESRECALCULATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTTIMESERIESRECALCULATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/recalculate_timeseries/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEXPERIMENTTIMESERIESRECALCULATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_experiment_timeseries(
    context: ToolContext,
    experiment_id: Annotated[int, "A unique integer identifying the experiment to retrieve timeseries data for."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project to access. Retrieve the ID with a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_timeseries_results_retrieve'."]:  # noqa: E501
    """Retrieve timeseries data for an experiment-metric pair.

    This tool retrieves timeseries results for a specified experiment and metric combination by aggregating daily results into a compatible format for frontend use. It requires the metric's UUID and its configuration fingerprint."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/{id}/timeseries_results/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_experiments_eligible_feature_flags(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_eligible_feature_flags_retrieve'."]:  # noqa: E501
    """Retrieve feature flags eligible for experiments.

    This tool retrieves a list of feature flags that can be used in experiments. Eligible flags must be multivariate with at least two variants and have 'control' as the first variant key. You can filter results by flag key, name, active status, creator ID, order, and evaluation runtime. Pagination options include limit and offset."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/eligible_feature_flags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_experiments_flag_status(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access for flag implementation status retrieval. Obtain using /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'experiments_requires_flag_implementation_retrieve'."]:  # noqa: E501
    """Retrieve status of experiments requiring flag implementation.

    This tool retrieves information about experiments in a specific project that require flag implementation. It should be called when you need to track or manage feature flag dependencies in experiments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/experiments/requires_flag_implementation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_exports(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access exports for. Use /api/projects/ to find the project ID."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page for export details."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The initial index to start returning results from. Use this to paginate results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'exports_list'."]:
    """Retrieve a list of exports for a given project ID.

    Use this tool to get a list of export data associated with a specific project ID. It helps in obtaining export details available for any project in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_exports(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier of the Datadog project to initiate exports. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'exports_create'."]:
    """Initiate the export process for Datadog projects.

    Use this tool to start the export process for a specified Datadog project by providing the project ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEXPORTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEXPORTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEXPORTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/exports/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEXPORTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_export(
    context: ToolContext,
    export_id: Annotated[int, "Unique integer to identify the exported asset."],
    project_id: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the project ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'exports_retrieve'."]:
    """Retrieve data of a specific project export.

    Use this tool to get export data for a specific project by providing the project and export IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/exports/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=export_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_exported_content(
    context: ToolContext,
    exported_asset_id: Annotated[int, "A unique integer identifying the exported asset."],
    project_identifier: Annotated[str, "The ID of the project you want to access. Use /api/projects/ to find the project ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'exports_content_retrieve'."]:
    """Retrieve exported content from a specific project.

    Use this tool to obtain the exported content from a specified project in Datadog by providing the project ID and export ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/exports/{id}/content/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=exported_asset_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_feature_flags(
    context: ToolContext,
    project_identifier: Annotated[str, "The identifier for the project to access feature flags. Retrieve using /api/projects/."],  # noqa: E501
    exclude_feature_flag_keys: Annotated[str | None, "A JSON-encoded list of feature flag keys to exclude from the results. Useful for filtering."] = None,  # noqa: E501
    feature_flag_search_term: Annotated[str | None, "Search for a feature flag by its key or name, case insensitive."] = None,  # noqa: E501
    filter_by_active_status: Annotated[str | None, "Filter feature flags by active status. Use 'STALE', 'false', or 'true'."] = None,  # noqa: E501
    filter_by_evaluation_runtime: Annotated[str | None, "Filter feature flags by their evaluation runtime. Options: 'both', 'client', 'server'."] = None,  # noqa: E501
    filter_by_tags: Annotated[str | None, "A JSON-encoded list of tag names to filter feature flags by. Use this to specify which tags should be included in the results."] = None,  # noqa: E501
    flag_type: Annotated[str | None, "Specifies the feature flag type to filter results. Options are 'boolean', 'experiment', or 'multivariant'."] = None,  # noqa: E501
    initial_creator_user_id: Annotated[str | None, "The User ID that initially created the feature flag. It helps filter feature flags created by a specific user."] = None,  # noqa: E501
    results_offset_index: Annotated[int | None, "The starting index for the results to be returned."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of feature flags to return for each page of results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_list'."]:
    """Retrieve feature flags for a specified project.

    Use this tool to fetch all feature flags associated with a given project. Useful for managing and reviewing the state of feature flags within an application."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"active": filter_by_active_status, "created_by_id": initial_creator_user_id, "evaluation_runtime": filter_by_evaluation_runtime, "excluded_properties": exclude_feature_flag_keys, "limit": results_per_page, "offset": results_offset_index, "search": feature_flag_search_term, "tags": filter_by_tags, "type": flag_type}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_feature_flag(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_unique_identifier: Annotated[str | None, "The unique identifier for the project to access. Retrieve it by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_create'."]:
    """Create a new feature flag in a specific project.

    Use this tool to create a feature flag within a specified project on the Datadog platform. Ideal for managing feature flags in applications.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_unique_identifier:
        missing_params.append(("project_unique_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAG"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_unique_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_feature_flags(
    context: ToolContext,
    feature_flag_identifier: Annotated[int, "The unique integer ID that identifies the specific feature flag to retrieve."],  # noqa: E501
    project_id: Annotated[str, "ID of the project to access. Retrieve by calling /api/projects/."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_retrieve'."]:
    """Retrieve details of a specific feature flag.

    This tool retrieves information about a specific feature flag within a given project. It should be called when you need to check the status or properties of a feature flag. Use it to ensure feature flags are correctly set for specific users or conditions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_feature_flags(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    feature_flag_id: Annotated[int | None, "A unique integer identifying the feature flag to modify.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_update'."]:
    """Update existing feature flags in a project.

    This tool updates the details of a feature flag in a specified project within Datadog. Use this tool to modify feature flag settings, such as enabling, disabling, or changing conditions.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYFEATUREFLAGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not feature_flag_id:
        missing_params.append(("feature_flag_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYFEATUREFLAGS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYFEATUREFLAGS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYFEATUREFLAGS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_feature_flags(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    feature_flag_id: Annotated[int | None, "A unique integer value identifying the specific feature flag to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique identifier for the project to access. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_partial_update'."]:
    """Update feature flags for a specific project.

    Use this tool to update existing feature flags within a specified project in Datadog. This is useful for modifying feature settings without requiring a full create or delete operation.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEFEATUREFLAGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not feature_flag_id:
        missing_params.append(("feature_flag_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEFEATUREFLAGS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEFEATUREFLAGS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEFEATUREFLAGS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def mark_feature_flag_deleted(
    context: ToolContext,
    feature_flag_id: Annotated[int, "A unique integer value used to identify the feature flag."],
    project_identifier: Annotated[str, "Project ID to access a specific project. Retrieve by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_destroy'."]:
    """Mark a feature flag as deleted.

    This tool marks a feature flag as deleted by setting its \"deleted\" status to true. It should be used when you need to effectively delete a feature flag within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_feature_flag_activity(
    context: ToolContext,
    feature_flag_id: Annotated[int, "A unique integer identifying the feature flag to retrieve activity for."],  # noqa: E501
    project_identifier: Annotated[str, "Unique identifier for the project to access. Obtain from the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_activity_retrieve_2'."]:  # noqa: E501
    """Retrieve activity details for a specific feature flag.

    Call this tool to get the activity details of a specific feature flag in a given project. Useful for monitoring changes and updates to feature flags."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_static_cohort_for_feature_flag(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    feature_flag_id: Annotated[int | None, "A unique integer value identifying the specific feature flag to create a static cohort for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access for creating a static cohort for the feature flag. Retrieve via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_create_static_cohort_for_flag_create'."]:  # noqa: E501
    """Create a static cohort for a specific feature flag.

    This tool is used to create a static cohort for a specified feature flag within a given project. Useful for managing user groups associated with feature flags in applications.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATESTATICCOHORTFORFEATUREFLAG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not feature_flag_id:
        missing_params.append(("feature_flag_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATESTATICCOHORTFORFEATUREFLAG"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATESTATICCOHORTFORFEATUREFLAG"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/create_static_cohort_for_flag/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATESTATICCOHORTFORFEATUREFLAG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_feature_flags_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    feature_flag_id: Annotated[int | None, "A unique integer value identifying this feature flag for creation or modification.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_dashboard_create'."]:
    """Create a dashboard for feature flags in a project.

    Use this tool to create a feature flags dashboard within a specified project. This is useful for managing and visualizing feature flags, helping to control and experiment with feature rollouts.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGSDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not feature_flag_id:
        missing_params.append(("feature_flag_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGSDASHBOARD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGSDASHBOARD"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/dashboard/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGSDASHBOARD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_feature_flag_usage_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    feature_flag_id: Annotated[int | None, "A unique integer identifying this feature flag for the usage dashboard.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_enrich_usage_dashboard_create'."]:  # noqa: E501
    """Create or manage feature flag usage dashboards.

    This tool allows you to create, read, update, or delete feature flag usage dashboards. It should be called when you need to manage the display and tracking of feature flags in your project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGUSAGEDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not feature_flag_id:
        missing_params.append(("feature_flag_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGUSAGEDASHBOARD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGUSAGEDASHBOARD"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/enrich_usage_dashboard/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGUSAGEDASHBOARD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_feature_flag_config(
    context: ToolContext,
    feature_flag_identifier: Annotated[int, "The unique integer that identifies the specific feature flag to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Use /api/projects/ to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_remote_config_retrieve'."]:  # noqa: E501
    """Retrieve remote configuration of a specific feature flag.

    This tool retrieves the remote configuration of a specified feature flag within a project. It should be called when you need to access feature flag settings to determine its behavior in your application."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/remote_config/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_feature_flag_status(
    context: ToolContext,
    feature_flag_id: Annotated[int, "A unique integer identifying the feature flag whose status you want to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access a specific project. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_status_retrieve'."]:
    """Retrieve the status of a specific feature flag for a project.

    This tool retrieves the status of a specific feature flag within a project. It should be called when you need to know whether a feature flag is enabled or its current status in a given project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/{id}/status/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=feature_flag_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_feature_flags_activity(
    context: ToolContext,
    project_identifier: Annotated[str, "Unique identifier for the project to retrieve feature flags activity. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_activity_retrieve'."]:
    """Retrieve feature flags activity for a specific project.

    Use this tool to get the activity related to feature flags within a specified project. This can be useful for monitoring changes and updates to feature flags."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_feature_flag_keys(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Obtain the ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_bulk_keys_create'."]:
    """Retrieve feature flag keys using a list of IDs.

    Use this tool to get the keys associated with specific feature flag IDs in a project. It accepts a list of feature flag IDs and returns a mapping of each ID to its corresponding key.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GETFEATUREFLAGKEYS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GETFEATUREFLAGKEYS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GETFEATUREFLAGKEYS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/bulk_keys/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GETFEATUREFLAGKEYS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_feature_flags_evaluation_reasons(
    context: ToolContext,
    project_id_for_feature_flags: Annotated[str, "The ID of the project to access for retrieving feature flags evaluation reasons. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_evaluation_reasons_retrieve'."]:  # noqa: E501
    """Retrieve evaluation reasons for feature flags by project.

    Use this tool to get the evaluation reasons for feature flags associated with a specific project. This is helpful for understanding the behavior of feature flags for different users in your application."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/evaluation_reasons/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_feature_flags),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_local_feature_flags(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access feature flags for. Retrieve this ID via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_local_evaluation_retrieve'."]:  # noqa: E501
    """Retrieve feature flags for local evaluation in a project.

    Call this tool to check if feature flags are enabled for a specific project. Useful for applications using local feature flag evaluations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/local_evaluation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_feature_flags(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access feature flags for. Make a call to /api/projects/ to find the project's ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_my_flags_retrieve'."]:
    """Retrieve current feature flags for a user's project.

    Use this tool to get the list of feature flags for a specific project. This is useful when you need to check which feature flags are active for a user's project in the Datadog environment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/my_flags/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_feature_flag_blast_radius(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    feature_flag_project_id: Annotated[str | None, "The Project ID for accessing the desired project. Obtainable via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'feature_flags_user_blast_radius_create'."]:  # noqa: E501
    """Create a feature flag blast radius for a project.

    This tool creates a user blast radius for feature flags within a specified project. It can be used to manage the scope of feature flag exposure to users. Refer to the documentation for more details on managing feature flags.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGBLASTRADIUS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not feature_flag_project_id:
        missing_params.append(("feature_flag_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGBLASTRADIUS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGBLASTRADIUS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/feature_flags/user_blast_radius/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=feature_flag_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFEATUREFLAGBLASTRADIUS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_file_systems(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for which you want to list file systems. Obtain by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page for file system listings."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A search term to filter the list of file systems."] = None,
    start_index: Annotated[int | None, "The initial index from which to return the file system results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_list'."]:
    """Fetches the list of file systems for a given project.

    Use this tool to retrieve a list of all file systems associated with a specific project in Datadog. This is useful for managing and monitoring project storage."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index, "search": search_term}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_file_system(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project for which you want to create a file system. Retrieve this ID by calling `/api/projects/`.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_create'."]:
    """Create a file system for a specified project.

    Use this tool to create a file system for a given project in Datadog. It should be called when a new file system needs to be initialized within a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROJECTFILESYSTEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROJECTFILESYSTEM"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROJECTFILESYSTEM"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROJECTFILESYSTEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_file_system_info(
    context: ToolContext,
    file_system_id: Annotated[str, "A UUID string identifying the file system to retrieve details for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Get this ID by calling the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_retrieve'."]:
    """Retrieve detailed file system information for a project.

    This tool is used to retrieve detailed information about a file system associated with a given project. It's useful when needing to access specific file system details for analysis or reporting."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_file_system(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_id: Annotated[str | None, "A UUID string uniquely identifying the file system to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The identifier for the project you want to access. Use the project ID to specify which project's file system to update. Retrieve the ID by calling the /api/projects/ endpoint if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_update'."]:
    """Updates a file system in a specific project by ID.

    Call this tool to update the settings or data of a specific file system within a given project on Datadog. Use it when modifications to the file system are needed, such as changing configurations or data structures.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEFILESYSTEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_id:
        missing_params.append(("file_system_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEFILESYSTEM"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEFILESYSTEM"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEFILESYSTEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_file_system(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_id: Annotated[str | None, "A UUID string used to identify the specific file system to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique ID of the project. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_partial_update'."]:
    """Update specific details of a file system.

    Use this tool to update specific details within a file system for a given project. Call this tool when modifications are needed to existing file system configurations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYFILESYSTEM"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_id:
        missing_params.append(("file_system_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYFILESYSTEM"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYFILESYSTEM"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYFILESYSTEM"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_file_system(
    context: ToolContext,
    file_system_id: Annotated[str, "A UUID string identifying the file system to delete."],
    project_id: Annotated[str, "Provide the Project ID of the project you're trying to access. Retrieve the ID with a /api/projects/ call."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_destroy'."]:
    """Delete a specified file system in a project.

    Use this tool to delete a specific file system within a project by providing the project and file system IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_folder_file_count(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_uuid: Annotated[str | None, "A UUID string that uniquely identifies the file system for which you want to get the file count.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID to access the project for counting files. Obtain via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_count_create'."]:
    """Get the count of all files in a folder.

    This tool checks and returns the total number of files present in a specified folder. Use this when you need to know how many files are contained within a folder on the file system.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["FETCHFOLDERFILECOUNT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_uuid:
        missing_params.append(("file_system_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["FETCHFOLDERFILECOUNT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["FETCHFOLDERFILECOUNT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/count/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["FETCHFOLDERFILECOUNT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_file_system_link(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_id: Annotated[str | None, "A UUID string that uniquely identifies the file system.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_link_create'."]:
    """Create a link for a file system in a specific project.

    This tool creates a link for a file system within a specified project. It should be called when you need to establish a new link in your project’s file system.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLINK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_id:
        missing_params.append(("file_system_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLINK"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLINK"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/link/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLINK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def move_file_system_entry(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    file_system_id: Annotated[str | None, "A UUID string identifying the file system to be moved within the project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    target_project_id: Annotated[str | None, "The Project ID of the target project where the file system entry will be moved. Obtain this ID from the /api/projects/ endpoint if necessary.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_move_create'."]:
    """Moves a file system entry to a new location within the project.

    Use this tool to relocate a file or directory within a specified project in Datadog’s file system. It should be called when you need to change the location of a file system entry.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MOVEFILESYSTEMENTRY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not file_system_id:
        missing_params.append(("file_system_id", "path"))
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MOVEFILESYSTEMENTRY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MOVEFILESYSTEMENTRY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/{id}/move/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_id, project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MOVEFILESYSTEMENTRY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_file_count_by_path(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_count_by_path_create'."]:  # noqa: E501
    """Retrieve the count of files in a specified folder.

    Use this tool to get the number of files within a specified directory in a project. Ideal for monitoring or managing file systems efficiently.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["FETCHFILECOUNTBYPATH"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["FETCHFILECOUNTBYPATH"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["FETCHFILECOUNTBYPATH"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/count_by_path/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["FETCHFILECOUNTBYPATH"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_file_system_log_view(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    target_project_id: Annotated[str | None, "The ID of the project for which you want to create a file system log view. Use the API to retrieve the project ID if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_log_view_create'."]:
    """Create a new file system log view for a project.

    Use this tool to initiate the creation of a file system log view for a specified project. It interacts with the Datadog API to set up logging configurations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLOGVIEW"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLOGVIEW"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLOGVIEW"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/log_view/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEFILESYSTEMLOGVIEW"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_unfiled_files(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project whose unfiled files you want to retrieve. Make a call to /api/projects/ to find this ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_unfiled_retrieve'."]:
    """Retrieve unfiled files for a specific project.

    This tool retrieves unfiled files within a specified project using the Datadog API. It should be called when there is a need to access files that have not been organized into folders for a given project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system/unfiled/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_file_shortcuts(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access file system shortcuts. Obtain this ID via /api/projects/."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The zero-based index from which to start returning results. Use to manage pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page when retrieving file system shortcuts."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_shortcut_list'."]:
    """Retrieve a list of file system shortcuts for a given project.

    Use this tool to obtain a detailed list of all file system shortcuts associated with a specific project. Ideal for managing and accessing project-related file paths efficiently."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system_shortcut/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_result_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def file_system_shortcut_create(
    context: ToolContext,
    file_system_shortcut_path: Annotated[str, "The file path where the shortcut will be created. It should be a valid string path within the project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve project IDs by calling /api/projects/."],  # noqa: E501
    shortcut_creation_timestamp: Annotated[str, "The timestamp when the shortcut was created, in string format. Typically, in ISO 8601 format."],  # noqa: E501
    shortcut_id: Annotated[str, "A unique identifier for the file system shortcut being created."],
    reference_id: Annotated[str | None, "A unique reference string for the shortcut. This identifies the shortcut within the project."] = None,  # noqa: E501
    shortcut_type: Annotated[str | None, "Specifies the type of file system shortcut to be created. Accepted values could include types like 'link', 'alias', or 'junction'."] = None,  # noqa: E501
    shortcut_url: Annotated[str | None, "The URL reference for the file system shortcut to be created."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_shortcut_create'."]:
    """Create a file system shortcut in a specific project.

    Call this tool to create a file system shortcut within a specific project using the Datadog API."""  # noqa: E501
    request_data: Any = {"id": shortcut_id, "path": file_system_shortcut_path, "type": shortcut_type, "ref": reference_id, "href": shortcut_url, "created_at": shortcut_creation_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system_shortcut/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_file_system_shortcut(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Use the /api/projects/ endpoint to find the ID if needed."],  # noqa: E501
    shortcut_id: Annotated[str, "A UUID string to identify the file system shortcut to retrieve details for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_shortcut_retrieve'."]:
    """Retrieve details of a file system shortcut.

    Use this tool to get information about a specific file system shortcut within a project by providing the project ID and shortcut ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=shortcut_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_file_system_shortcut(
    context: ToolContext,
    creation_timestamp: Annotated[str, "A string representing the creation date and time of the shortcut. Format: ISO 8601 (e.g., '2021-09-15T13:45:30Z')."],  # noqa: E501
    file_system_path: Annotated[str, "The file system path of the shortcut to be updated. Provide the exact path within the project."],  # noqa: E501
    file_system_shortcut_id: Annotated[str, "The UUID string identifying the file system shortcut to be updated."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project you want to update the file system shortcut for. Retrieve this ID by calling /api/projects/."],  # noqa: E501
    shortcut_id: Annotated[str, "The unique identifier for the file system shortcut to be updated."],  # noqa: E501
    file_system_shortcut_href: Annotated[str | None, "The URL of the file system shortcut to be updated. It specifies the link to the resource."] = None,  # noqa: E501
    reference_identifier: Annotated[str | None, "A unique string identifier for the file system shortcut to be updated. This is used to specify which shortcut you are modifying."] = None,  # noqa: E501
    shortcut_type: Annotated[str | None, "Specifies the type of the file system shortcut to update. Accepted values may vary based on use case."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_shortcut_update'."]:
    """Update a file system shortcut in a specified project.

    Use this tool to update details of a file system shortcut within a project. This can be helpful for managing project shortcuts by modifying them as needed."""  # noqa: E501
    request_data: Any = {"id": shortcut_id, "path": file_system_path, "type": shortcut_type, "ref": reference_identifier, "href": file_system_shortcut_href, "created_at": creation_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=shortcut_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_file_system_shortcut(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    file_system_shortcut_id: Annotated[str | None, "A UUID identifying the file system shortcut to be updated."] = None,  # noqa: E501
    file_system_shortcut_link: Annotated[str | None, "The URL or path to link the file system shortcut to. This should be a valid URL or path, depending on the system configuration."] = None,  # noqa: E501
    reference_identifier: Annotated[str | None, "The reference identifier for the file system shortcut to be updated. This is a string value required to specify which shortcut you are targeting for the update."] = None,  # noqa: E501
    shortcut_creation_date: Annotated[str | None, "ISO 8601 format string representing when the shortcut was created."] = None,  # noqa: E501
    shortcut_id: Annotated[str | None, "The unique identifier for the file system shortcut to be updated. This ID specifies which shortcut will have its details modified."] = None,  # noqa: E501
    shortcut_path: Annotated[str | None, "The file path for the shortcut to be updated. This should specify the exact location within the file system where the shortcut is located."] = None,  # noqa: E501
    shortcut_type: Annotated[str | None, "Specify the type of the file system shortcut, such as 'symbolic' or 'hard'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_shortcut_partial_update'."]:  # noqa: E501
    """Update a file system shortcut in a project.

    Use this tool to modify the details of an existing file system shortcut within a specified project on Datadog. Useful for adjusting configurations or updating linked resources."""  # noqa: E501
    request_data: Any = {"id": shortcut_id, "path": shortcut_path, "type": shortcut_type, "ref": reference_identifier, "href": file_system_shortcut_link, "created_at": shortcut_creation_date}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=shortcut_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_file_system_shortcut(
    context: ToolContext,
    file_system_shortcut_uuid: Annotated[str, "A UUID string identifying the file system shortcut to delete."],  # noqa: E501
    project_identifier: Annotated[str, "The Project ID to access. Retrieve it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'file_system_shortcut_destroy'."]:
    """Delete a file system shortcut from a project.

    This tool deletes a specific file system shortcut within a given project. Use it to remove unnecessary or outdated shortcuts from your project infrastructure."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/file_system_shortcut/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=file_system_shortcut_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_feature_flag_values(
    context: ToolContext,
    project_id: Annotated[str, "The unique ID of the project to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'flag_value_values_retrieve'."]:
    """Retrieve possible values for a feature flag.

    Call this tool to get the possible values associated with a specific feature flag by providing the flag ID. Useful when you need to know what options a feature flag can take."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/flag_value/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_groups_by_type(
    context: ToolContext,
    group_type_to_list: Annotated[int, "Specify the type of the group to retrieve by providing the index."],  # noqa: E501
    project_id: Annotated[str, "Project ID of the target project. It can be found by calling /api/projects/."],  # noqa: E501
    search_group_name: Annotated[str, "Search for a group by its name. Provide keywords or partial names to filter the group list."],  # noqa: E501
    pagination_cursor_value: Annotated[str | None, "Provide the pagination cursor value to navigate through paginated results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_list'."]:
    """Retrieve all groups for a specified group type.

    Use this tool to list all groups of a given type within a project. Specify the group type to get corresponding groups."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"cursor": pagination_cursor_value, "group_type_index": group_type_to_list, "search": search_group_name}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_group(
    context: ToolContext,
    group_identifier_key: Annotated[str, "A unique string identifier for the new group being created within a project. This key should be distinct to avoid conflicts with existing groups."],  # noqa: E501
    group_type_identifier: Annotated[int, "An integer specifying the type of group to create within the project."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project where the new group will be created. Use /api/projects/ to find the ID."],  # noqa: E501
    group_properties: Annotated[str | None, "Specify the properties of the group you want to create. Provide this as a JSON string with property keys and values."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_create'."]:
    """Create a new group in a specified project.

    This tool is used to create a new group within a specified project in Datadog. It should be called when there is a need to organize or manage project resources effectively by grouping related items together."""  # noqa: E501
    request_data: Any = {"group_type_index": group_type_identifier, "group_key": group_identifier_key, "group_properties": group_properties}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_group_activity(
    context: ToolContext,
    group_type_id: Annotated[int, "The numeric identifier for the group type to retrieve activity data."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access the specific group activity. Find this ID via the /api/projects/ endpoint."],  # noqa: E501
    user_id_for_group_retrieval: Annotated[str, "Specify the user ID to find associated groups for activity retrieval."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_activity_retrieve'."]:
    """Fetches activity data for specified project groups.

    This tool retrieves the activity information for groups within a specified project. It is useful for monitoring or analyzing group interactions and activities within a particular project scope."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"group_type_index": group_type_id, "id": user_id_for_group_retrieval}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_group_property(
    context: ToolContext,
    group_identifier_key: Annotated[str, "The unique identifier key of the group from which the property will be deleted. This is required to specify the exact group within the project."],  # noqa: E501
    group_index_type: Annotated[int, "An integer representing the index of the group type to delete a property from."],  # noqa: E501
    group_key_for_deletion: Annotated[str, "The unique key identifying the group from which the property will be deleted."],  # noqa: E501
    group_type_index: Annotated[int, "An integer specifying the group type to find within a project for property deletion."],  # noqa: E501
    project_id: Annotated[str, "The ID of the Datadog project for accessing and managing group properties. To find this ID, make a call to /api/projects/."],  # noqa: E501
    property_creation_date: Annotated[str, "The timestamp when the group property was created. Use ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)."],  # noqa: E501
    group_property_key: Annotated[str | None, "The key of the group property to be deleted from the Datadog project."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_delete_property_create'."]:
    """Delete a group property in a Datadog project.

    This tool deletes a property from a group within a specified Datadog project. It should be used when there's a need to remove specific properties from groups in the context of project management within Datadog."""  # noqa: E501
    request_data: Any = {"group_type_index": group_index_type, "group_key": group_identifier_key, "group_properties": group_property_key, "created_at": property_creation_date}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/delete_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({"group_key": group_identifier_key, "group_type_index": group_index_type}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_groups(
    context: ToolContext,
    group_key_to_find: Annotated[str, "Specify the key of the group you want to find. This is used to identify the specific group within the project."],  # noqa: E501
    group_type_index: Annotated[int, "Specify the integer index for the group type you want to find within a project."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project to access group details. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_find_retrieve'."]:
    """Retrieve group details for a specific project.

    This tool retrieves details of groups associated with a specific project. It should be called when there is a need to obtain information about project groups using a specified project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/find/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"group_key": group_key_to_find, "group_type_index": group_type_index}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_group_property_definitions(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_property_definitions_retrieve'."]:  # noqa: E501
    """Retrieve group property definitions for a project.

    Call this tool to get a list of property definitions for a specific project group. Useful for viewing the properties associated with groups in a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/property_definitions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_group_property_values(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_property_values_retrieve'."]:
    """Retrieve property values for groups within a project.

    This tool retrieves property values for groups under a specified project in Datadog. It is useful when you need to access specific group configurations or data within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/property_values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_related_groups(
    context: ToolContext,
    group_type_index: Annotated[int, "The index specifying the type of group to find."],
    project_id: Annotated[str, "The ID of the project to access. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
    user_id_to_find_groups: Annotated[str, "The ID of the user to find related groups for within a specified project. It should be a string value."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_related_retrieve'."]:
    """Retrieve related groups for a specific project in Datadog.

    Use this tool to get information on groups related to a specified project within Datadog. This can help in understanding project group associations and dependencies."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/related/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"group_type_index": group_type_index, "id": user_id_to_find_groups}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_group_property(
    context: ToolContext,
    group_identifier: Annotated[str, "Specify the unique key of the group to locate and update within the project."],  # noqa: E501
    group_identifier_key: Annotated[str, "The unique key identifying the group to update. This key ensures that the correct group is modified."],  # noqa: E501
    group_property_creation_date: Annotated[str, "The date and time when the group property was created. Use ISO 8601 format, e.g., '2023-10-05T14:48:00Z'."],  # noqa: E501
    group_type_index: Annotated[int, "Specify the integer index of the group type to identify the group."],  # noqa: E501
    index_of_group_type: Annotated[int, "An integer representing the index of the group type to update. Specify the correct index to modify the desired group type within the project."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    group_properties_value: Annotated[str | None, "The properties or attributes to update for the specified group in the project. This should be a string describing the desired changes."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_update_property_create'."]:
    """Update a property of a group within a project.

    This tool updates a specific property of a group in a given project. Use it when you need to modify group settings or attributes within a project on the Datadog platform."""  # noqa: E501
    request_data: Any = {"group_type_index": index_of_group_type, "group_key": group_identifier_key, "group_properties": group_properties_value, "created_at": group_property_creation_date}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups/update_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({"group_key": group_identifier_key, "group_type_index": index_of_group_type}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_group_types(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_list'."]:
    """Retrieve list of group types for a specific project.

    Call this tool to get the different types of groups available within a specific project on Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_group_type(
    context: ToolContext,
    group_type_index: Annotated[int, "Index of the group type to be deleted. Use an integer value to specify the group type."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Obtain this ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_destroy'."]:
    """Delete a specified group type in a project.

    Use this tool to remove a group type from a specified project. This is useful when a group type is no longer needed or needs to be reconfigured."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_index, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_group_type_metrics(
    context: ToolContext,
    group_type_index: Annotated[int, "The index of the group type for which to retrieve metrics. This identifies the specific group type within the project."],  # noqa: E501
    project_identifier: Annotated[str, "String representing the Project ID to access the desired project in Datadog. Obtain it through a call to /api/projects/."],  # noqa: E501
    results_offset: Annotated[int | None, "The starting index for returning results, used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_metrics_list'."]:
    """Retrieve metrics for a specific group type in a project.

    Call this tool to get a list of metrics related to a specific group type within a given project. Use it when you need detailed metric information for analytics or monitoring purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_index, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_offset}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_group_type_metric(
    context: ToolContext,
    group_type_index: Annotated[int, "An integer representing the index of the group type to which a new metric will be added."],  # noqa: E501
    group_type_metric_id: Annotated[str, "The unique identifier for the metric you wish to create. It should be a string value."],  # noqa: E501
    metric_filters: Annotated[str, "Optional filters to apply when creating the group type metric. It accepts a string of filter criteria to narrow down the data."],  # noqa: E501
    metric_name: Annotated[str, "The name of the metric to be created for the group type. This should be a descriptive and unique identifier that helps distinguish this metric from others."],  # noqa: E501
    project_id: Annotated[str, "Project ID for accessing the specific project. Make a call to /api/projects/ to retrieve available IDs."],  # noqa: E501
    display_format: Annotated[str | None, "Specifies how the metric will be displayed: 'number' for a numeric display, or 'sparkline' for a graphical display."] = None,  # noqa: E501
    interval_in_days: Annotated[int | None, "Specify the interval in days for the metric data aggregation."] = None,  # noqa: E501
    metric_format: Annotated[str | None, "Specify the format for the metric. Options are 'numeric' or 'currency'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_metrics_create'."]:
    """Create a new metric for a specific group type.

    This tool creates a new metric for a specified group type within a project. It should be called when you need to add a new performance or data metric to a group type for monitoring or analysis purposes."""  # noqa: E501
    request_data: Any = {"id": group_type_metric_id, "name": metric_name, "format": metric_format, "interval": interval_in_days, "display": display_format, "filters": metric_filters}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_index, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_group_type_metric(
    context: ToolContext,
    group_type_index: Annotated[int, "An integer representing the index of the group type to retrieve metrics for."],  # noqa: E501
    group_usage_metric_id: Annotated[str, "A UUID string identifying this group usage metric to retrieve its details."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access, retrievable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_metrics_retrieve'."]:
    """Retrieve metrics for a specific group type.

    Calls the Datadog API to retrieve detailed information about a specific metric within a specified group type for a project. Useful for monitoring and analyzing specific metrics in projects."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_index, id=group_usage_metric_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_group_type_metrics(
    context: ToolContext,
    filters_criteria: Annotated[str, "Specify criteria to filter metrics data. Use a string representation of conditions."],  # noqa: E501
    group_type_index: Annotated[int, "An integer representing the index of the group type to be updated. This is required to identify which group type's metrics need modification."],  # noqa: E501
    group_usage_metric_id: Annotated[str, "A UUID string identifying the group usage metric to be updated."],  # noqa: E501
    metric_id: Annotated[str, "Unique identifier for the metric to be updated. Expect a string value."],  # noqa: E501
    metric_name: Annotated[str, "The name of the metric to update for the specified group type in a project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you want to access. Use /api/projects/ to find it."],  # noqa: E501
    interval_in_days: Annotated[int | None, "Specify the interval in days for updating metrics."] = None,  # noqa: E501
    metric_display_type: Annotated[str | None, "Defines how the metrics are displayed. Options are 'number' or 'sparkline'."] = None,  # noqa: E501
    metric_format_type: Annotated[str | None, "Specifies the display format of the metric: 'numeric' for numeric values or 'currency' for currency representation."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_metrics_update'."]:
    """Updates metrics for a specified group type in a project.

    This tool updates the metrics for a given group type in a specified project. It should be called when there's a need to modify or update the metrics associated with a group type. Useful for maintaining or adjusting project metric configurations."""  # noqa: E501
    request_data: Any = {"id": metric_id, "name": metric_name, "format": metric_format_type, "interval": interval_in_days, "display": metric_display_type, "filters": filters_criteria}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_index, id=metric_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_metrics_for_group_type(
    context: ToolContext,
    group_type_position: Annotated[int, "The index of the group type to update within the metrics. It should be an integer value."],  # noqa: E501
    project_id: Annotated[str, "The unique ID of the project you want to access. Retrieve it by calling /api/projects/."],  # noqa: E501
    filter_conditions: Annotated[str | None, "Conditions to filter the metrics. Specify as a string, e.g., 'status:active'."] = None,  # noqa: E501
    group_metric_name: Annotated[str | None, "The name of the metric to update for the specified group type."] = None,  # noqa: E501
    group_type_id: Annotated[str | None, "The unique identifier for the group type to update metrics for."] = None,  # noqa: E501
    group_usage_metric_id: Annotated[str | None, "A UUID string identifying the group usage metric to update."] = None,  # noqa: E501
    metric_display_type: Annotated[str | None, "Defines how the metric should be displayed: 'number' or 'sparkline'."] = None,  # noqa: E501
    metric_format_type: Annotated[str | None, "Specifies the format of the metric. Can be 'numeric' or 'currency'. Choose 'numeric' for plain numbers and 'currency' for currency representation."] = None,  # noqa: E501
    update_interval_days: Annotated[int | None, "Number of days to set as the interval for updating metrics."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_metrics_partial_update'."]:  # noqa: E501
    """Update metrics for a specific group type in a project.

    This tool updates metrics for a specified group type within a project in Datadog. It should be called when metrics need to be modified or adjusted for a particular group type associated with a project."""  # noqa: E501
    request_data: Any = {"id": group_type_id, "name": group_metric_name, "format": metric_format_type, "interval": update_interval_days, "display": metric_display_type, "filters": filter_conditions}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_position, id=group_type_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_group_type_metric(
    context: ToolContext,
    group_type_index: Annotated[int, "An integer representing the position of the group type in the list. Specify the exact index to delete the associated metric."],  # noqa: E501
    metric_uuid: Annotated[str, "A UUID string identifying the metric to be deleted from the group type."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve it via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_metrics_destroy'."]:
    """Delete a specific metric from a group type.

    Use this tool to delete a specific metric from a group type within a project. Ideal for removing unused or incorrect metrics."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/{group_type_index}/metrics/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), group_type_index=group_type_index, id=metric_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_group_dashboard(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The string representing the Project ID you want to access. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_create_detail_dashboard_update'."]:  # noqa: E501
    """Update a project's group detail dashboard.

    Use this tool to update the configuration of a group detail dashboard within a specific project. Ideal for modifying existing dashboard settings.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEGROUPDASHBOARD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEGROUPDASHBOARD"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEGROUPDASHBOARD"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/create_detail_dashboard/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEGROUPDASHBOARD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_default_group_columns(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project you want to access. Retrieve it by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_set_default_columns_update'."]:  # noqa: E501
    """Update default columns for group types in a project.

    This tool updates the default columns for group types within a specified project. It should be called to modify the columns used by default when displaying group types in the application.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEDEFAULTGROUPCOLUMNS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEDEFAULTGROUPCOLUMNS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEDEFAULTGROUPCOLUMNS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/set_default_columns/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEDEFAULTGROUPCOLUMNS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_group_type_metadata(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID to access a specific project. Use /api/projects/ to find the ID."],  # noqa: E501
    default_columns: Annotated[list[str] | None, "An array of strings representing the default columns for the group type metadata. Each string specifies a column name to be included by default."] = None,  # noqa: E501
    detail_dashboard_id: Annotated[int | None, "The integer ID of the detail dashboard associated with the group type."] = None,  # noqa: E501
    group_type_creation_date: Annotated[str | None, "The creation date of the group type in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)."] = None,  # noqa: E501
    group_type_identifier: Annotated[str | None, "The identifier for the group type to update metadata for. Provide a unique string value that represents the group type within the project."] = None,  # noqa: E501
    group_type_index: Annotated[int | None, "An integer representing the index of the group type you want to update within the project. It identifies which specific group type's metadata is to be modified."] = None,  # noqa: E501
    group_type_name_plural: Annotated[str | None, "The plural name for the group type to be updated. This should reflect the plural form used in the project metadata."] = None,  # noqa: E501
    singular_group_name: Annotated[str | None, "The singular name to be used for a specific group type. This is used for clear identification and communication."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'groups_types_update_metadata_partial_update'."]:  # noqa: E501
    """Updates metadata for group types in a project.

    Use this tool to update the metadata for group types within a specific project. It should be called when there's a need to partially update this information for better organization and management of project data."""  # noqa: E501
    request_data: Any = {"group_type": group_type_identifier, "group_type_index": group_type_index, "name_singular": singular_group_name, "name_plural": group_type_name_plural, "detail_dashboard": detail_dashboard_id, "default_columns": default_columns, "created_at": group_type_creation_date}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/groups_types/update_metadata/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_hog_functions(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Obtain via /api/projects/."],  # noqa: E501
    created_at: Annotated[str | None, "Specify the creation date for filtering hog functions. Use ISO 8601 format (YYYY-MM-DD)."] = None,  # noqa: E501
    created_by_user_id: Annotated[int | None, "The unique integer ID of the user who created the resource."] = None,  # noqa: E501
    function_id: Annotated[str | None, "The unique identifier for the hog function to retrieve details for."] = None,  # noqa: E501
    hog_function_types: Annotated[list[str] | None, "A list of hog function types, specified as strings. Supports multiple values."] = None,  # noqa: E501
    include_only_enabled_functions: Annotated[bool | None, "Include only enabled functions. Set to true to include enabled functions, false to include all."] = None,  # noqa: E501
    result_offset: Annotated[int | None, "The starting index for the returned results, used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Integer specifying the number of results to return per page."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A search term used to filter the list of hog functions based on specific criteria."] = None,  # noqa: E501
    updated_timestamp: Annotated[str | None, "The timestamp for the latest update of the hog function. Use an ISO 8601 format."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_list'."]:
    """Retrieve a list of hog functions for a project.

    Use this tool to obtain a list of hog functions associated with a specific project ID. Each API call logs a new view of the file system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"created_at": created_at, "created_by": created_by_user_id, "enabled": include_only_enabled_functions, "id": function_id, "limit": results_per_page, "offset": result_offset, "search": search_term, "type": hog_function_types, "updated_at": updated_timestamp}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_hog_function(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The unique ID of the project to access. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_create'."]:
    """Log a new file system view for a specified project.

    This tool logs a new file system view each time a GET request is made on the resource. It should be called to track resource views under a specific project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEHOGFUNCTION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_hog_function(
    context: ToolContext,
    hog_function_id: Annotated[str, "A UUID string identifying the specific hog function to retrieve."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project you want to access. Retrieve it via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_retrieve'."]:
    """Retrieve details of a hog function in a project.

    Use this tool to get detailed information about a specific hog function within a given project in Datadog. This tool helps in tracking file system views by logging each GET request as a new view."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_hog_functions(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_uuid: Annotated[str | None, "A UUID string to uniquely identify the hog function to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the desired project. Retrieve via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_update'."]:
    """Update and track file system views for hog functions.

    Use this tool to update specific hog functions and track file system views in Datadog. It should be called when modifications to a hog function in a project are required and each GET on the resource should be logged as a new view.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYHOGFUNCTIONS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_uuid:
        missing_params.append(("hog_function_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYHOGFUNCTIONS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYHOGFUNCTIONS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYHOGFUNCTIONS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_hog_function_views(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_uuid: Annotated[str | None, "A UUID string identifying the hog function to log a view for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique ID of the project. Retrieve by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_partial_update'."]:
    """Log and update views for hog functions in a project.

    Use this tool to log a new view of a specific hog function within a given project. It tracks file system views by logging each access to the resource.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_uuid:
        missing_params.append(("hog_function_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONVIEWS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_hog_function(
    context: ToolContext,
    hog_function_id: Annotated[str, "A UUID string identifying the HOG function to be marked as deleted."],  # noqa: E501
    project_id_for_deletion: Annotated[str, "The unique identifier of the project where the HOG function resides. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_destroy'."]:
    """Marks a HOG function as deleted in a Datadog project.

    Use this tool to mark a specific HOG function in a Datadog project as deleted. This is performed by setting the \"deleted\" attribute to true, as hard deletion is not permitted."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_id, project_id=project_id_for_deletion),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_file_system_view(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_uuid: Annotated[str | None, "A UUID string identifying the hog function to track.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "A string representing the Project ID of the project to access. Retrieve this ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_broadcast_create'."]:
    """Log and track a file system view on resource access.

    This tool logs a new view each time a GET request is made on the specified resource, useful for tracking access patterns.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["TRACKFILESYSTEMVIEW"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_uuid:
        missing_params.append(("hog_function_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["TRACKFILESYSTEMVIEW"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["TRACKFILESYSTEMVIEW"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/broadcast/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["TRACKFILESYSTEMVIEW"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_fs_view(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    hog_function_uuid: Annotated[str | None, "A UUID string identifying this hog function. Required for logging views.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you are accessing. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_invocations_create'."]:  # noqa: E501
    """Logs a view each time a resource is accessed via GET.

    Use this tool to track access views on file system resources by logging a view each time they are accessed. This can help in monitoring and analyzing file system interactions within a specified project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["TRACKFSVIEW"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not hog_function_uuid:
        missing_params.append(("hog_function_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["TRACKFSVIEW"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["TRACKFSVIEW"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/invocations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["TRACKFSVIEW"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_logs_for_file_system_views(
    context: ToolContext,
    hog_function_uuid: Annotated[str, "A UUID string identifying the specific hog function to retrieve logs for."],  # noqa: E501
    project_identifier: Annotated[str, "A string representing the Project ID for access. Call /api/projects/ to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_logs_retrieve'."]:
    """Retrieves logs for tracked file system views.

    Use this tool to retrieve logs that track each GET request on a specified file system resource within a project. This is useful for monitoring access patterns and resource usage."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_file_system_views(
    context: ToolContext,
    hog_function_id: Annotated[str, "A UUID string identifying the specific hog function for tracking views."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_metrics_retrieve'."]:
    """Retrieve metrics for tracking file system views.

    This tool retrieves metrics related to views on file system resources. It logs a new view each time the resource is accessed via a GET request. Use this to monitor and analyze access patterns."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/metrics/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_hog_function_metrics_totals(
    context: ToolContext,
    hog_function_uuid: Annotated[str, "A UUID string identifying the specific hog function for which metrics are being retrieved."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID for accessing the specific project. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_metrics_totals_retrieve'."]:  # noqa: E501
    """Retrieve total metrics for a specified hog function.

    This tool retrieves the total metrics for a specified hog function within a project. It should be called when you need to assess the overall metrics data of a hog function. Ideal for tracking and analyzing file system views."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/{id}/metrics/totals/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=hog_function_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_hog_function_icon(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for which you want to retrieve the hog function icon. Obtain the ID via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_icon_retrieve'."]:
    """Retrieve the icon for hog functions in a specific project.

    This tool is used to retrieve the icon associated with hog functions for a given project. It should be called when you need to visualise or access icon data related to hog functions tracked by the system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/icon/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_icons(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project you want to access. Retrieve it using /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_icons_retrieve'."]:
    """Retrieve and log views of project icons.

    Use this tool to retrieve icons for a specific project and log each retrieval as a system view."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/icons/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_hogfunction_order(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "ID of the project to access. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'hog_functions_rearrange_partial_update'."]:  # noqa: E501
    """Modify the order of execution for HogFunctions.

    Use this tool to update the execution order of multiple HogFunctions within a specified project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONORDER"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONORDER"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONORDER"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/hog_functions/rearrange/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEHOGFUNCTIONORDER"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_insights(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access specific insights. Obtain it via /api/projects/."],  # noqa: E501
    creator_user_id: Annotated[int | None, "The user ID of the creator of the insights. Provide this as an integer value to filter insights by the creator."] = None,  # noqa: E501
    insights_refresh_mode: Annotated[str | None, "Determine how aggressively to refresh insights: 'force_cache', 'blocking', 'async', 'lazy_async', 'force_blocking', or 'force_async'."] = "force_cache",  # noqa: E501
    project_short_id: Annotated[str | None, "The short identifier for the project within Datadog. Used to specify which project's insights to retrieve."] = None,  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response, either 'csv' or 'json'. Choose based on your output preference."] = None,  # noqa: E501
    results_offset_index: Annotated[int | None, "The starting index for returning results from the insights list."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of insights to return per page."] = None,  # noqa: E501
    return_basic_metadata_only: Annotated[bool | None, "If true, return only basic insight metadata without results for a faster response."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_list'."]:
    """Retrieve insights list for a specific project.

    This tool fetches insights data for a specified project from the Datadog API. Use it to track and log file system views with each GET request."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"basic": return_basic_metadata_only, "created_by": creator_user_id, "format": response_format, "limit": results_per_page, "offset": results_offset_index, "refresh": insights_refresh_mode, "short_id": project_short_id}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_insight_entry(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project for which you want to log a file system view. Obtain it using the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response, either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_create'."]:
    """Logs a new file system view entry for insights.

    Use this tool to create a new insight entry when tracking file system views. Each invocation logs a view for a specified project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEINSIGHTENTRY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEINSIGHTENTRY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEINSIGHTENTRY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEINSIGHTENTRY"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_insight_sharing(
    context: ToolContext,
    insight_identifier: Annotated[int, "The unique identifier for the specific insight you want to retrieve sharing details for. This is an integer value that uniquely represents an insight within the project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_sharing_list'."]:
    """Retrieve sharing details for a specific insight.

    Use this tool to get information about the sharing status and access details for a specific insight within a project. Useful for managing and reviewing who has access to insights in a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{insight_id}/sharing/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_insights_sharing_password(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_identifier: Annotated[int | None, "The numerical ID representing the specific insight to create a password for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_sharing_passwords_create'."]:  # noqa: E501
    """Create a new password for insights sharing configuration.

    This tool is used to create a new password for the sharing configuration of a specific insight within a project. Call this tool when you need to generate a password for sharing insights securely.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEINSIGHTSSHARINGPASSWORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_identifier:
        missing_params.append(("insight_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEINSIGHTSSHARINGPASSWORD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEINSIGHTSSHARINGPASSWORD"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{insight_id}/sharing/passwords/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEINSIGHTSSHARINGPASSWORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_password_from_sharing_config(
    context: ToolContext,
    insight_identifier: Annotated[int, "The unique integer identifier for the insight from which the password is being deleted."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve it via the /api/projects endpoint."],  # noqa: E501
    sharing_password_id: Annotated[str, "The unique ID of the password to be deleted from the sharing configuration."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_sharing_passwords_destroy'."]:  # noqa: E501
    """Delete a password from the sharing configuration of an insight.

    Use this tool to delete a specific password associated with a sharing configuration in Datadog insights. It should be called when you need to remove access control via password on shared insights."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{insight_id}/sharing/passwords/{password_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_identifier, password_id=sharing_password_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def refresh_insight_sharing(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_identifier: Annotated[int | None, "The unique integer identifier for the insight to refresh sharing settings.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The Project ID to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_sharing_refresh_create'."]:
    """Refresh the sharing settings of an insight.

    Use this tool to refresh the sharing settings for a specific insight within a project. This is useful when access permissions or sharing parameters need to be updated to reflect the latest configurations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSHARING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_identifier:
        missing_params.append(("insight_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSHARING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSHARING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{insight_id}/sharing/refresh/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), insight_id=insight_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REFRESHINSIGHTSHARING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_insight_data(
    context: ToolContext,
    insight_id: Annotated[int, "A unique integer identifying the specific insight to retrieve."],
    project_id: Annotated[str, "Project ID to access. Obtain it by calling /api/projects/."],
    dashboard_context_id: Annotated[int | None, "ID of the dashboard for context-specific insight. Filters and date range from this dashboard will be applied."] = None,  # noqa: E501
    output_format: Annotated[str | None, "Specifies the format for the retrieved insights data. Options are 'csv' or 'json'."] = None,  # noqa: E501
    refresh_insight_strategy: Annotated[str | None, "Defines the strategy for refreshing the insight. Options include 'force_cache', 'blocking', 'async', 'lazy_async', 'force_blocking', and 'force_async', determining sync/async behavior and cache usage."] = "force_cache",  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_retrieve'."]:
    """Retrieve tracked insights for project file system views.

    This tool retrieves tracked insights whenever a file system view in a project is accessed, logging each view occurrence."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format, "from_dashboard": dashboard_context_id, "refresh": refresh_insight_strategy}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_insights(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_id: Annotated[int | None, "A unique integer identifying the insight to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specify the format of the response data. Accepts 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_update'."]:
    """Update insights tracking view for a project resource.

    Use this tool to log a new view of a specific insight within a project, helping track file system views. It updates the view count each time it's called.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEINSIGHTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_id:
        missing_params.append(("insight_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEINSIGHTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEINSIGHTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEINSIGHTS"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_insights_view_log(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    insight_id: Annotated[int | None, "A unique integer value to identify the specific insight.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID to access the required insight. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the response. Acceptable values are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_partial_update'."]:
    """Log a new view for a specific insight resource.

    This tool triggers a log entry each time a specific insight resource is accessed, helping to track file system views.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEINSIGHTSVIEWLOG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not insight_id:
        missing_params.append(("insight_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEINSIGHTSVIEWLOG"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEINSIGHTSVIEWLOG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEINSIGHTSVIEWLOG"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_insight(
    context: ToolContext,
    insight_id: Annotated[int, "A unique integer identifying the insight to be marked as deleted."],
    project_identifier: Annotated[str, "Project ID to access and mark an insight as deleted. Use /api/projects/ to find the ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_destroy'."]:
    """Marks an insight as deleted in a project.

    Use this tool to mark an insight within a project as deleted. This operation does not hard delete the insight but flags it as deleted."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_insights_activity(
    context: ToolContext,
    insight_id: Annotated[int, "A unique integer identifying the specific insight to retrieve logs for."],  # noqa: E501
    project_id_for_access: Annotated[str, "Project ID to access the desired project. Retrieve ID via /api/projects/ if unknown."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response: 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_activity_retrieve_2'."]:
    """Retrieve logs of insight views for a project.

    This tool is used to track and retrieve logs of views on a specific insight resource within a project. It is called to monitor activity on insights, logging each GET request made to the resource."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=insight_id, project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_insights_activity(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access insights activity data. Obtain by calling /api/projects/."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the format for the output: 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_activity_retrieve'."]:
    """Retrieve insights activity logs for a specified project.

    Fetches activity logs each time a GET request is made to the specified project's insights activity resource. Useful for tracking file system views and understanding project interaction trends."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def stop_insight_process(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The unique identifier for the project. Use /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "The desired format of the response, either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_cancel_create'."]:
    """Cancel the ongoing insight creation process for a project.

    Use this tool to stop the creation of insights for a specific project. When a view logs a GET request to the resource, this process allows the automatic tracking and cancellation of ongoing insight creation activities.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["STOPINSIGHTPROCESS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["STOPINSIGHTPROCESS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["STOPINSIGHTPROCESS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["STOPINSIGHTPROCESS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_recently_viewed_insights(
    context: ToolContext,
    project_id: Annotated[str, "Project ID for accessing the specific project insights. Obtainable via `/api/projects/`."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the returned data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_my_last_viewed_retrieve'."]:  # noqa: E501
    """Retrieve details of the last 5 insights viewed by the user.

    Use this tool to get the most recently viewed insights, with up to 5 insights returned in the order they were accessed. Ideal for quickly accessing an overview of your recent insights."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/insights/my_last_viewed/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def record_insight_views(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Retrieve the ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the response. Choose between 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'insights_viewed_create'."]:
    """Update the view timestamps for specified insights.

    Use this tool to update the view timestamps of specific insights by providing their IDs. This tool is helpful when tracking which insights have been viewed and updating their status within a given project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RECORDINSIGHTVIEWS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RECORDINSIGHTVIEWS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RECORDINSIGHTVIEWS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/insights/viewed/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RECORDINSIGHTVIEWS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_integrations(
    context: ToolContext,
    project_id: Annotated[str, "Specify the Project ID to retrieve its associated integrations. You can find this ID by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The index to start returning results from, used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_list'."]:
    """Retrieve a list of integrations for a specific project.

    This tool is used to get a list of integrations associated with a specific project by providing the project ID. Call this tool when you need to explore or manage the integrations linked to a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_integration(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_create'."]:
    """Creates a new integration for a specific project.

    Use this tool to create an integration for a project by providing the project ID. It sets up integrations to connect your project with other services.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROJECTINTEGRATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROJECTINTEGRATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROJECTINTEGRATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROJECTINTEGRATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_integration_details(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying this integration."],
    project_id: Annotated[str, "The ID of the project for which integration details are needed. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_retrieve'."]:
    """Retrieve integration details for a specific project.

    Use this tool to retrieve detailed information about a specific integration within a specified project on Datadog. This is helpful for understanding configuration and status of integrations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_integration(
    context: ToolContext,
    integration_id: Annotated[int, "The unique integer used to identify the specific integration to be deleted."],  # noqa: E501
    project_id: Annotated[str, "The Project ID needed to access the project. Retrieve it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_destroy'."]:
    """Delete an existing integration for a project.

    Use this tool to remove a specific integration from a project by providing the project and integration identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_integration_channels(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the specific integration in Datadog."],  # noqa: E501
    project_identifier: Annotated[str, "Project identifier for accessing a specific project. Use the /api/projects/ endpoint to find the ID if needed."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_channels_retrieve'."]:
    """Retrieve integration channels for a specific project and ID.

    Call this tool to get a list of channels associated with a specific integration for a given project ID in Datadog. Useful for checking configured communication channels in your integrations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/channels/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_clickup_lists(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer to identify the integration for retrieving ClickUp lists."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_clickup_lists_retrieve'."]:  # noqa: E501
    """Retrieve ClickUp lists for a specific project integration.

    Use this tool to obtain a list of ClickUp lists associated with a specific project and integration ID through the Datadog API."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/clickup_lists/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_clickup_spaces(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the integration to retrieve associated ClickUp spaces."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access spaces for. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_clickup_spaces_retrieve'."]:  # noqa: E501
    """Retrieve ClickUp spaces for a specific integration.

    Use this tool to get a list of ClickUp spaces linked to a particular integration within a project. This is useful for managing or understanding the spaces connected to your integrations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/clickup_spaces/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_clickup_workspaces(
    context: ToolContext,
    integration_unique_identifier: Annotated[int, "A unique integer identifying the integration for retrieving ClickUp workspaces."],  # noqa: E501
    project_id: Annotated[str, "Project ID to access specific ClickUp workspaces. Obtain the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_clickup_workspaces_retrieve'."]:  # noqa: E501
    """Retrieve ClickUp workspaces for a project integration.

    Use this tool to obtain the ClickUp workspaces associated with a specific project integration in Datadog. Ideal for checking or managing workspace details within the integration."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/clickup_workspaces/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_unique_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_email_verification_integration(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    integration_id: Annotated[int | None, "A unique integer identifying the integration to set up email verification for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project for which the email verification integration is to be initiated. Obtain this ID by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_email_verify_create'."]:  # noqa: E501
    """Initiate an email verification integration for a project.

    This tool initiates the email verification integration for a specified project and integration ID on the Datadog platform. Use it to set up email verification for project integrations.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEEMAILVERIFICATIONINTEGRATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not integration_id:
        missing_params.append(("integration_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEEMAILVERIFICATIONINTEGRATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEEMAILVERIFICATIONINTEGRATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/email/verify/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEEMAILVERIFICATIONINTEGRATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_github_repos_for_integration(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer representing the integration whose associated GitHub repositories will be retrieved."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project you wish to access in Datadog. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_github_repos_retrieve'."]:  # noqa: E501
    """Retrieve GitHub repositories for a specified integration.

    Call this tool to get a list of GitHub repositories associated with a specific integration in a Datadog project. Useful for managing or reviewing linked repositories."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/github_repos/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_google_accessible_accounts(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the specific integration."],
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve this ID by making a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_google_accessible_accounts_retrieve'."]:  # noqa: E501
    """Retrieve accessible Google accounts for integration.

    This tool retrieves a list of Google accounts accessible through a specified integration in a Datadog project. It should be called when you need to access or verify Google account integrations for a specific project. The tool returns the accessible accounts related to the integration."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/google_accessible_accounts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_google_conversion_data(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the integration for which to retrieve Google conversion actions."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you wish to access. Use this to retrieve specific Google conversion actions. You can find the project ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_google_conversion_actions_retrieve'."]:  # noqa: E501
    """Retrieve Google conversion actions for a specific project.

    Use this tool to obtain Google conversion actions associated with a given project in Datadog. This is useful for monitoring and analyzing conversion metrics within your integrated Google services."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/google_conversion_actions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_linear_teams(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the specific integration to retrieve Linear team details."],  # noqa: E501
    project_identifier: Annotated[str, "The ID of the project to access. Obtain it through the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_linear_teams_retrieve'."]:  # noqa: E501
    """Fetch Linear team details for a specific integration.

    This tool retrieves information about Linear teams associated with a specific project and integration."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/linear_teams/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_linkedin_ads_accounts(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer identifying the LinkedIn integration for the project."],  # noqa: E501
    project_id: Annotated[str, "Unique ID of the project for accessing LinkedIn Ads accounts. Obtainable by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_linkedin_ads_accounts_retrieve'."]:  # noqa: E501
    """Retrieve LinkedIn Ads accounts for a project integration.

    This tool retrieves LinkedIn Ads account details for a specified project integration in Datadog. Use it to access LinkedIn Ads accounts associated with a given project to manage or analyze ad campaigns."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/linkedin_ads_accounts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_linkedin_ads_conversion_rules(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer value identifying the LinkedIn integration."],
    project_id: Annotated[str, "The ID of the project to access LinkedIn Ads conversion rules. Retrieve via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_linkedin_ads_conversion_rules_retrieve'."]:  # noqa: E501
    """Retrieve LinkedIn Ads conversion rules for a specific project.

    Use this tool to obtain LinkedIn Ads conversion rules associated with a specific project in Datadog. Essential for analyzing conversion strategies and performance within LinkedIn Ads."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/linkedin_ads_conversion_rules/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_twilio_phone_numbers(
    context: ToolContext,
    integration_id: Annotated[int, "A unique integer value identifying this Twilio integration to retrieve phone numbers for."],  # noqa: E501
    project_id_for_twilio_integration: Annotated[str, "The ID of the project to access Twilio phone numbers. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_twilio_phone_numbers_retrieve'."]:  # noqa: E501
    """Retrieve Twilio phone numbers for a specific integration.

    Use this tool to obtain the list of Twilio phone numbers associated with a specific integration in a project. It's useful for managing or auditing phone numbers linked to Twilio integrations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/{id}/twilio_phone_numbers/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=integration_id, project_id=project_id_for_twilio_integration),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_integration_authorization(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project to access integration authorization details. Obtainable via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'integrations_authorize_retrieve'."]:
    """Retrieve integration authorization details for a project.

    Use this tool to get the authorization details for integrations within a specified project on the Datadog platform. It should be called when there is a need to understand or verify the integration authorization status for a particular project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/integrations/authorize/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_chat_completion(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The unique identifier for the project to access. Retrieve via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the chat completion response. Possible values are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'llm_gateway_v1_chat_completions_create'."]:  # noqa: E501
    """Create a chat completion using OpenAI or compatible models.

    Utilize this tool to generate chat responses using OpenAI or compatible models. It adheres to OpenAI's Chat Completions API format, providing a seamless integration for chat completion needs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATECHATCOMPLETION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATECHATCOMPLETION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATECHATCOMPLETION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/llm_gateway/v1/chat/completions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATECHATCOMPLETION"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_message_with_claude(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project you want to access. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    message_format: Annotated[str | None, "Specify the format of the message. Options are 'json' or 'txt'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'llm_gateway_v1_messages_create'."]:
    """Create a message using Anthropic's Claude models.

    This tool creates a new message with Anthropic's Claude models, using the format compatible with Anthropic's Messages API. It should be called when you need to generate a message leveraging Claude's capabilities.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEMESSAGEWITHCLAUDE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEMESSAGEWITHCLAUDE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEMESSAGEWITHCLAUDE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/llm_gateway/v1/messages/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEMESSAGEWITHCLAUDE"],
        params=remove_none_values({"format": message_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_log_attributes(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'logs_attributes_retrieve'."]:
    """Retrieve log attributes for a specific project.

    This tool retrieves log attributes for a specified project using its project ID. It should be called when detailed insights into log data attributes are needed for analysis or reporting."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/logs/attributes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_log_query(
    context: ToolContext,
    project_id: Annotated[str, "The unique Project ID for accessing the desired project in Datadog. Obtain by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'logs_query_create'."]:
    """Initiate a logs query for a specific project.

    Use this tool to create a new log query for a specified project in Datadog. It's useful for starting the process of retrieving logs data based on specific parameters."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/logs/query/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_logs_sparkline(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project for which you want to create a sparkline. Retrieve the ID using the /api/projects/ endpoint before using it here."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'logs_sparkline_create'."]:
    """Create a sparkline for project logs.

    Use this tool to create a sparkline visualization of logs for a specific project. Useful for summarizing log data trends over time."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/logs/sparkline/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_log_values(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to retrieve logs from. Obtain the project ID via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'logs_values_retrieve'."]:
    """Retrieve log values for a specified project.

    Use this tool to fetch log values associated with a specific project. It should be called when you need to analyze or view log data for monitoring or troubleshooting purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/logs/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_posthog_notebooks(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access notebooks for. Use /api/projects/ to find the ID."],  # noqa: E501
    filter_by_logged_in_user: Annotated[str | None, "Provide any value to filter results to notebooks created by the logged-in user."] = None,  # noqa: E501
    filter_criteria: Annotated[str | None, "String to filter notebooks. Use colon-separated key-value pairs, separated by space or comma."] = None,  # noqa: E501
    filter_date_before: Annotated[str | None, "Filter for notebooks created before this specified date and time. Use ISO 8601 format (e.g., '2023-10-01T15:00:00Z')."] = None,  # noqa: E501
    filter_from_date: Annotated[str | None, "Filter for notebooks created after this specific date and time. The date should be provided in an appropriate format, such as ISO 8601."] = None,  # noqa: E501
    notebook_creator_uuid: Annotated[int | None, "The UUID of the notebook's creator. Use this to filter notebooks by their creator."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of notebook results to return per page."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The index to start returning results from. This is used for pagination."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_list'."]:
    """Retrieve a list of notebooks from Datadog.

    Use this tool to get a list of notebooks associated with a specific project in Datadog. Ideal for viewing or managing notebooks within the Datadog platform."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"contains": filter_criteria, "created_by": notebook_creator_uuid, "date_from": filter_from_date, "date_to": filter_date_before, "limit": results_per_page, "offset": starting_index_for_results, "user": filter_by_logged_in_user}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_notebook(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project where the notebook will be created. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_create'."]:
    """Create a new notebook within a specified project.

    This tool allows for the creation of a new notebook within a specified project in Datadog. Ideal for organizing data and analyses in one place.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATENOTEBOOK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATENOTEBOOK"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATENOTEBOOK"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATENOTEBOOK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_notebook_details(
    context: ToolContext,
    notebook_short_id: Annotated[str, "The short ID of the notebook you want to retrieve details for. This is required to specify the notebook within the project."],  # noqa: E501
    project_identifier: Annotated[str, "Project ID to access specific project details. Obtain via /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_retrieve'."]:
    """Retrieve details of a specific notebook.

    Use this tool to get details of a notebook using its project ID and notebook short ID. This can be useful for accessing notebook content or metadata."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier, short_id=notebook_short_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_notebook(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project you are accessing. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    notebook_short_id: Annotated[str | None, "Provide the unique short ID of the notebook to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_update'."]:
    """Update a specific notebook's details.

    Use this tool to update the details of a specific notebook identified by its project and notebook IDs. Suitable for modifying existing notebook content or configuration.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATENOTEBOOK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not notebook_short_id:
        missing_params.append(("notebook_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATENOTEBOOK"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATENOTEBOOK"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=notebook_short_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATENOTEBOOK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_notebook_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    target_project_id: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to find the project ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    notebook_short_id: Annotated[str | None, "The unique short identifier for the notebook to be updated. This ID is required to specify which notebook to modify within the project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_partial_update'."]:
    """Update notebook details in a specified project.

    Use this tool to modify specific attributes of a notebook within a project in Datadog. This functionality is in early access and may change.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATENOTEBOOKDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))
    if not notebook_short_id:
        missing_params.append(("notebook_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATENOTEBOOKDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATENOTEBOOKDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=target_project_id, short_id=notebook_short_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATENOTEBOOKDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_notebook(
    context: ToolContext,
    notebook_short_id: Annotated[str, "The short ID of the notebook to mark as deleted. This ID uniquely identifies the notebook within the project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_destroy'."]:
    """Deletes a specific notebook by marking it as deleted.

    Use this tool to mark a notebook as deleted by its project and notebook ID. It doesn't perform a hard delete but updates the status to deleted."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=notebook_short_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_notebook_activity(
    context: ToolContext,
    notebook_short_id: Annotated[str, "The unique short identifier of the notebook for which activity details are requested. Used to specify the exact notebook within the project."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project you're trying to access. Obtain it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_activity_retrieve_2'."]:
    """Retrieve activity details of a specific notebook.

    Use this tool to get the activity details of a notebook within a specific project on Datadog. This is useful for monitoring changes and interactions with the notebook. Note that this feature is in early access and may undergo changes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/{short_id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=notebook_short_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_notebook_activity(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project from which to retrieve notebook activity. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_activity_retrieve'."]:
    """Retrieve activity details for a specific project notebook.

    Use this tool to get activity information related to notebooks within a specified project. Useful for monitoring and analyzing notebook usage."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_notebook_comments(
    context: ToolContext,
    project_identifier: Annotated[str, "Provide the Project ID to access specific notebook comments. Use /api/projects/ to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'notebooks_recording_comments_retrieve'."]:  # noqa: E501
    """Retrieve comments from notebook recordings in a project.

    Use this tool to get comments from notebook recordings within a specified project using Datadog's API."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/notebooks/recording_comments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_persisted_folders(
    context: ToolContext,
    project_id: Annotated[str, "Project ID of the project to access. Obtain the ID by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The initial index from which to start returning the results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persisted_folder_list'."]:
    """Retrieve persisted folders for a given project.

    Use this tool to obtain a list of all persisted folders associated with a specific project ID in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persisted_folder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def persist_folder_creation(
    context: ToolContext,
    folder_category: Annotated[str, "Specifies the type of the persisted folder. Options are 'home' for Home or 'pinned' for Pinned."],  # noqa: E501
    folder_creation_date: Annotated[str, "The date and time when the persisted folder is created, in ISO 8601 format."],  # noqa: E501
    folder_last_updated: Annotated[str, "A string representing the timestamp of the last update to the folder, in ISO 8601 format."],  # noqa: E501
    folder_type: Annotated[str, "Specifies the type of the folder. Possible values are 'home' for Home or 'pinned' for Pinned."],  # noqa: E501
    project_identifier: Annotated[str, "The unique identifier for the target project. Retrieve it via /api/projects/."],  # noqa: E501
    folder_path: Annotated[str | None, "Specify the path where the persisted folder will be created within the project. It should be a string representing the directory structure needed."] = None,  # noqa: E501
    folder_protocol: Annotated[str | None, "Specify the protocol for the persisted folder. Expected values are network protocol types like HTTP or FTP."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persisted_folder_create'."]:
    """Create a new persisted folder in Datadog.

    Use this tool to create a new persisted folder within a specified project in Datadog. It is called when organizing or categorizing project assets in a dedicated folder is needed."""  # noqa: E501
    request_data: Any = {"id": folder_type, "type": folder_category, "protocol": folder_protocol, "path": folder_path, "created_at": folder_creation_date, "updated_at": folder_last_updated}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persisted_folder/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persisted_folder(
    context: ToolContext,
    persisted_folder_uuid: Annotated[str, "A UUID string identifying the persisted folder to be retrieved."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project to access the persisted folder. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persisted_folder_retrieve'."]:
    """Retrieve a specific persisted folder within a project.

    This tool retrieves the details of a persisted folder by using the project and folder IDs. Call this tool when you need information about a particular persisted folder within a specified project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=persisted_folder_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_persisted_folder(
    context: ToolContext,
    folder_creation_date: Annotated[str, "The date when the folder was originally created, in string format. Use this to specify the creation timestamp for folder updates."],  # noqa: E501
    folder_id: Annotated[str, "The unique identifier of the folder to update within the project."],
    folder_type: Annotated[str, "Specify the folder type: 'home' for Home or 'pinned' for Pinned."],
    persisted_folder_id: Annotated[str, "A UUID string identifying the persisted folder to update."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve using /api/projects/."],
    update_timestamp: Annotated[str, "Provide the timestamp when the folder was last updated. Use ISO 8601 format (e.g., '2023-10-01T12:34:56Z')."],  # noqa: E501
    folder_path: Annotated[str | None, "Specify the path where the persisted folder is located within the project."] = None,  # noqa: E501
    update_protocol: Annotated[str | None, "Specify the protocol for the folder update. This value should be a string."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persisted_folder_update'."]:
    """Update details of a persisted folder in a project.

    Use this tool to update the details of a persisted folder within a specified project using the project and folder IDs."""  # noqa: E501
    request_data: Any = {"id": folder_id, "type": folder_type, "protocol": update_protocol, "path": folder_path, "created_at": folder_creation_date, "updated_at": update_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=folder_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_folder_info(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the Datadog project you want to access. Make a call to /api/projects/ to find it."],  # noqa: E501
    folder_creation_date: Annotated[str | None, "The date when the folder was created, expected in a string format (e.g., YYYY-MM-DD)."] = None,  # noqa: E501
    folder_id: Annotated[str | None, "The unique identifier of the persisted folder to update."] = None,  # noqa: E501
    folder_path: Annotated[str | None, "The path to the persisted folder to update in Datadog. This specifies the location or hierarchy within the project where the folder resides."] = None,  # noqa: E501
    folder_type: Annotated[str | None, "Specify the type of the folder. Options are 'home' for Home or 'pinned' for Pinned."] = None,  # noqa: E501
    persisted_folder_id: Annotated[str | None, "A UUID string identifying the persisted folder to update."] = None,  # noqa: E501
    protocol_type: Annotated[str | None, "Specify the protocol type for the persisted folder metadata. This is typically a string indicating the protocol used."] = None,  # noqa: E501
    update_timestamp: Annotated[str | None, "Timestamp indicating when the persisted folder was last updated. Use ISO 8601 format."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persisted_folder_partial_update'."]:
    """Update a persisted folder's metadata in Datadog.

    This tool updates the metadata of a specific persisted folder in a Datadog project. It should be called when you need to modify information about an existing persisted folder, such as its name or description."""  # noqa: E501
    request_data: Any = {"id": folder_id, "type": folder_type, "protocol": protocol_type, "path": folder_path, "created_at": folder_creation_date, "updated_at": update_timestamp}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=folder_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_folder(
    context: ToolContext,
    persisted_folder_id: Annotated[str, "A UUID string identifying the persisted folder to be deleted."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtain this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persisted_folder_destroy'."]:
    """Deletes a specified persisted folder from a project.

    Use this tool to delete a persisted folder from a specific project by specifying the project and folder IDs. This is useful for managing project resources and cleaning up unnecessary data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persisted_folder/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=persisted_folder_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_person_data(
    context: ToolContext,
    person_identifier: Annotated[int, "Unique integer identifying the person to retrieve information for."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project for accessing specific person data. Obtain it via /api/projects/."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the format in which to retrieve the person data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_retrieve'."]:
    """Retrieve detailed information about a specific person.

    Use this tool to access detailed information about a person in a specific project. It's suitable for reading existing person data within the specified project context."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_person_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_id: Annotated[int | None, "A unique integer representing a person to update in the project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "ID of the target project for accessing person data. Retrieve the ID via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the response output, either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_update'."]:
    """Update properties for a person in the project.

    This tool updates specific properties for a person using a \"$set\" event without removing or altering other existing properties. Use this to make partial updates to a person's data in the specified project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYPERSONDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_id:
        missing_params.append(("person_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYPERSONDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYPERSONDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYPERSONDETAILS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_person_info(
    context: ToolContext,
    project_id: Annotated[str, "Project ID for accessing the intended project. Obtain by calling /api/projects/."],  # noqa: E501
    creation_timestamp: Annotated[str | None, "The timestamp when the person data was initially created, in ISO 8601 format (e.g., '2023-10-05T14:48:00.000Z')."] = None,  # noqa: E501
    person_distinct_ids: Annotated[list[str] | None, "An array of unique identifiers for the person whose data is being updated. These identifiers help to distinguish between different users."] = None,  # noqa: E501
    person_id: Annotated[int | None, "The identifier of the person whose information is being updated. It should be an integer."] = None,  # noqa: E501
    person_identifier: Annotated[int | None, "A unique integer identifying the person to update."] = None,  # noqa: E501
    person_name: Annotated[str | None, "The name of the person whose details are being updated. This should be a string representing the person's full name."] = None,  # noqa: E501
    person_properties: Annotated[str | None, "Stringified JSON containing specific person properties to update."] = None,  # noqa: E501
    response_format: Annotated[str | None, "The format of the response. Options are 'csv' or 'json'."] = None,  # noqa: E501
    user_uuid: Annotated[str | None, "The unique identifier for the person to be updated. Must be a valid UUID string."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_partial_update'."]:
    """Update person details using partial data.

    This tool updates specific attributes of a person's data within a project. Ideal for modifying user properties via the PATCH method."""  # noqa: E501
    request_data: Any = {"id": person_id, "name": person_name, "distinct_ids": person_distinct_ids, "properties": person_properties, "created_at": creation_timestamp, "uuid": user_uuid}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_person(
    context: ToolContext,
    person_id: Annotated[int, "A unique integer identifying the person to be deleted."],
    project_id: Annotated[str, "The ID of the project to access. Retrieve by calling /api/projects/."],  # noqa: E501
    delete_events: Annotated[bool | None, "Set to true to create a task to delete all events associated with this person, batched and executed at 5AM UTC every Sunday."] = False,  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response data. Choose between 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_destroy'."]:
    """Delete an individual person from a project.

    This tool deletes a specific person from a given project. Use it when you need to remove an individual person. For deleting multiple persons at once, consider using a bulk deletion method."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({"delete_events": delete_events, "format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_person_activity(
    context: ToolContext,
    person_identifier: Annotated[int, "A unique integer value identifying the person. Required for retrieving their activity details."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Obtainable via /api/projects/."],
    response_format: Annotated[str | None, "Specify the format of the response, either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_activity_retrieve_2'."]:
    """Retrieve activities and details of a specific person.

    Use this tool to access and view the activities associated with a particular person in a given project. Can be useful for tracking user actions and engagement."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def queue_person_event_deletion(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_identifier: Annotated[int | None, "A unique integer value identifying the person whose events are to be deleted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Unique identifier for the project. Obtain via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Choose either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_delete_events_create'."]:
    """Queue deletion of events for a person during non-peak hours.

    Use this tool to schedule the deletion of all events associated with a specific person in a project. This task is performed during non-peak hours to optimize performance.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTDELETION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTDELETION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTDELETION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/delete_events/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["QUEUEPERSONEVENTDELETION"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_person_attribute(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    property_key_to_delete: Annotated[str | None, "Specify the property key you want to delete from a person's profile.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    person_identifier: Annotated[int | None, "A unique integer to identify the person whose property you want to delete.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you want to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the desired format for the response. Can be 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_delete_property_create'."]:
    """Delete a specific property from a person's profile.

    Use this tool to delete a specific property from a person's profile in a project. Suitable for managing user data by removing unneeded properties.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REMOVEPERSONATTRIBUTE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not property_key_to_delete:
        missing_params.append(("property_key_to_delete", "query"))
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REMOVEPERSONATTRIBUTE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REMOVEPERSONATTRIBUTE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/delete_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REMOVEPERSONATTRIBUTE"],
        params=remove_none_values({"$unset": property_key_to_delete, "format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_person_recordings(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_identifier: Annotated[int | None, "A unique integer value used to identify the person whose recordings are to be deleted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique identifier for the project. To obtain this ID, call /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    file_format: Annotated[str | None, "Specify the format type for the output. Acceptable values are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_delete_recordings_create'."]:  # noqa: E501
    """Queue deletion of all recordings associated with a person.

    Use this tool to initiate the deletion process for all recordings related to a specific person within a project. It should be called when you need to remove all recording data for a given individual.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REMOVEPERSONRECORDINGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REMOVEPERSONRECORDINGS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REMOVEPERSONRECORDINGS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/delete_recordings/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REMOVEPERSONRECORDINGS"],
        params=remove_none_values({"format": file_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_person_properties_timeline(
    context: ToolContext,
    person_id: Annotated[int, "A unique integer value identifying this person."],
    project_id: Annotated[str, "The unique identifier for the project you're trying to access. Obtain it via a call to /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response. Accepted values are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_properties_timeline_retrieve'."]:  # noqa: E501
    """Retrieve the timeline of a person's properties changes.

    Use this tool to fetch the timeline of changes to a person's properties within a project. This is useful for understanding how a person's attributes have changed over time."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/properties_timeline/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def split_person_entity_create(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    person_identifier: Annotated[int | None, "A unique integer identifying the person for whom a sub-entity will be created.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve by calling `/api/projects/`.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    output_format: Annotated[str | None, "Specifies the output format for the response. Accepts 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_split_create'."]:
    """Create a sub-person entity for an existing person.

    Use this tool to create a sub-person entity for an existing person within a project. This is useful for scenarios requiring detailed segmentation or tracking of individual entities.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["SPLITPERSONENTITYCREATE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["SPLITPERSONENTITYCREATE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["SPLITPERSONENTITYCREATE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/split/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["SPLITPERSONENTITYCREATE"],
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_user_attribute(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    property_key: Annotated[str | None, "The key for the property you want to update for the person.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    property_value: Annotated[str | None, "Specify the value of the property to be updated for a person.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    person_identifier: Annotated[int | None, "A unique integer value used to identify the person whose property is being updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID to access the relevant project. Retrieve it via `/api/projects/`.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format for the response. Use 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_update_property_create'."]:
    """Update a specific property for a person in a project.

    Use this tool to update a property for a person within a specified project. This is useful for modifying attributes of a person using the Datadog API, such as user properties in an analytics context.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYUSERATTRIBUTE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not property_key:
        missing_params.append(("property_key", "query"))
    if not property_value:
        missing_params.append(("property_value", "query"))
    if not person_identifier:
        missing_params.append(("person_identifier", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYUSERATTRIBUTE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYUSERATTRIBUTE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/{id}/update_property/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=person_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYUSERATTRIBUTE"],
        params=remove_none_values({"format": response_format, "key": property_key, "value": property_value}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def person_activity_info(
    context: ToolContext,
    access_project_id: Annotated[str, "The ID of the project you want to access. Call /api/projects/ to find this ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format for the response, either 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_activity_retrieve'."]:
    """Retrieve details of a person's activities.

    Use this tool to get information on a person's activities within a specific project. Ideal for analyzing user engagement or actions in a project context. For creating or updating person details, consider using the capture API or relevant SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=access_project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def bulk_delete_persons(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access for deleting persons. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    distinct_ids_list: Annotated[dict[str, str] | None, "A list of distinct IDs to delete associated persons, limited to 1000 IDs per call.  Only used when mode is 'execute'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specifies the format of the response, either 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    posthog_person_ids: Annotated[dict[str, str] | None, "A JSON list of up to 1000 PostHog person IDs to delete.  Only used when mode is 'execute'."] = None,  # noqa: E501

    delete_associated_events: Annotated[bool | None, "If true, a task is created to delete all events related to the persons being deleted. It runs every Sunday at 5AM UTC.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_bulk_delete_create'."]:
    """Bulk delete persons by IDs in a specified project.

    Use this tool to delete multiple persons in bulk by providing a list of either PostHog person IDs or distinct IDs, with a limit of 1000 IDs per call. Ideal for managing large datasets effectively.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["BULKDELETEPERSONS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["BULKDELETEPERSONS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["BULKDELETEPERSONS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/bulk_delete/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["BULKDELETEPERSONS"],
        params=remove_none_values({"delete_events": delete_associated_events, "distinct_ids": distinct_ids_list, "format": response_format, "ids": posthog_person_ids}),  # noqa: E501
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_persons_cohorts(
    context: ToolContext,
    project_id: Annotated[str, "Project ID of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format of the response: 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_cohorts_retrieve'."]:
    """Retrieve information about person cohorts in a project.

    Use this tool to read person cohorts associated with a specific project. This is not for creating or updating persons; for those actions, use the capture API or appropriate SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/cohorts/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_funnel(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Find it by calling /api/projects/."],  # noqa: E501
    output_format: Annotated[str | None, "Specify the desired output format. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_funnel_retrieve'."]:
    """Retrieve persons data for a project funnel.

    This tool retrieves information about persons in a project's funnel using a specified project ID. It's useful for understanding and analyzing the flow of individuals within the funnel in a project context."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/funnel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": output_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_or_update_persons(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique identifier for the project to access. Use /api/projects/ to find the ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_funnel_create'."]:
    """Create or update persons in a project funnel.

    Use this tool to create or update persons within a specific project's funnel on Datadog, aligning with the correct project ID. For reading or deleting persons, consider other API endpoints as suggested.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEORUPDATEPERSONS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEORUPDATEPERSONS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEORUPDATEPERSONS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/funnel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEORUPDATEPERSONS"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def funnel_correlation_persons_retrieve(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project you want to access. Retrieve this ID by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Format of the response data. Choose 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_funnel_correlation_retrieve'."]:  # noqa: E501
    """Retrieve funnel correlation data for persons in a project.

    This tool retrieves correlation data for persons in a specific project's funnel. It should be called when you need insights into funnel performance related to specific persons. For managing persons, consider using the capture API or SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/funnel/correlation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_persons_funnel_correlation(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID for accessing the project. Obtain by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the format of the response. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_funnel_correlation_create'."]:  # noqa: E501
    """Create or update persons in a funnel correlation.

    This tool is used to handle persons within a funnel correlation context, specifically for reading and deleting purposes. For creating or updating persons, consider using the capture API or relevant SDKs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ADDPERSONSFUNNELCORRELATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ADDPERSONSFUNNELCORRELATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ADDPERSONSFUNNELCORRELATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/funnel/correlation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ADDPERSONSFUNNELCORRELATION"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_persons_lifecycle(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access the specific project. Use /api/projects/ to find the ID if unknown."],  # noqa: E501
    response_format: Annotated[str | None, "The format in which to retrieve lifecycle information. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_lifecycle_retrieve'."]:
    """Retrieve lifecycle information of persons in a project.

    Use this tool to retrieve lifecycle data of persons associated with a specified project. It's suitable for reading person data; for creation or updates, refer to other APIs like the capture API."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/lifecycle/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def reset_person_distinct_id(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project you want to access. Use the /api/projects/ endpoint to retrieve available IDs.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    response_format: Annotated[str | None, "Specify the response format. Options are 'csv' or 'json'.  Only used when mode is 'execute'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_reset_person_distinct_id_create'."]:  # noqa: E501
    """Reset a distinct_id for a deleted person to reuse it.

    This tool is used to reset a distinct_id associated with a deleted person in the specified project, allowing the distinct_id to be reused.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path, query parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path, query parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["RESETPERSONDISTINCTID"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path, query parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["RESETPERSONDISTINCTID"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["RESETPERSONDISTINCTID"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/persons/reset_person_distinct_id/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["RESETPERSONDISTINCTID"],
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_persons_stickiness(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project to access. Retrieve by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Determines the format of the response. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_stickiness_retrieve'."]:
    """Retrieve information about persons' stickiness in a project.

    Use this tool to retrieve data on how often individuals engage with a platform within a specified project. This endpoint provides insights into user behavior patterns. For creating or updating persons, consider other APIs or SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/stickiness/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_person_trends(
    context: ToolContext,
    project_identifier: Annotated[str, "The Project ID required to access and retrieve trends of persons for a specific project. Use the /api/projects/ endpoint to find the ID."],  # noqa: E501
    response_format: Annotated[str | None, "Specify the format for the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_trends_retrieve'."]:
    """Retrieve trends related to persons in a project.

    Use this tool to get insights and trends about persons within a specific project. Useful for analyzing changes in user behavior and engagement over time."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/trends/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_person_info(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access specific project details in Datadog. Obtain this by calling /api/projects/."],  # noqa: E501
    response_format: Annotated[str | None, "Specifies the format of the response data. Options are 'csv' or 'json'."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'persons_values_retrieve'."]:
    """Retrieve or delete person details in a Datadog project.

    This tool allows you to retrieve person details from a specific project in Datadog. Note that for creating or updating persons, it's recommended to use the capture API or relevant SDKs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/persons/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"format": response_format}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_plugin_config_logs(
    context: ToolContext,
    plugin_configuration_id: Annotated[str, "The ID of the plugin configuration whose logs you want to retrieve."],  # noqa: E501
    project_id: Annotated[str, "The unique identifier for the project whose plugin logs you want to access. Obtain this by calling /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page for the log list."] = None,  # noqa: E501
    starting_index: Annotated[int | None, "The starting index for results retrieval, used to paginate through logs."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'plugin_configs_logs_list'."]:
    """Retrieve logs for a specific plugin configuration.

    This tool retrieves logs related to a specific plugin configuration within a project. It should be called when you need to access and review logs for debugging, monitoring, or auditing purposes."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/plugin_configs/{plugin_config_id}/logs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), plugin_config_id=plugin_configuration_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_property_definitions(
    context: ToolContext,
    project_id: Annotated[str, "ID of the project you're accessing. Use /api/projects/ to find it."],  # noqa: E501
    event_names_json: Annotated[str | None, "A JSON-encoded string of event names to populate `is_seen_on_filtered_events` in the response."] = None,  # noqa: E501
    exclude_core_properties: Annotated[bool | None, "Set to true to exclude core properties from the response; false to include them."] = False,  # noqa: E501
    exclude_hidden_properties: Annotated[bool | None, "Set to true to exclude properties marked as hidden from the results."] = False,  # noqa: E501
    excluded_properties_list: Annotated[str | None, "A JSON-encoded list of property names to exclude from the response."] = None,  # noqa: E501
    filter_feature_flag_properties: Annotated[bool | None, "Set to true to include only feature flag properties, false to exclude them."] = None,  # noqa: E501
    filter_properties_by_event_names: Annotated[bool | None, "Set to true to return only properties for events specified in `event_names`."] = None,  # noqa: E501
    filter_properties_list: Annotated[str | None, "Comma-separated list of properties to filter the results by."] = None,  # noqa: E501
    group_type_index_for_group_properties: Annotated[int | None, "Provide the group type index specifically for properties of type 'group'. This should only be set if the type is set to 'group'."] = None,  # noqa: E501
    include_only_numerical_properties: Annotated[bool | None, "Set to true to return only numerical property definitions, false to exclude them."] = None,  # noqa: E501
    property_definition_type: Annotated[str | None, "Specify which type of property definitions to return: 'event', 'person', 'group', or 'session'."] = "event",  # noqa: E501
    result_start_index: Annotated[int | None, "The initial index from which to return the results. Use this to paginate through results starting from a specific index."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page when retrieving property definitions."] = None,  # noqa: E501
    search_query: Annotated[str | None, "Keyword to search properties by name in the project."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'property_definitions_list'."]:
    """Retrieve a list of property definitions for a specific project.

    Use this tool to fetch property definitions from a specified project by providing the project ID. It returns the available property definitions related to that project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/property_definitions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"event_names": event_names_json, "exclude_core_properties": exclude_core_properties, "exclude_hidden": exclude_hidden_properties, "excluded_properties": excluded_properties_list, "filter_by_event_names": filter_properties_by_event_names, "group_type_index": group_type_index_for_group_properties, "is_feature_flag": filter_feature_flag_properties, "is_numerical": include_only_numerical_properties, "limit": results_per_page, "offset": result_start_index, "properties": filter_properties_list, "search": search_query, "type": property_definition_type}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_property_definitions(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve it via /api/projects/."],  # noqa: E501
    property_definition_id: Annotated[str, "A UUID string identifying the specific property definition."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'property_definitions_retrieve'."]:
    """Retrieve details of property definitions for a given project.

    Use this tool to get information about specific property definitions within a project by providing the project ID and property definition ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/property_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=property_definition_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_property_definitions(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    property_definition_id: Annotated[str | None, "A UUID string identifying the specific property definition to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID to access specific project details in Datadog. Call /api/projects/ to find it.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'property_definitions_update'."]:
    """Update property definitions for a specific project.

    Call this tool to update the property definitions of a specified project in your Datadog account.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITIONS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not property_definition_id:
        missing_params.append(("property_definition_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITIONS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITIONS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/property_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=property_definition_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITIONS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_property_definition(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    property_definition_id: Annotated[str | None, "A UUID string identifying the property definition to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'property_definitions_partial_update'."]:  # noqa: E501
    """Update partial property definition details.

    Use this tool to update specific details of a property definition for a given project. It should be called when you need to modify existing property information without altering the entire dataset.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not property_definition_id:
        missing_params.append(("property_definition_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/property_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=property_definition_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROPERTYDEFINITION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_property_definition(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve it via the /api/projects/ endpoint."],  # noqa: E501
    property_definition_id: Annotated[str, "A UUID string identifying the property definition to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'property_definitions_destroy'."]:
    """Delete a property definition from a project.

    This tool deletes a specific property definition from a given project in Datadog. It should be called when a property definition is no longer needed or requires removal."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/property_definitions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=property_definition_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def check_property_event_association(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the target project. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'property_definitions_seen_together_retrieve'."]:  # noqa: E501
    """Check if a property has been seen with specified event names.

    This tool checks whether a specified property has ever been associated with a list of given event names. It returns a mapping of each event name to a boolean, indicating whether the association exists. Useful for analyzing event-property relationships in a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/property_definitions/seen_together/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_query_from_project(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project you want to access. Obtainable via a call to /api/projects/."],  # noqa: E501
    query_id: Annotated[str, "The unique identifier of the query you want to retrieve from the project. This is required to specify which query to access."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'query_retrieve'."]:
    """Retrieve a specific query from a project.

    Use this tool to obtain detailed information about a specific query associated with a project in Datadog. It is particularly useful for fetching query details using a project and query identifier."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/query/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_project_query(
    context: ToolContext,
    project_id: Annotated[str, "ID of the project you want to access. Retrieve it via a call to /api/projects/."],  # noqa: E501
    query_id: Annotated[str, "The unique identifier for the query to be deleted within the project."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'query_destroy'."]:
    """Delete a specific project query.

    Use this tool to delete a specific query within a project on Datadog. The operation is experimental and involves providing the project and query IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/query/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_query_log_details(
    context: ToolContext,
    project_id: Annotated[str, "Project ID for accessing the specific project. Retrieve by calling /api/projects/."],  # noqa: E501
    query_id: Annotated[str, "The unique identifier of the query to retrieve log details. The query must have been issued within the last 24 hours."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'query_log_retrieve'."]:
    """Retrieve query log details for a specified query ID.

    Fetches details from the query_log_archive table for a specific query ID, provided the query was issued in the last 24 hours."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/query/{id}/log/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def check_async_auth(
    context: ToolContext,
    project_id_for_auth_check: Annotated[str, "The ID of the Datadog project to check access for creating asynchronous queries. Obtain the ID by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'query_check_auth_for_async_create'."]:  # noqa: E501
    """Checks authorization for creating asynchronous queries.

    Call this tool to determine if a user is authorized to create asynchronous queries in a specific Datadog project. Useful for workflows that need to verify permissions before proceeding with query operations."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/query/check_auth_for_async/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_auth_check),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_draft_sql_query(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access for the draft SQL query. Obtainable via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'query_draft_sql_retrieve'."]:
    """Retrieve draft SQL query for a specific project.

    This tool retrieves the draft SQL query for a given project identified by its project ID. It is useful for obtaining the current draft version of SQL queries in development within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/query/draft_sql/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_session_playlists(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project you're trying to access. Obtain it by calling /api/projects/."],  # noqa: E501
    created_by_user_id: Annotated[int | None, "ID of the user who created the playlist. Must be an integer."] = None,  # noqa: E501
    playlist_short_id: Annotated[str | None, "A specific short identifier for the playlist to retrieve."] = None,  # noqa: E501
    results_offset: Annotated[int | None, "The index from which to start returning results. Useful for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Number of results to return per page."] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_list'."]:  # noqa: E501
    """Retrieve session recording playlists, including synthetic ones.

"""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"created_by": created_by_user_id, "limit": results_per_page, "offset": results_offset, "short_id": playlist_short_id}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def new_session_recording_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project for which you want to create a session recording playlist. Obtain this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_create'."]:  # noqa: E501
    """Create a new session recording playlist for a project.

    Use this tool to create a session recording playlist within a specified project by providing the project ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["NEWSESSIONRECORDINGPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["NEWSESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["NEWSESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["NEWSESSIONRECORDINGPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_recording_playlist(
    context: ToolContext,
    playlist_short_id: Annotated[str, "The short ID of the session recording playlist to retrieve. This helps identify the specific playlist to fetch."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve it by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_retrieve'."]:  # noqa: E501
    """Retrieve a session recording playlist for a project.

    Use this tool to get details about a specific session recording playlist by providing the project and playlist IDs. It is helpful for tracking and viewing file system interactions related to sessions."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=playlist_short_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_session_recording_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project you want to access. Retrieve the ID by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    playlist_short_identifier: Annotated[str | None, "A unique identifier for the session recording playlist to be updated. It is used to specify the exact playlist within the project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_update'."]:  # noqa: E501
    """Update session recording playlists for a project.

    Use this tool to update existing session recording playlists within a specified project. This is typically used when changes to playlist details are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDINGPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not playlist_short_identifier:
        missing_params.append(("playlist_short_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDINGPLAYLIST"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=playlist_short_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYSESSIONRECORDINGPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def edit_session_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The unique identifier of the project. Obtain it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    playlist_short_id: Annotated[str | None, "The short ID of the session recording playlist to modify. Required for identifying the playlist.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_partial_update'."]:  # noqa: E501
    """Partially update a session recording playlist.

    Call this tool to update specific attributes of a session recording playlist by providing the project and playlist IDs. Useful for modifying playlist details without replacing all data.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EDITSESSIONPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))
    if not playlist_short_id:
        missing_params.append(("playlist_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EDITSESSIONPLAYLIST"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EDITSESSIONPLAYLIST"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier, short_id=playlist_short_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EDITSESSIONPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_session_recording_playlist(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    session_recording_playlist_short_id: Annotated[str, "A unique short identifier for the session recording playlist to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_destroy'."]:  # noqa: E501
    """Soft delete a session recording playlist in a project.

    Use this tool to mark a session recording playlist as deleted within a specified project. This tool should be called when you need to remove access to a session recording playlist without permanently deleting its data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier, short_id=session_recording_playlist_short_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_recording_playlist_views(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access specific recording playlists. Use /api/projects/ to find the ID."],  # noqa: E501
    recording_short_id: Annotated[str, "The short identifier of the recording playlist to retrieve views for. Required for accessing specific recordings."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_recordings_retrieve'."]:  # noqa: E501
    """Retrieve and log views of session recording playlists.

    Use this tool to track and retrieve logs each time a session recording playlist is viewed. It helps in monitoring how often and by whom the playlists are accessed."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/recordings/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, short_id=recording_short_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_session_recording_to_playlist(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "Project ID to access the specific project. Retrieve by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_identifier: Annotated[str | None, "The unique ID of the session recording to be added to the playlist. This ID identifies the specific recording you want to track or log in the given playlist.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_short_id: Annotated[str | None, "The unique short identifier of the session recording to add to the playlist within the specified project.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_recordings_create'."]:  # noqa: E501
    """Add a session recording to a specified playlist.

    This tool allows you to add a session recording to a specific playlist within a project. It should be called when you need to track or log a session recording view in a particular playlist.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ADDSESSIONRECORDINGTOPLAYLIST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not session_recording_identifier:
        missing_params.append(("session_recording_identifier", "path"))
    if not session_recording_short_id:
        missing_params.append(("session_recording_short_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ADDSESSIONRECORDINGTOPLAYLIST"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ADDSESSIONRECORDINGTOPLAYLIST"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/recordings/{session_recording_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, session_recording_id=session_recording_identifier, short_id=session_recording_short_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ADDSESSIONRECORDINGTOPLAYLIST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_session_recording2(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Obtainable via /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "The unique identifier for the session recording to be deleted."],  # noqa: E501
    session_recording_short_id: Annotated[str, "The unique short ID of the session recording to delete from the playlist."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recording_playlists_recordings_destroy'."]:  # noqa: E501
    """Delete a session recording from a playlist in a project.

    Use this tool to permanently delete a specific session recording from a designated playlist within a project. Ideal for managing and cleaning up session data."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recording_playlists/{short_id}/recordings/{session_recording_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, session_recording_id=session_recording_id, short_id=session_recording_short_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_session_recordings(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier of the project for which to retrieve session recordings. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of session recordings to return per page. This controls the pagination size."] = None,  # noqa: E501
    start_index_for_results: Annotated[int | None, "The initial index from which to start returning the results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_list'."]:
    """Retrieve session recordings for a specific project.

    Use this tool to get a list of session recordings associated with a particular project ID. Useful for accessing session data stored in a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index_for_results}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_session_recording(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Find the project ID with /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "A UUID string that uniquely identifies the session recording to retrieve."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_retrieve'."]:
    """Retrieve details of a specific session recording.

    Use this tool to get detailed information about a session recording for a given project using its ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_session_recording2(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    session_recording_id: Annotated[str | None, "A UUID string identifying the session recording to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. To find this ID, use the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_update'."]:
    """Update session recording details for a specific project.

    This tool updates the details of a session recording for a given project in Datadog. Use it to modify existing recording parameters by specifying the project and recording ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING2"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not session_recording_id:
        missing_params.append(("session_recording_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING2"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING2"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDING2"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def edit_session_recording(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    session_recording_id: Annotated[str | None, "A UUID string used to uniquely identify the session recording to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_partial_update'."]:  # noqa: E501
    """Update specific details of a session recording.

    Use this tool to modify attributes of a session recording by specifying the project and recording IDs. Ideal for updating incomplete data or correcting entries.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EDITSESSIONRECORDING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not session_recording_id:
        missing_params.append(("session_recording_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EDITSESSIONRECORDING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EDITSESSIONRECORDING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EDITSESSIONRECORDING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def destroy_session_recording(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project containing the session recording to delete. Retrieve using /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "A UUID string identifying this session recording for deletion."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_destroy'."]:
    """Delete a specific session recording from a project.

    Use this tool to delete a session recording from a specified project in Datadog. Ideal for managing and removing unwanted or outdated session recordings."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=session_recording_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_session_recordings_sharing_links(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access session recordings. Retrieve via /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "The unique ID of the session recording for which you want to obtain sharing links. This ID is required to specify the exact recording within the project."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_sharing_list'."]:
    """Obtain sharing links for a Datadog session recording.

    Use this tool to access the sharing links for a specific session recording in Datadog. This is helpful for reviewing or sharing recordings with team members or stakeholders."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{recording_id}/sharing/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, recording_id=session_recording_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_recording_share_password(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Use the /api/projects/ endpoint to find the project ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    recording_id: Annotated[str | None, "Unique identifier of the recording for which the sharing password is being created.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_sharing_passwords_create'."]:  # noqa: E501
    """Create a new password for sharing configuration of a recording.

    This tool is used to create a new password for the sharing configuration of a specific session recording. It should be called when there's a need to password-protect access to a session recording within a project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATERECORDINGSHAREPASSWORD"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not recording_id:
        missing_params.append(("recording_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATERECORDINGSHAREPASSWORD"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATERECORDINGSHAREPASSWORD"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{recording_id}/sharing/passwords/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, recording_id=recording_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATERECORDINGSHAREPASSWORD"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_sharing_password(
    context: ToolContext,
    password_identifier: Annotated[str, "The unique identifier for the password to be removed from the sharing configuration."],  # noqa: E501
    project_identifier: Annotated[str, "The unique ID of the project for accessing its session recordings. Retrieve this by calling /api/projects/."],  # noqa: E501
    session_recording_id: Annotated[str, "The ID of the session recording from which the password will be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_sharing_passwords_destroy'."]:  # noqa: E501
    """Delete a sharing configuration password from a session recording.

    Use to remove a specific password from the sharing configuration of a session recording in a given project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{recording_id}/sharing/passwords/{password_id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), password_id=password_identifier, project_id=project_identifier, recording_id=session_recording_id),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_session_recording_sharing(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The unique string identifier for the project you want to access. Obtainable via the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    session_recording_id: Annotated[str | None, "The unique ID of the session recording to update the sharing status for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'session_recordings_sharing_refresh_create'."]:  # noqa: E501
    """Refresh session recording sharing status.

    Call this tool to refresh or update the sharing status of a session recording for a specified project and recording ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGSHARING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not session_recording_id:
        missing_params.append(("session_recording_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGSHARING"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGSHARING"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/session_recordings/{recording_id}/sharing/refresh/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, recording_id=session_recording_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESESSIONRECORDINGSHARING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_session_property_definitions(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access session property definitions. Obtainable via the /api/projects/ call."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'sessions_property_definitions_retrieve'."]:  # noqa: E501
    """Retrieve definitions of session properties for a project.

    Use this tool to get detailed information about session property definitions for a specific project in Datadog. Ideal for understanding the attributes of each session."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/sessions/property_definitions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_project_session_values(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access session values. Obtain it via a call to /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'sessions_values_retrieve'."]:
    """Retrieve session values for a specific project.

    This tool is used to retrieve session values for a given project by its ID. It should be called when users need detailed session data from a specific DataDog project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/sessions/values/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_subscriptions(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access subscriptions for. Use /api/projects/ to find the ID if unknown."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page for the subscription list."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The index position to start returning results from within the subscription list."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'subscriptions_list'."]:
    """Retrieve a list of subscriptions for a specific project.

    Use this tool to get details on all subscriptions associated with a given project, identified by project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/subscriptions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_subscription(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'subscriptions_create'."]:
    """Create a new subscription for a specified project.

    Use this tool to add a subscription to a specific project. It is called when you need to create a subscription within a project using the project's ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROJECTSUBSCRIPTION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROJECTSUBSCRIPTION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROJECTSUBSCRIPTION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/subscriptions/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROJECTSUBSCRIPTION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_subscription_info(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Obtain it via a call to /api/projects/."],  # noqa: E501
    subscription_id: Annotated[int, "A unique integer value identifying this subscription."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'subscriptions_retrieve'."]:
    """Retrieve details of a specific project subscription.

    Use this tool to obtain detailed information about a specific subscription within a given project by providing the project and subscription IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_subscription_settings(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    subscription_id: Annotated[int | None, "A unique integer identifying the subscription to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it via /api/projects/ if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'subscriptions_update'."]:
    """Update subscription settings for a project.

    This tool updates the settings of a subscription for a specified project in Datadog. It should be called when modifications to subscription details are needed.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONSETTINGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not subscription_id:
        missing_params.append(("subscription_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONSETTINGS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONSETTINGS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONSETTINGS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_subscription_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    subscription_id: Annotated[int | None, "A unique integer value identifying this subscription.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project you want to access. Retrieve it via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'subscriptions_partial_update'."]:
    """Update details of a project subscription.

    Use this tool to update specific details of a subscription within a project on Datadog. Ideal for modifying settings or information for an existing subscription.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not subscription_id:
        missing_params.append(("subscription_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESUBSCRIPTIONDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def unsubscribe_from_project_alerts(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve it from the /api/projects/ endpoint."],  # noqa: E501
    subscription_id: Annotated[int, "A unique integer identifier for the project alert subscription to be marked as deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'subscriptions_destroy'."]:
    """Set project alert subscription as deleted.

    Use this tool to mark a project alert subscription as deleted. This does not hard delete the model but updates its status to indicate deletion."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/subscriptions/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=subscription_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_surveys(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access. Retrieve project ID via the /api/projects/ endpoint."],  # noqa: E501
    initial_result_index: Annotated[int | None, "The starting index for returning survey results, used for pagination."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page, as an integer."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A search term to filter the list of surveys."] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_list'."]:
    """Retrieve a list of surveys for a given project.

    Use this tool to get a list of surveys associated with a specific project identified by its project ID. Each call logs a new view of the file system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": initial_result_index, "search": search_term}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_survey(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project for creating a survey. Retrieve this ID via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_create'."]:
    """Create a new survey for a project.

    Use this tool to initiate the creation of a new survey within a specified project. This tool should be called when you need to log a new survey for project tracking purposes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATESURVEY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATESURVEY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATESURVEY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATESURVEY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_survey_data(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve it via /api/projects/ if unknown."],  # noqa: E501
    survey_uuid: Annotated[str, "A UUID string identifying the specific survey to be retrieved."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_retrieve'."]:
    """Retrieve data for a specific survey using project and survey IDs.

    Call this tool to get detailed information about a specific survey by providing the project and survey identifiers. Useful for tracking survey views or accessing specific survey details."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_survey_tracking(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    survey_uuid: Annotated[str | None, "A UUID string that uniquely identifies the survey to track.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The unique identifier of the project to access. Retrieve this ID by making a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_update'."]:
    """Tracks a new view for a survey by logging access.

    Call this tool to log and track when a survey is viewed. It updates the survey view count in a specified project, providing insights into survey access frequency.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESURVEYTRACKING"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not survey_uuid:
        missing_params.append(("survey_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESURVEYTRACKING"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESURVEYTRACKING"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESURVEYTRACKING"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_survey_info(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    survey_uuid: Annotated[str | None, "A UUID string identifying the survey to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to find this ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_partial_update'."]:
    """Update information for a specific survey.

    Call this tool to update details of a specific survey in a project on Datadog. This is useful for modifying existing survey data, such as survey name, description, or other fields.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATESURVEYINFO"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not survey_uuid:
        missing_params.append(("survey_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATESURVEYINFO"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATESURVEYINFO"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATESURVEYINFO"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_survey(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project containing the survey to delete. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
    survey_uuid: Annotated[str, "A UUID string that uniquely identifies the survey to delete."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_destroy'."]:
    """Delete a survey from a specific project.

    Use this tool to delete a survey from a particular project in Datadog. This action is irreversible, so it should be called when a survey is no longer needed."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_survey_activity(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    survey_uuid: Annotated[str, "A UUID string uniquely identifying the survey to retrieve activity logs for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_activity_retrieve_2'."]:
    """Retrieve logs of survey activity views.

    Call this tool to get logs of views for a specific survey within a project. Each GET request returns the activity related to how often and when the survey was accessed."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def duplicate_survey_to_projects(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    survey_uuid: Annotated[str | None, "A UUID string identifying the survey to be duplicated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    target_project_id: Annotated[str | None, "The ID of the target project where the survey will be duplicated. Obtain this ID via the /api/projects/ call.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_duplicate_to_projects_create'."]:  # noqa: E501
    """Duplicate a survey to multiple projects in one transaction.

    Use this tool to copy a survey into multiple projects simultaneously, ensuring an all-or-nothing transaction where failures result in rollback.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DUPLICATESURVEYTOPROJECTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not survey_uuid:
        missing_params.append(("survey_uuid", "path"))
    if not target_project_id:
        missing_params.append(("target_project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DUPLICATESURVEYTOPROJECTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DUPLICATESURVEYTOPROJECTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/duplicate_to_projects/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=target_project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DUPLICATESURVEYTOPROJECTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_survey_response_statistics(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve this using the /api/projects/ endpoint."],  # noqa: E501
    survey_uuid: Annotated[str, "A UUID string identifying the specific survey to retrieve statistics for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_stats_retrieve_2'."]:
    """Get survey response statistics for a specific survey.

    Retrieves detailed statistics for a given survey, including event counts, unique respondents, and conversion rates. Use this tool to analyze survey performance over a specified date range."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/stats/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def summarize_survey_responses(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    survey_uuid: Annotated[str | None, "A UUID string that uniquely identifies the survey for which responses are to be summarized.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique identifier string for the project. Obtain it by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_summarize_responses_create'."]:  # noqa: E501
    """Create a summary of survey responses for a project.

    This tool generates a summary of responses for a specific survey within a project. It should be called when you need to consolidate and analyze survey data.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["SUMMARIZESURVEYRESPONSES"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not survey_uuid:
        missing_params.append(("survey_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["SUMMARIZESURVEYRESPONSES"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["SUMMARIZESURVEYRESPONSES"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/{id}/summarize_responses/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=survey_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["SUMMARIZESURVEYRESPONSES"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def track_survey_activity(
    context: ToolContext,
    project_id: Annotated[str, "The Project ID to access and track survey activities. Find the ID using /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_activity_retrieve'."]:
    """Retrieve and log survey activity views.

    Use this tool to retrieve and log each view of survey activities in a project. It tracks when the surveys are accessed, effectively recording each GET request."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_survey_response_count(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project whose survey response count you want to retrieve. Use /api/projects/ to find the ID."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_responses_count_retrieve'."]:  # noqa: E501
    """Retrieve the count of survey responses for a project.

    Use this tool to get the total number of responses to surveys for a specified project. It's useful for tracking engagement and participation metrics."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/responses_count/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_survey_statistics(
    context: ToolContext,
    project_id: Annotated[str, "The unique identifier for the project to access. Get this by calling /api/projects/."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'surveys_stats_retrieve'."]:
    """Retrieve aggregated response statistics for surveys.

    Call this tool to obtain aggregated statistics for survey responses within a specified date range. Useful for analyzing overall survey performance, including total counts and response rates."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/surveys/stats/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_project_tasks(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier of the project for which to retrieve tasks. Obtain this ID via the /api/projects/ endpoint."],  # noqa: E501
    results_per_page: Annotated[int | None, "Number of task results to return per page. Use this to limit the result set size."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The zero-based index from which to begin returning task results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_list'."]:
    """Retrieve tasks for a specific project.

    This tool retrieves the list of tasks associated with a given project. Use it when you need to see all units of work within a specific project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_project_task(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project to access for task creation. Retrieve the ID using a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_create'."]:
    """Create a new task within a specified project.

    This tool is used to create a new task in a given project by specifying the project ID. It helps manage tasks effectively by adding units of work to be performed by an agent.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEPROJECTTASK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEPROJECTTASK"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEPROJECTTASK"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEPROJECTTASK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_project_task_details(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique ID of the project to access task details. Use /api/projects/ to find available project IDs."],  # noqa: E501
    task_id: Annotated[str, "A UUID string identifying the specific task within the project."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_retrieve'."]:
    """Retrieve details of a specific task within a project.

    Call this tool to get detailed information about a specific task in a project. Useful for tracking and managing work assignments."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_project_task(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    task_uuid: Annotated[str | None, "A UUID string identifying the task to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project being accessed. Use /api/projects/ to find project IDs.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_update'."]:
    """Update task details within a project.

    Use this tool to update the details of a specific task within a project. It's useful for modifying task attributes to reflect changes in work requirements or progress.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEPROJECTTASK"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not task_uuid:
        missing_params.append(("task_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEPROJECTTASK"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEPROJECTTASK"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEPROJECTTASK"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_task_in_project(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    task_uuid: Annotated[str | None, "A UUID string that uniquely identifies the specific task to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project to access for task updates. Retrieve this using the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_partial_update'."]:
    """Update a specific task within a project.

    Use this tool to modify details of a specific task within a specified project in order to manage work assignments effectively.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATETASKINPROJECT"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not task_uuid:
        missing_params.append(("task_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATETASKINPROJECT"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATETASKINPROJECT"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATETASKINPROJECT"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_project_task(
    context: ToolContext,
    project_identifier: Annotated[str, "Project ID of the target project. Obtain this by calling /api/projects/."],  # noqa: E501
    task_uuid: Annotated[str, "A UUID string identifying the specific task to delete within a project."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_destroy'."]:
    """Delete a specific task within a project.

    Used to remove a task from a project in cases where it is no longer needed or was created in error. This tool should be called when needing to manage or clean up tasks within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def initiate_task_workflow(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Retrieve this by calling /api/projects/."],  # noqa: E501
    task_uuid: Annotated[str, "A UUID string used to uniquely identify the task to be initiated."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_run_create'."]:
    """Initiate the workflow for a specific task stage.

    Use this tool to start the workflow process for a task in its current stage within a project."""
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{id}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_task_position(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project for accessing or modifying tasks. Obtainable via a call to /api/projects/."],  # noqa: E501
    task_identifier: Annotated[str, "A UUID string specifying the task to be updated."],
    new_task_position: Annotated[int | None, "The new integer position for the task within its current stage."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_update_position_partial_update'."]:  # noqa: E501
    """Update the position of a task within its current stage.

    Use this tool to adjust the order of tasks within the same stage in a project. This is useful for reorganizing tasks based on priority or progress within a project's existing structure."""  # noqa: E501
    request_data: Any = {"position": new_task_position}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{id}/update_position/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_identifier, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_task_runs(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Obtain it via a call to /api/projects/."],  # noqa: E501
    task_identifier: Annotated[str, "The unique ID of the task for which you want to list the run executions. Ensures retrieval of all run data related to this specific task."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page. This is useful for paginating large datasets."] = None,  # noqa: E501
    starting_index_for_results: Annotated[int | None, "The starting index for returning results in a paginated list of task runs."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_runs_list'."]:
    """Retrieve a list of task run executions for a specific task.

    Use this tool to retrieve information about all executions of a specific task in a given project. Each run represents an execution instance of the task."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{task_id}/runs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, task_id=task_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": starting_index_for_results}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_task_run(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id: Annotated[str | None, "The ID of the project to access. Use /api/projects/ to retrieve project IDs.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    task_id: Annotated[str | None, "The identifier for the specific task to run within the project. Ensure it matches the correct task you intend to execute.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_runs_create'."]:
    """Create and manage execution of a specific task by ID.

    Use this tool to initiate a run for a specific task within a project on Datadog. It's useful for managing task executions when you need to automate or monitor tasks.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATETASKRUN"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id:
        missing_params.append(("project_id", "path"))
    if not task_id:
        missing_params.append(("task_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATETASKRUN"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATETASKRUN"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{task_id}/runs/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id, task_id=task_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATETASKRUN"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_task_run_details(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier for the project you want to access. Obtain it via a call to /api/projects/."],  # noqa: E501
    task_identifier: Annotated[str, "A UUID string identifying the specific task run execution."],
    task_run_id: Annotated[str, "A UUID string to identify the specific task run execution."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_runs_retrieve'."]:
    """Retrieve details of a specific task run execution.

    Use this tool to get information about a particular execution of a task within a project. This includes status, execution time, and other relevant details of the task run."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{task_id}/runs/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_run_id, project_id=project_identifier, task_id=task_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_task_run_status(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    task_run_id: Annotated[str | None, "A UUID string identifying the specific task run to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve via /api/projects/ if unknown.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    task_run_task_identifier: Annotated[str | None, "The unique task ID for identifying the specific task run to update. This ID is associated with the task execution.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_runs_partial_update'."]:
    """Update the status of a specific task run.

    Use this tool to update details of a specific task run within a project. Suitable for changing statuses or executing minor updates on task executions.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATETASKRUNSTATUS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not task_run_id:
        missing_params.append(("task_run_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))
    if not task_run_task_identifier:
        missing_params.append(("task_run_task_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATETASKRUNSTATUS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATETASKRUNSTATUS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{task_id}/runs/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_run_id, project_id=project_identifier, task_id=task_run_task_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATETASKRUNSTATUS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def append_task_run_logs(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    task_run_uuid: Annotated[str | None, "A UUID string to identify the specific task run for log appending.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "ID of the project to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    task_run_task_id: Annotated[str | None, "A string representing the task ID for the task run. This identifies which task the logs are associated with.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_runs_append_log_create'."]:
    """Append log entries to a specific task run log array.

    This tool is used to add one or more log entries to the log array of a specified task run, identified by project, task, and run IDs.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["APPENDTASKRUNLOGS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not task_run_uuid:
        missing_params.append(("task_run_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))
    if not task_run_task_id:
        missing_params.append(("task_run_task_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["APPENDTASKRUNLOGS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["APPENDTASKRUNLOGS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{task_id}/runs/{id}/append_log/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_run_uuid, project_id=project_identifier, task_id=task_run_task_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["APPENDTASKRUNLOGS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_task_run_output(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique Project ID required to access and update the specific task run details within a project. Obtainable via the /api/projects/ endpoint."],  # noqa: E501
    task_identifier: Annotated[str, "A string representing the unique identifier for a particular task run being accessed."],  # noqa: E501
    task_run_id: Annotated[str, "A UUID string that uniquely identifies the task run to update."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'tasks_runs_set_output_partial_update'."]:  # noqa: E501
    """Update the output field for a specific task run.

    Use this tool to update the output details (like PR URL, commit SHA) for a specific task run within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/tasks/{task_id}/runs/{id}/set_output/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=task_run_id, project_id=project_identifier, task_id=task_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_saved_queries_list(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Retrieve this ID by calling /api/projects/."],  # noqa: E501
    current_page_number: Annotated[int | None, "Indicates the page number for retrieving paginated results of saved warehouse queries."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A search term to filter the saved warehouse queries."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_list'."]:
    """Retrieve saved warehouse queries for a specific project.

    This tool is used to list all saved warehouse queries for a given project ID in Datadog. It should be called when needing to review or manage existing queries related to a project's data warehouse."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"page": current_page_number, "search": search_term}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_warehouse_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id_for_access: Annotated[str | None, "The ID of the project to access. Obtainable by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_create'."]:
    """Create a warehouse saved query for data management.

    Use this tool to create a new saved query for warehouse data management within a specified project. It helps in managing warehouse tables effectively.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ADDWAREHOUSESAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id_for_access:
        missing_params.append(("project_id_for_access", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ADDWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ADDWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ADDWAREHOUSESAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_warehouse_saved_query(
    context: ToolContext,
    project_id: Annotated[str, "Project ID to access the specific project. Retrieve it via /api/projects/."],  # noqa: E501
    query_uuid: Annotated[str, "A UUID string identifying the specific data warehouse saved query to retrieve."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_retrieve'."]:  # noqa: E501
    """Retrieve details of a specific warehouse saved query.

    Use this tool to get information about a particular saved query in a warehouse by specifying the project and query IDs."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def edit_warehouse_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_id: Annotated[str | None, "A UUID string identifying the specific data warehouse saved query to update.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique ID of the project to access. Retrieve this ID via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_update'."]:
    """Update a specific warehouse saved query.

    Use this tool to update a saved query in a warehouse. It is applicable when changes need to be made to existing warehouse queries.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EDITWAREHOUSESAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_id:
        missing_params.append(("saved_query_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EDITWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EDITWAREHOUSESAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EDITWAREHOUSESAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_warehouse_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    query_identifier: Annotated[str | None, "A UUID string that identifies the specific warehouse saved query to be partially updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID for the warehouse saved query. Obtain it via /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_partial_update'."]:  # noqa: E501
    """Partially update a warehouse saved query in a project.

    Use this tool to apply partial updates to an existing warehouse saved query within the specified project. It is suitable for modifying specific attributes of a saved query without altering the entire dataset.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSEQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not query_identifier:
        missing_params.append(("query_identifier", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSEQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSEQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_identifier, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYWAREHOUSEQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_warehouse_saved_query(
    context: ToolContext,
    project_id_to_access: Annotated[str, "Provide the Project ID for the warehouse project. Obtain the ID by calling /api/projects/."],  # noqa: E501
    saved_query_uuid: Annotated[str, "A UUID string that uniquely identifies the data warehouse saved query to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_destroy'."]:
    """Deletes a specified warehouse saved query.

    Use this tool to delete a specific saved query in a warehouse project. It should be called when you need to permanently remove a saved query by providing its ID and the project ID."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_id_to_access),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_saved_query_activity(
    context: ToolContext,
    project_identifier: Annotated[str, "The identifier for the project you want to access. Retrieve it via /api/projects/."],  # noqa: E501
    saved_query_id: Annotated[str, "The UUID of the data warehouse saved query to retrieve activity details for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_activity_retrieve'."]:  # noqa: E501
    """Retrieve activity details of a saved warehouse query.

    Use this tool to retrieve details about the activity related to a saved query in the warehouse. It's helpful for monitoring and managing query activities within a project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/activity/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_ancestors_of_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    data_warehouse_query_uuid: Annotated[str | None, "A UUID identifying the specific data warehouse saved query to retrieve ancestors for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "Project ID to access. Retrieve the ID using the /api/projects/ endpoint if needed.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_ancestors_create'."]:  # noqa: E501
    """Retrieve ancestors of a saved query in Datadog.

    Fetches the ancestors of the specified saved query. By default, it returns the immediate parents. The 'level' parameter can be used to look further back in the ancestor tree.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GETANCESTORSOFSAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not data_warehouse_query_uuid:
        missing_params.append(("data_warehouse_query_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GETANCESTORSOFSAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GETANCESTORSOFSAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/ancestors/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=data_warehouse_query_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GETANCESTORSOFSAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_running_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "A UUID string that identifies the saved data warehouse query to cancel.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID to access the specific project. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_cancel_create'."]:  # noqa: E501
    """Cancel a running saved query workflow in progress.

    Use this tool to cancel an ongoing saved query execution within a project. Useful when you need to stop a query that is currently running to avoid unnecessary resource usage.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CANCELRUNNINGSAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CANCELRUNNINGSAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CANCELRUNNINGSAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/cancel/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CANCELRUNNINGSAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_query_descendants(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    query_id: Annotated[str | None, "A UUID string identifying the data warehouse saved query to retrieve descendants for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project to access. Retrieve it by calling the /api/projects/ endpoint.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_descendants_create'."]:  # noqa: E501
    """Retrieve descendants of a saved query.

    Call this tool to get the descendants of a specified saved query within a project. By default, it returns the immediate children, but the `level` parameter can be used to explore further descendants. If the `level` is too high, an empty list is returned.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GETQUERYDESCENDANTS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not query_id:
        missing_params.append(("query_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GETQUERYDESCENDANTS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GETQUERYDESCENDANTS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/descendants/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GETQUERYDESCENDANTS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def undo_materialization(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    saved_query_uuid: Annotated[str | None, "A UUID string identifying the specific data warehouse saved query to be reverted.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Provide the Project ID for accessing the specific project. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_revert_materialization_create'."]:  # noqa: E501
    """Revert back to the original view by undoing materialization.

    Use this tool to revert a materialized table back to its original view. This action deletes the materialized table and its schedule, effectively undoing the materialization.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not saved_query_uuid:
        missing_params.append(("saved_query_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/revert_materialization/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=saved_query_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UNDOMATERIALIZATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def execute_saved_query(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    query_uuid: Annotated[str | None, "The UUID string identifying the specific data warehouse saved query to execute.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The ID of the project you want to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_saved_queries_run_create'."]:  # noqa: E501
    """Executes a saved query in Datadog's warehouse.

    Use this tool to execute a pre-saved query in Datadog's warehouse. It should be called when you need to retrieve the results of a specific query by its ID.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EXECUTESAVEDQUERY"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not query_uuid:
        missing_params.append(("query_uuid", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EXECUTESAVEDQUERY"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EXECUTESAVEDQUERY"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_saved_queries/{id}/run/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=query_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EXECUTESAVEDQUERY"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def warehouse_tables_overview(
    context: ToolContext,
    project_identifier: Annotated[str, "The unique identifier of the project whose warehouse tables you wish to access. Use the project ID obtained via a call to /api/projects/."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page when listing warehouse tables."] = None,  # noqa: E501
    results_start_index: Annotated[int | None, "The initial index from which the results should start. Useful for pagination."] = None,  # noqa: E501
    search_term: Annotated[str | None, "A term to filter the list of warehouse tables by matching names or descriptions."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_list'."]:
    """Retrieve a list of warehouse tables for a specific project.

    This tool allows you to retrieve the list of warehouse tables associated with a specified project ID. It should be called when you need to view or manage the tables within a data project's warehouse."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": results_start_index, "search": search_term}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def add_warehouse_table(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_identifier: Annotated[str | None, "The ID of the project to access. Retrieve it by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_create'."]:
    """Create a new warehouse table in a specified project.

    Use this tool to create a new warehouse table within a specified project using its project ID. Useful for initializing data structures in a warehouse environment.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["ADDWAREHOUSETABLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["ADDWAREHOUSETABLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["ADDWAREHOUSETABLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["ADDWAREHOUSETABLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_warehouse_table(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to retrieve the warehouse table from. Obtainable by calling /api/projects/."],  # noqa: E501
    warehouse_table_id: Annotated[str, "A UUID string identifying the data warehouse table to be retrieved."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_retrieve'."]:
    """Retrieve details of a specific warehouse table.

    Use this tool to get information about a particular warehouse table within a specified project in Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def edit_warehouse_table(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_id: Annotated[str | None, "A UUID string identifying the data warehouse table to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "The ID of the project you want to access. Obtainable via a call to /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_update'."]:
    """Updates information for a specific warehouse table.

    Use this tool to update details of a specific warehouse table within a project. Suitable for modifying table configurations or data schema.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["EDITWAREHOUSETABLE"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_id:
        missing_params.append(("warehouse_table_id", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["EDITWAREHOUSETABLE"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["EDITWAREHOUSETABLE"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["EDITWAREHOUSETABLE"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_warehouse_table2(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_id: Annotated[str | None, "A UUID string identifying the data warehouse table to be updated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "Project ID of the project you're trying to access. Use the `/api/projects/` endpoint to find the correct ID.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_partial_update'."]:
    """Partially update a warehouse table entry.

    Use this tool to partially update a specified warehouse table within a project. It should be called when there's a need to modify existing warehouse table data for a specific project.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE2"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_id:
        missing_params.append(("warehouse_table_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE2"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE2"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEWAREHOUSETABLE2"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def remove_warehouse_table(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project to access. Use /api/projects/ to find this ID."],  # noqa: E501
    warehouse_table_uuid: Annotated[str, "A UUID string identifying the data warehouse table to be deleted."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_destroy'."]:
    """Delete a specified warehouse table from a project.

    Use this tool to remove a warehouse table from a specific project by providing the project and table identifiers."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_uuid, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_table_schema(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    warehouse_table_uuid: Annotated[str | None, "A UUID string identifying the warehouse table to refresh the schema for.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_id: Annotated[str | None, "String representing the Project ID for accessing a specific project. Retrieve this by calling /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_refresh_schema_create'."]:  # noqa: E501
    """Refresh the schema of a specific warehouse table.

    Use this tool to initiate a refresh of the schema for a specified warehouse table within a project. This is useful when you need to ensure the table schema is up to date with any changes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATETABLESCHEMA"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not warehouse_table_uuid:
        missing_params.append(("warehouse_table_uuid", "path"))
    if not project_id:
        missing_params.append(("project_id", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATETABLESCHEMA"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATETABLESCHEMA"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/{id}/refresh_schema/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=warehouse_table_uuid, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATETABLESCHEMA"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def modify_table_schema(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    table_id: Annotated[str | None, "A UUID string to identify the data warehouse table for schema modification.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    project_identifier: Annotated[str | None, "The unique Project ID for accessing the desired project. To obtain this ID, call /api/projects/.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_update_schema_create'."]:  # noqa: E501
    """Update the schema of a warehouse table.

    Use this tool to modify the schema of an existing warehouse table in a specified project. Ideal for managing table structure changes such as adding or removing columns.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["MODIFYTABLESCHEMA"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not table_id:
        missing_params.append(("table_id", "path"))
    if not project_identifier:
        missing_params.append(("project_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["MODIFYTABLESCHEMA"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["MODIFYTABLESCHEMA"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/{id}/update_schema/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=table_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["MODIFYTABLESCHEMA"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def warehouse_table_file_operations(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    project_id_for_access: Annotated[str | None, "Specify the Project ID to access the desired project. Use /api/projects/ to find available IDs.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'warehouse_tables_file_create'."]:
    """Create a new warehouse table from a file.

    Use this tool to create a new warehouse table in a specified project by providing a file. It supports creating tables within the DataDog platform.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["WAREHOUSETABLEFILEOPERATIONS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not project_id_for_access:
        missing_params.append(("project_id_for_access", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["WAREHOUSETABLEFILEOPERATIONS"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["WAREHOUSETABLEFILEOPERATIONS"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/projects/{project_id}/warehouse_tables/file/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["WAREHOUSETABLEFILEOPERATIONS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def fetch_web_analytics_breakdown(
    context: ToolContext,
    breakdown_property: Annotated[str, "Specify the property to break down web analytics by, such as Browser, DeviceType, Country, etc."],  # noqa: E501
    end_date: Annotated[str, "The end date for retrieving web analytics data, formatted as YYYY-MM-DD."],  # noqa: E501
    project_id_for_access: Annotated[str, "Project ID to access specific analytics data. Obtainable via a call to /api/projects/."],  # noqa: E501
    start_date: Annotated[str, "Start date for the query in the format YYYY-MM-DD."],
    apply_url_path_cleaning: Annotated[bool | None, "Set to true to apply URL path cleaning."] = True,  # noqa: E501
    filter_by_host: Annotated[str | None, "Specify the domain to filter the results by, such as 'example.com'."] = None,  # noqa: E501
    filter_test_accounts: Annotated[bool | None, "Set to true to filter out test accounts from the results."] = True,  # noqa: E501
    results_limit: Annotated[int | None, "Specify the maximum number of results to return from the query."] = 100,  # noqa: E501
    results_offset: Annotated[int | None, "Number of results to skip for paginated data retrieval."] = 0,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_analytics_breakdown_retrieve'."]:  # noqa: E501
    """Retrieve breakdown of web analytics by property.

    Use this tool to obtain a detailed breakdown of web analytics data by various properties such as browser, device type, or country. Ideal for analyzing how different segments interact with your web project."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_analytics/breakdown/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"apply_path_cleaning": apply_url_path_cleaning, "breakdown_by": breakdown_property, "date_from": start_date, "date_to": end_date, "filter_test_accounts": filter_test_accounts, "host": filter_by_host, "limit": results_limit, "offset": results_offset}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def get_web_analytics_overview(
    context: ToolContext,
    end_date_query: Annotated[str, "End date for the query in the format YYYY-MM-DD."],
    project_id: Annotated[str, "The unique identifier for the project you want to access web analytics data for. Obtain this by calling /api/projects/."],  # noqa: E501
    start_date: Annotated[str, "Start date for the query in YYYY-MM-DD format. Determines the beginning of the analytics data range."],  # noqa: E501
    filter_test_accounts: Annotated[bool | None, "Set to true to filter out test accounts from the analytics data."] = True,  # noqa: E501
    host_filter: Annotated[str | None, "Specify the host to filter web analytics data by (e.g., example.com)."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_analytics_overview_retrieve'."]:
    """Retrieve an overview of web analytics data for a project.

    This tool provides insights into web analytics, such as the number of visitors, views, sessions, bounce rate, and session duration for a specified project. It should be called when there's a need to analyze or monitor web traffic and user behavior."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_analytics/overview/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"date_from": start_date, "date_to": end_date_query, "filter_test_accounts": filter_test_accounts, "host": host_filter}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_web_experiments(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project to access web experiments. Retrieve this ID via the /api/projects/ endpoint."],  # noqa: E501
    results_per_page: Annotated[int | None, "Specifies the number of results to return per page when retrieving web experiments."] = None,  # noqa: E501
    start_index_for_results: Annotated[int | None, "The initial index from which to return the experiment results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_experiments_list'."]:
    """Retrieve a list of web experiments for a given project.

    Use this tool to obtain a list of web experiments associated with a specific project. It should be called when there's a need to access or manage web experiments data for project tracking or analytics."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_experiments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({"limit": results_per_page, "offset": start_index_for_results}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_web_experiment(
    context: ToolContext,
    experiment_id: Annotated[int, "Unique integer ID for the web experiment. Required for identifying the experiment within the project."],  # noqa: E501
    experiment_name: Annotated[str, "The name for the web experiment you want to create in Datadog."],  # noqa: E501
    feature_flag_key: Annotated[str, "Unique identifier for the feature flag associated with the web experiment."],  # noqa: E501
    project_id: Annotated[str, "ID of the project for the web experiment. Obtain it via /api/projects/."],  # noqa: E501
    web_experiment_variants: Annotated[str, "JSON string defining the variants for the web experiment, including transforms, conditions, and rollout percentages."],  # noqa: E501
    experiment_creation_date: Annotated[str | None, "The timestamp when the web experiment was created, in ISO 8601 format."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_experiments_create'."]:
    """Create a web experiment for a project.

    Use this tool to create a new web experiment within a specified project on Datadog. Each invocation logs the creation of a new experiment."""  # noqa: E501
    request_data: Any = {"id": experiment_id, "name": experiment_name, "created_at": experiment_creation_date, "feature_flag_key": feature_flag_key, "variants": web_experiment_variants}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_experiments/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), project_id=project_id),  # noqa: E501  # noqa: UP032
        method="POST",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_web_experiment(
    context: ToolContext,
    project_id: Annotated[str, "The ID of the project you want to access. Call /api/projects/ to retrieve the ID."],  # noqa: E501
    web_experiment_id: Annotated[int, "A unique integer identifying the web experiment to retrieve details for."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_experiments_retrieve'."]:
    """Retrieve details of a specific web experiment.

    This tool is used to retrieve detailed information about a specific web experiment from a project. It should be called when you need to access data related to a web experiment identified by its ID within a project. Each call will log a new view of the experiment."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=web_experiment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_web_experiment(
    context: ToolContext,
    experiment_id: Annotated[int, "The ID of the web experiment to update. Must be an integer."],
    experiment_name: Annotated[str, "Specify the name of the web experiment to update. This is used to identify the experiment for modification within the project."],  # noqa: E501
    feature_flag_key: Annotated[str, "Unique identifier for the feature flag associated with the web experiment."],  # noqa: E501
    project_id: Annotated[str, "The ID of the project to access. Retrieve this ID via the `/api/projects/` endpoint."],  # noqa: E501
    web_experiment_id: Annotated[int, "A unique integer identifying this web experiment to be updated."],  # noqa: E501
    web_experiment_variants: Annotated[str, "JSON string specifying variants for the web experiment. Include control, transforms, conditions, and rollout_percentage."],  # noqa: E501
    creation_timestamp: Annotated[str | None, "Timestamp indicating when the web experiment was created. It should be in ISO 8601 format."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_experiments_update'."]:
    """Update web experiment details within a project.

    Use this tool to update specific details of a web experiment in a given project on Datadog. It tracks changes and logs views for the resource."""  # noqa: E501
    request_data: Any = {"id": experiment_id, "name": experiment_name, "created_at": creation_timestamp, "feature_flag_key": feature_flag_key, "variants": web_experiment_variants}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_id, project_id=project_id),  # noqa: E501  # noqa: UP032
        method="PUT",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_web_experiment_status(
    context: ToolContext,
    project_id_for_access: Annotated[str, "Project ID to access the specific project. Obtain it via /api/projects/."],  # noqa: E501
    creation_timestamp: Annotated[str | None, "The timestamp when the web experiment was created. Must be in ISO 8601 format (e.g., '2023-10-05T14:48:00.000Z')."] = None,  # noqa: E501
    experiment_identifier: Annotated[int | None, "The unique identifier for the web experiment that needs to be updated."] = None,  # noqa: E501
    experiment_name: Annotated[str | None, "The name of the web experiment to be updated. This should be a descriptive string identifying the specific experiment within the project."] = None,  # noqa: E501
    feature_flag_key: Annotated[str | None, "A string representing the feature flag key associated with the web experiment. It uniquely identifies the feature toggle you want to update."] = None,  # noqa: E501
    web_experiment_id: Annotated[int | None, "A unique integer identifying the web experiment."] = None,  # noqa: E501
    web_experiment_variants: Annotated[str | None, "JSON string defining the variants for the web experiment. Include text, HTML, selector, conditions, and rollout percentage for each variant. Example: { \"control\": { \"transforms\": [ { \"text\": \"Here comes Superman!\", \"html\": \"\", \"selector\": \"#page > #body > .header h1\" } ], \"conditions\": \"None\", \"rollout_percentage\": 50 } }"] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_experiments_partial_update'."]:
    """Update the status of a web experiment.

    Use this tool to update the status or data of an existing web experiment within a specific project by providing the relevant identifiers."""  # noqa: E501
    request_data: Any = {"id": experiment_identifier, "name": experiment_name, "created_at": creation_timestamp, "feature_flag_key": feature_flag_key, "variants": web_experiment_variants}  # noqa: E501
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=experiment_identifier, project_id=project_id_for_access),  # noqa: E501  # noqa: UP032
        method="PATCH",
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_web_experiment(
    context: ToolContext,
    project_identifier: Annotated[str, "The ID of the project from which you want to delete the web experiment. Obtainable via the /api/projects/ call."],  # noqa: E501
    web_experiment_id: Annotated[int, "Unique integer identifying the web experiment to delete."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'web_experiments_destroy'."]:
    """Delete a web experiment from a specific project.

    Use this tool to remove a web experiment by specifying the project and experiment IDs. It allows for the permanent deletion of the experiment from the system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/projects/{project_id}/web_experiments/{id}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), id=web_experiment_id, project_id=project_identifier),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def list_users(
    context: ToolContext,
    filter_staff_only: Annotated[bool | None, "Set to true to list only staff members; set to false to include all users."] = None,  # noqa: E501
    results_per_page: Annotated[int | None, "Specify the number of results to return per page when listing users."] = None,  # noqa: E501
    start_index: Annotated[int | None, "The index to start retrieving results from. Useful for pagination of user results."] = None,  # noqa: E501
    user_email: Annotated[str | None, "Filter users by email. Use a full or partial email address to narrow results."] = None,  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_list'."]:
    """Retrieve a list of users from Datadog.

    This tool fetches and returns a list of users associated with the Datadog account. It should be called when you need to access user information from Datadog."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL")),  # noqa: UP032
        method="GET",
        params=remove_none_values({"email": user_email, "is_staff": filter_staff_only, "limit": results_per_page, "offset": start_index}),  # noqa: E501
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_user_information(
    context: ToolContext,
    user_unique_identifier: Annotated[str, "The unique identifier for a specific user in Datadog. This should be a string value."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_retrieve'."]:
    """Retrieve detailed information about a specific user.

    Use this tool to get detailed information about a specific user in Datadog by providing their unique identifier."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/{uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_unique_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_user_details(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_uuid: Annotated[str | None, "The unique identifier (UUID) of the user to be updated. Required for identifying the specific user record.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_update'."]:
    """Update user details in the database.

    Use this tool to update user information based on their unique identifier (UUID).

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEUSERDETAILS"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEUSERDETAILS"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEUSERDETAILS"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="PUT",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEUSERDETAILS"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_user_info(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_uuid: Annotated[str | None, "The unique identifier for the user to be updated. This is required to specify which user's information should be modified.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_partial_update'."]:
    """Partially update a user's information in Datadog.

    Use this tool to update specific fields of a user's information in Datadog. Ideal for modifying user details without needing to provide all account details again.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEUSERINFO"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEUSERINFO"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEUSERINFO"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEUSERINFO"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def delete_user_account(
    context: ToolContext,
    user_uuid: Annotated[str, "The UUID of the user account to be deleted."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_destroy'."]:
    """Deletes a user account from the system.

    This tool deletes a user account identified by a UUID. It should be called when there is a need to permanently remove a user profile from the system."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/{uuid}/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="DELETE",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_user_hedgehog_config(
    context: ToolContext,
    user_uuid: Annotated[str, "The unique UUID of the user whose hedgehog configuration details are to be retrieved."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_hedgehog_config_retrieve'."]:
    """Retrieve a user's hedgehog configuration details.

    This tool fetches the hedgehog configuration for a specific user using their UUID. It should be called when you need to access the user's hedgehog settings."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/{uuid}/hedgehog_config/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def update_user_hedgehog_config(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_uuid: Annotated[str | None, "A unique identifier for the user whose hedgehog configuration is to be updated. It is a string value that must be provided to target the correct user.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_hedgehog_config_partial_update'."]:  # noqa: E501
    """Update a user's hedgehog configuration settings in Datadog.

    Call this tool to update specific settings in a user's hedgehog configuration. Useful for modifying user preferences or settings related to the hedgehog feature in Datadog.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["UPDATEUSERHEDGEHOGCONFIG"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["UPDATEUSERHEDGEHOGCONFIG"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["UPDATEUSERHEDGEHOGCONFIG"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/hedgehog_config/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["UPDATEUSERHEDGEHOGCONFIG"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def create_user_scene_personalization(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_uuid: Annotated[str | None, "The unique identifier for the user whose scene you want to personalize.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_scene_personalisation_create'."]:  # noqa: E501
    """Create personalized scene settings for a user.

    This tool is used to create personalized scene settings for a user identified by their UUID. It should be called when there's a need to customize a user's interface or experience by setting specific scene preferences.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CREATEUSERSCENEPERSONALIZATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CREATEUSERSCENEPERSONALIZATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CREATEUSERSCENEPERSONALIZATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/scene_personalisation/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CREATEUSERSCENEPERSONALIZATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def initiate_user2fa_setup(
    context: ToolContext,
    user_uuid: Annotated[str, "A unique identifier for the user to initiate 2FA setup."],
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_start_2fa_setup_retrieve'."]:
    """Initiate two-factor authentication setup for a user.

    Call this tool to start the two-factor authentication setup process for a specified user. It is used when you need to initialize 2FA for enhanced security."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/{uuid}/start_2fa_setup/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def generate_backup_codes(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_uuid: Annotated[str | None, "A unique identifier for the user to generate new backup codes.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_two_factor_backup_codes_create'."]:  # noqa: E501
    """Generate new backup codes for two-factor authentication.

    Use this tool to create new backup codes for a user's two-factor authentication, which will invalidate any existing backup codes.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["GENERATEBACKUPCODES"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["GENERATEBACKUPCODES"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["GENERATEBACKUPCODES"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/two_factor_backup_codes/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["GENERATEBACKUPCODES"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def disable_user2fa(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_unique_identifier: Annotated[str | None, "The unique identifier of the user whose 2FA is to be disabled.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_two_factor_disable_create'."]:
    """Disable two-factor authentication for a user.

    This tool disables two-factor authentication (2FA) for a user and removes all associated devices. Use this when a user needs to deactivate their 2FA settings.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["DISABLEUSER2FA"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_unique_identifier:
        missing_params.append(("user_unique_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["DISABLEUSER2FA"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["DISABLEUSER2FA"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/two_factor_disable/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_unique_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["DISABLEUSER2FA"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve_user2fa_setup_status(
    context: ToolContext,
    user_identifier: Annotated[str, "A unique identifier for the user whose two-factor authentication setup status is being retrieved. This is typically a UUID string."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_two_factor_start_setup_retrieve'."]:  # noqa: E501
    """Retrieve a user's two-factor authentication setup status.

    This tool retrieves the current status of a user's two-factor authentication setup. It should be called when you need to check if a user has initiated the setup of two-factor authentication."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/{uuid}/two_factor_start_setup/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_identifier),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def retrieve2fa_status(
    context: ToolContext,
    user_identifier_uuid: Annotated[str, "A unique identifier for the user to retrieve the 2FA status. Typically a string of alphanumeric characters."],  # noqa: E501
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_two_factor_status_retrieve'."]:  # noqa: E501
    """Retrieve current 2FA status and backup codes if enabled.

    Use this tool to get the current two-factor authentication (2FA) status for a user, including backup codes if they are enabled. This is useful for verifying 2FA settings and ensuring backup options are available."""  # noqa: E501
    request_data: Any = {}
    if isinstance(request_data, dict):
        request_data = remove_none_values(request_data)
    content = json.dumps(request_data) if request_data else None
    response = await make_request(
        url="{posthog_server_url}/api/users/{uuid}/two_factor_status/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_identifier_uuid),  # noqa: E501  # noqa: UP032
        method="GET",
        params=remove_none_values({}),
        headers=remove_none_values({"Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
        content=content,
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def validate_two_factor_authentication(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_identifier: Annotated[str | None, "The unique identifier for the user whose two-factor authentication is being validated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_two_factor_validate_create'."]:  # noqa: E501
    """Validate a user's two-factor authentication code.

    Use this tool to verify a user's two-factor authentication by providing the necessary code. It confirms whether the two-factor authentication is valid.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["VALIDATETWOFACTORAUTHENTICATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_identifier:
        missing_params.append(("user_identifier", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["VALIDATETWOFACTORAUTHENTICATION"] + "\n```"  # noqa: E501
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["VALIDATETWOFACTORAUTHENTICATION"] + "\n```"  # noqa: E501
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/two_factor_validate/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_identifier),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["VALIDATETWOFACTORAUTHENTICATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def validate_user2fa(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    user_uuid: Annotated[str | None, "The unique identifier for the user whose 2FA status needs to be validated.  Required when mode is 'execute', ignored when mode is 'get_request_schema'."] = None,  # noqa: E501

    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_validate_2fa_create'."]:
    """Validate a user's two-factor authentication status.

    Use this tool to validate whether a specific user's two-factor authentication (2FA) is correctly set up. Call this when you need to confirm a user's 2FA status in the system.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.\n\nThis operation also requires path parameters.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.\n      Note: You must also provide the required path parameters when executing.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["VALIDATEUSER2FA"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter along with the required path parameters. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters
    # Validate required parameters
    missing_params = []
    if not user_uuid:
        missing_params.append(("user_uuid", "path"))

    if missing_params:
        param_names = [p[0] for p in missing_params]
        param_details = ", ".join(
            [f"{p[0]} ({p[1]})" for p in missing_params]
        )
        raise RetryableToolError(
            message=f"Missing required parameters: {param_names}",
            developer_message=(
                f"Required parameters validation failed: {param_details}"
            ),
            additional_prompt_content=(
                f"The following required parameters are missing: "
                f"{param_details}. Please call this tool again with all "
                "required parameters."
            ),
        )


    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["VALIDATEUSER2FA"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["VALIDATEUSER2FA"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/{uuid}/validate_2fa/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL"), uuid=user_uuid),  # noqa: E501  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["VALIDATEUSER2FA"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def cancel_email_change_request(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_cancel_email_change_request_partial_update'."]:  # noqa: E501
    """Cancel a pending email change request.

    Use this tool to cancel a pending email change request for a user in the system. It ensures that the email update process is stopped.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["CANCELEMAILCHANGEREQUEST"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters

    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["CANCELEMAILCHANGEREQUEST"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["CANCELEMAILCHANGEREQUEST"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/cancel_email_change_request/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL")),  # noqa: UP032
        method="PATCH",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["CANCELEMAILCHANGEREQUEST"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def request_email_verification(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_request_email_verification_create'."]:  # noqa: E501
    """Request an email verification for a user.



    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["REQUESTEMAILVERIFICATION"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters

    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["REQUESTEMAILVERIFICATION"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["REQUESTEMAILVERIFICATION"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/request_email_verification/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL")),  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["REQUESTEMAILVERIFICATION"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}


@tool(requires_secrets=["POSTHOG_SERVER_URL", "POSTHOG_PERSONAL_API_KEY"])
async def verify_user_email(
    context: ToolContext,
    mode: Annotated[
        ToolMode,
        "Operation mode: 'get_request_schema' returns the OpenAPI spec "
        "for the request body, 'execute' performs the actual operation",
    ],
    request_body: Annotated[
        str | None,
        "Stringified JSON representing the request body. Required when "
        "mode is 'execute', ignored when mode is 'get_request_schema'",
    ] = None,
) -> Annotated[dict[str, Any], "Response from the API endpoint 'users_verify_email_create'."]:
    """Initiates the email verification process for a user.

    Use this tool to start the process of verifying a user's email address. Ideal for confirming email ownership during account setup or security checks.

    Note: Understanding the request schema is necessary to properly create
    the stringified JSON input object for execution.

    Modes:
    - GET_REQUEST_SCHEMA: Returns the schema. Only call if you don't
      already have it. Do NOT call repeatedly if you already received
      the schema.
    - EXECUTE: Performs the operation with the provided request body
      JSON.

    If you need the schema, call with mode='get_request_schema' ONCE, then execute.
    """  # noqa: E501
    if mode == ToolMode.GET_REQUEST_SCHEMA:
        return {
            "request_body_schema": REQUEST_BODY_SCHEMAS["VERIFYUSEREMAIL"],
            "instructions": (
                "Use the request_body_schema to construct a valid JSON object. "
                "Once you have populated the object following the schema "
                "structure and requirements, call this tool again with "
                "mode='execute' and the stringified JSON as the "
                "request_body parameter. "
                "Do NOT call the schema mode again - you already have "
                "the schema now."
            ),
        }

    # Mode is EXECUTE - validate parameters

    # Validate request body is provided (not None or empty string)
    # Note: Empty objects like {} are allowed - schema validation will check if valid
    if request_body is None or request_body.strip() == "":
        raise RetryableToolError(
            message="Request body is required when mode is 'execute'",
            developer_message="The request_body parameter was null or empty string",
            additional_prompt_content=(
                "The request body is required to perform this operation. "
                "Use the schema below to construct a valid JSON object, "
                "then call this tool again in execute mode with the "
                "stringified JSON as the request_body parameter.\n\n"
                "Schema:\n\n```json\n" + REQUEST_BODY_SCHEMAS["VERIFYUSEREMAIL"] + "\n```"
            ),
        )

    # Parse JSON
    try:
        request_data = json.loads(request_body)
    except json.JSONDecodeError as e:
        raise RetryableToolError(
            message=f"Invalid JSON in request body: {e!s}",
            developer_message=f"JSON parsing failed: {e!s}",
            additional_prompt_content=(
                f"The request body contains invalid JSON. Error: {e!s}\n\n"
                "Please provide a valid JSON string that matches the schema "
                "below, then call this tool again in execute mode.\n\n"
                "Schema:\n\n```json\n"+ REQUEST_BODY_SCHEMAS["VERIFYUSEREMAIL"] + "\n```"
            ),
        ) from e

    response = await make_request_with_schema_validation(
        url="{posthog_server_url}/api/users/verify_email/".format(posthog_server_url=context.get_secret("POSTHOG_SERVER_URL")),  # noqa: UP032
        method="POST",
        request_data=request_data,
        schema=REQUEST_BODY_SCHEMAS["VERIFYUSEREMAIL"],
        params=remove_none_values({}),
        headers=remove_none_values({"Content-Type": "application/json", "Authorization": "Bearer {authorization}".format(authorization=context.get_secret("POSTHOG_PERSONAL_API_KEY"))}),  # noqa: E501  # noqa: UP032
    )
    try:
        return {"response_json": response.json()}
    except Exception:
        return {"response_text": response.text}
