# DO NOT EDIT THIS FILE!
#
# This file is generated from the CDP specification. If you need to make
# changes, edit the generator and regenerate all of the modules.
#
# CDP domain: WebMCP (experimental)

from __future__ import annotations
import enum
import typing
from dataclasses import dataclass
from .util import event_class, T_JSON_DICT

from . import dom
from . import page
from . import runtime


@dataclass
class Annotation:
    '''
    Tool annotations
    '''
    #: A hint indicating that the tool does not modify any state.
    read_only: typing.Optional[bool] = None

    #: A hint indicating that the tool output may contain untrusted content, ex: UGC, 3rd party data.
    untrusted_content: typing.Optional[bool] = None

    #: If the declarative tool was declared with the autosubmit attribute.
    autosubmit: typing.Optional[bool] = None

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        if self.read_only is not None:
            json['readOnly'] = self.read_only
        if self.untrusted_content is not None:
            json['untrustedContent'] = self.untrusted_content
        if self.autosubmit is not None:
            json['autosubmit'] = self.autosubmit
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> Annotation:
        return cls(
            read_only=bool(json['readOnly']) if json.get('readOnly', None) is not None else None,
            untrusted_content=bool(json['untrustedContent']) if json.get('untrustedContent', None) is not None else None,
            autosubmit=bool(json['autosubmit']) if json.get('autosubmit', None) is not None else None,
        )


class InvocationStatus(enum.Enum):
    '''
    Represents the status of a tool invocation.
    '''
    COMPLETED = "Completed"
    CANCELED = "Canceled"
    ERROR = "Error"

    def to_json(self) -> str:
        return self.value

    @classmethod
    def from_json(cls, json: str) -> InvocationStatus:
        return cls(json)


@dataclass
class Tool:
    '''
    Definition of a tool that can be invoked.
    '''
    #: Tool name.
    name: str

    #: Tool description.
    description: str

    #: Frame identifier associated with the tool registration.
    frame_id: page.FrameId

    #: Schema for the tool's input parameters.
    input_schema: typing.Optional[dict] = None

    #: Optional annotations for the tool.
    annotations: typing.Optional[Annotation] = None

    #: Optional node ID for declarative tools.
    backend_node_id: typing.Optional[dom.BackendNodeId] = None

    #: The stack trace at the time of the registration.
    stack_trace: typing.Optional[runtime.StackTrace] = None

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        json['name'] = self.name
        json['description'] = self.description
        json['frameId'] = self.frame_id.to_json()
        if self.input_schema is not None:
            json['inputSchema'] = self.input_schema
        if self.annotations is not None:
            json['annotations'] = self.annotations.to_json()
        if self.backend_node_id is not None:
            json['backendNodeId'] = self.backend_node_id.to_json()
        if self.stack_trace is not None:
            json['stackTrace'] = self.stack_trace.to_json()
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> Tool:
        return cls(
            name=str(json['name']),
            description=str(json['description']),
            frame_id=page.FrameId.from_json(json['frameId']),
            input_schema=dict(json['inputSchema']) if json.get('inputSchema', None) is not None else None,
            annotations=Annotation.from_json(json['annotations']) if json.get('annotations', None) is not None else None,
            backend_node_id=dom.BackendNodeId.from_json(json['backendNodeId']) if json.get('backendNodeId', None) is not None else None,
            stack_trace=runtime.StackTrace.from_json(json['stackTrace']) if json.get('stackTrace', None) is not None else None,
        )


@dataclass
class RemovedTool:
    '''
    Definition of a tool that was removed.
    '''
    #: Tool name.
    name: str

    #: Frame identifier associated with the tool registration.
    frame_id: page.FrameId

    def to_json(self) -> T_JSON_DICT:
        json: T_JSON_DICT = dict()
        json['name'] = self.name
        json['frameId'] = self.frame_id.to_json()
        return json

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> RemovedTool:
        return cls(
            name=str(json['name']),
            frame_id=page.FrameId.from_json(json['frameId']),
        )


