# retoor <retoor@molodetz.nl>
from __future__ import annotations
from ..actions.spec import Action, Param
def arg(
name: str, description: str, required: bool = False, kind: str = "string"
) -> Param:
return Param(
name=name,
location="body",
description=description,
required=required,
type=kind,
)
UI = (
"Presents a channel-aware interactive prompt (CA-IWP). The host renders the best "
"affordance for the current channel (site custom elements, Telegram inline keys, or "
"plain numbered menus). Blocks until the user submits, cancels, or the timeout fires. "
"Never invent HTML or custom-element tags in your prose - call this tool instead."
)
INTERACTION_ACTIONS: tuple[Action, ...] = (
Action(
name="ui_prompt",
method="LOCAL",
path="",
summary="Ask the user an interactive question with widgets (confirm, choice, text, form)",
description=(
UI
+ " Prefer this for decisions and short forms. Returns structured "
"{interaction_id, status, values, meta}. Branch on status: submitted, cancelled, "
"timeout, superseded, or error. Keep labels short and value tokens stable."
),
handler="interaction",
requires_auth=False,
params=(
arg("title", "Short question title (≤120 chars).", required=True),
arg("description", "Optional help prose (≤500 chars)."),
arg(
"widgets",
"Ordered list of widget objects. Types: confirm, choice, choice_multi, "
"text, number, date, select, // (help), group. Each input needs name+label; "
"choice types need options[{value,label}].",
required=True,
kind="array",
),
arg("submit_label", "Primary action label (default Confirm)."),
arg("cancel_label", "Cancel action label (default Cancel)."),
arg("cancelable", "Whether the user may cancel (default true).", kind="boolean"),
arg(
"timeout_sec",
"Optional timeout in seconds (0 = none, max 86400).",
kind="integer",
),
arg("id", "Optional stable interaction id (a-z, digits, hyphens)."),
),
),
Action(
name="ui_cancel",
method="LOCAL",
path="",
summary="Cancel the open interactive prompt",
description="Closes the current open interaction (or the one named by id) with status cancelled.",
handler="interaction",
requires_auth=False,
params=(
arg("id", "Optional interaction id to cancel; defaults to the open one."),
arg("reason", "Optional cancel reason."),
),
),
Action(
name="ui_notify",
method="LOCAL",
path="",
summary="Show a non-blocking ephemeral status on channels that support it",
description=(
"Sends a short status line to the user without waiting. Only effective when the "
"channel advertises ephemeral_status (site-chat). Elsewhere it is skipped."
),
handler="interaction",
requires_auth=False,
params=(arg("text", "Status text to show (≤200 chars).", required=True),),
),
Action(
name="interactions_get",
method="LOCAL",
path="",
summary="Show whether interactive widgets (ui_prompt) are enabled for the user",
description=(
"Returns the effective interactive-widgets preference: enabled (bool), source "
"('user' override or 'default'), the admin default, and the user's override if set. "
"The site default is set by administrators on the Devii service; users may override "
"it on their profile or with interactions_set."
),
handler="interaction",
requires_auth=True,
read_only=True,
),
Action(
name="interactions_set",
method="LOCAL",
path="",
summary="Enable, disable, or reset interactive widgets for the user",
description=(
"Sets whether this account accepts interactive ui_prompt widgets. Pass enabled=true "
"or false to override the admin default; pass reset=true (or omit enabled and set "
"reset) to clear the override and inherit the admin default again. Guests cannot "
"set a preference."
),
handler="interaction",
requires_auth=True,
params=(
arg(
"enabled",
"true to enable interactive widgets, false to disable them. Omit when reset=true.",
kind="boolean",
),
arg(
"reset",
"true to clear the user override and inherit the administrator default again.",
kind="boolean",
),
),
),
)