ShiErFeng/shierfeng-fastapi-backend/cli/tui/actions/models.py
2026-07-24 09:43:10 +08:00

73 lines
2.1 KiB
Python

from collections.abc import Callable
from dataclasses import dataclass
from typing import Literal
from cli.tui.adapters.models import TUI_ADAPTER_MODEL_RENDERER, BrowserRecordSnapshot
ActionSlot = Literal['primary', 'secondary', 'global', 'utility']
ActionExecutionMode = Literal['nested_json', 'external']
ActionCommandBuilder = Callable[[BrowserRecordSnapshot | None, str], tuple[str, ...] | None]
ActionSummaryBuilder = Callable[[BrowserRecordSnapshot | None, str], list[str]]
ActionTextBuilder = Callable[[BrowserRecordSnapshot | None, str], str]
@dataclass(frozen=True)
class TuiActionSpec:
"""
TUI 低风险动作定义。
:param action_id: 动作唯一标识
:param label: 动作显示名称
:param command_args: 对应 CLI 命令参数
:param preview_title: 预览弹窗标题
:param preview_lines: 预览摘要文本
:param append_yes: 执行 nested JSON 动作时是否自动追加 `--yes`
:param refresh_view: 执行完成后是否刷新当前页面
"""
action_id: str
label: str
command_args: tuple[str, ...]
preview_title: str
preview_lines: list[str]
execution_mode: ActionExecutionMode = 'nested_json'
append_yes: bool = True
refresh_view: bool = True
@dataclass(frozen=True)
class TuiActionResult:
"""
TUI 动作执行结果。
:param spec: 动作定义
:param payload: CLI JSON 负载
"""
spec: TuiActionSpec
payload: dict[str, object] | None = None
external_exit_code: int | None = None
external_message: str | None = None
@property
def ok(self) -> bool:
"""
判断动作是否执行成功。
:return: 是否成功
"""
if self.external_exit_code is not None:
return self.external_exit_code == 0
return bool(isinstance(self.payload, dict) and self.payload.get('ok', False))
@property
def message(self) -> str:
"""
获取动作结果摘要。
:return: 结果摘要
"""
if self.external_message is not None:
return self.external_message
return TUI_ADAPTER_MODEL_RENDERER.extract_payload_message(self.payload)