aidial_assistant/commands/base.py (53 lines of code) (raw):

from abc import ABC, abstractmethod from enum import Enum from typing import Any, Callable, List, TypedDict, TypeVar from typing_extensions import override ExecutionCallback = Callable[[str], None] class ResultType(str, Enum): TEXT = "Text" JSON = "JSon" class ResultObject: def __init__(self, result_type: ResultType, text: str): self._type = result_type self._text = text @property def type(self) -> ResultType: return self._type @property def text(self) -> str: return self._text class TextResult(ResultObject): def __init__(self, text: str): super().__init__(ResultType.TEXT, text) class JsonResult(ResultObject): def __init__(self, text: str): super().__init__(ResultType.JSON, text) class Command(ABC): @staticmethod @abstractmethod def token() -> str: pass async def execute( self, args: dict[str, Any], execution_callback: ExecutionCallback ) -> ResultObject: raise Exception(f"Command {self} isn't implemented") def __str__(self) -> str: return self.token() class FinalCommand(Command, ABC): @override async def execute( self, args: dict[str, Any], execution_callback: ExecutionCallback ) -> ResultObject: raise Exception( f"Internal error: command {self} is final and can't be executed" ) class CommandObject(TypedDict): command: str args: List[str] CommandConstructor = Callable[[], Command] T = TypeVar("T") def get_required_field(args: dict[str, T], field: str) -> T: value = args.get(field) if value is None: raise Exception(f"Parameter '{field}' is required") return value