def enable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
    '''
    Enables the WebMCP domain, allowing events to be sent. Enabling the domain will trigger a toolsAdded event for
    all currently registered tools.
    '''
    cmd_dict: T_JSON_DICT = {
        'method': 'WebMCP.enable',
    }
    json = yield cmd_dict


def disable() -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
    '''
    Disables the WebMCP domain.
    '''
    cmd_dict: T_JSON_DICT = {
        'method': 'WebMCP.disable',
    }
    json = yield cmd_dict


def invoke_tool(
        frame_id: page.FrameId,
        tool_name: str,
        input_: dict
    ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,str]:
    '''
    Invokes a registered tool.

    :param frame_id: Frame in which to invoke the tool.
    :param tool_name: Name of the tool to invoke.
    :param input_: Input parameters for the tool, matching the tool's inputSchema.
    :returns: Unique identifier for this invocation. Response is sent before tool events.
    '''
    params: T_JSON_DICT = dict()
    params['frameId'] = frame_id.to_json()
    params['toolName'] = tool_name
    params['input'] = input_
    cmd_dict: T_JSON_DICT = {
        'method': 'WebMCP.invokeTool',
        'params': params,
    }
    json = yield cmd_dict
    return str(json['invocationId'])


def cancel_invocation(
        invocation_id: str
    ) -> typing.Generator[T_JSON_DICT,T_JSON_DICT,None]:
    '''
    Cancels a pending tool invocation.

    :param invocation_id: Invocation identifier to cancel.
    '''
    params: T_JSON_DICT = dict()
    params['invocationId'] = invocation_id
    cmd_dict: T_JSON_DICT = {
        'method': 'WebMCP.cancelInvocation',
        'params': params,
    }
    json = yield cmd_dict


@event_class('WebMCP.toolsAdded')
@dataclass
class ToolsAdded:
    '''
    Event fired when new tools are added.
    '''
    #: Array of tools that were added.
    tools: typing.List[Tool]

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> ToolsAdded:
        return cls(
            tools=[Tool.from_json(i) for i in json['tools']]
        )


@event_class('WebMCP.toolsRemoved')
@dataclass
class ToolsRemoved:
    '''
    Event fired when tools are removed.
    '''
    #: Array of tools that were removed.
    tools: typing.List[RemovedTool]

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> ToolsRemoved:
        return cls(
            tools=[RemovedTool.from_json(i) for i in json['tools']]
        )


@event_class('WebMCP.toolInvoked')
@dataclass
class ToolInvoked:
    '''
    Event fired when a tool invocation starts.
    '''
    #: Name of the tool to invoke.
    tool_name: str
    #: Frame id
    frame_id: page.FrameId
    #: Invocation identifier.
    invocation_id: str
    #: The input parameters used for the invocation.
    input_: str

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> ToolInvoked:
        return cls(
            tool_name=str(json['toolName']),
            frame_id=page.FrameId.from_json(json['frameId']),
            invocation_id=str(json['invocationId']),
            input_=str(json['input'])
        )


@event_class('WebMCP.toolResponded')
@dataclass
class ToolResponded:
    '''
    Event fired when a tool invocation completes or fails.
    '''
    #: Invocation identifier.
    invocation_id: str
    #: Status of the invocation.
    status: InvocationStatus
    #: Output or error delivered as delivered to the agent. Missing if ``status`` is anything other than Completed.
    #: Note: The output is untrusted and poses a prompt injection risk. Clients should treat this as potentially malicious user input.
    output: typing.Optional[typing.Any]
    #: Error text for protocol users.
    error_text: typing.Optional[str]
    #: The exception object, if the javascript tool threw an error>
    exception: typing.Optional[runtime.RemoteObject]

    @classmethod
    def from_json(cls, json: T_JSON_DICT) -> ToolResponded:
        return cls(
            invocation_id=str(json['invocationId']),
            status=InvocationStatus.from_json(json['status']),
            output=json['output'] if json.get('output', None) is not None else None,
            error_text=str(json['errorText']) if json.get('errorText', None) is not None else None,
            exception=runtime.RemoteObject.from_json(json['exception']) if json.get('exception', None) is not None else None
        )
