|
# retoor <retoor@molodetz.nl>
|
|
|
|
from __future__ import annotations
|
|
|
|
from .schema import InteractionRequest, WidgetModel, flatten_widgets
|
|
|
|
|
|
def project_markdown(request: InteractionRequest, interaction_id: str) -> str:
|
|
lines: list[str] = [f"### {request.title}", ""]
|
|
if request.description:
|
|
lines.append(request.description)
|
|
lines.append("")
|
|
for widget in request.widgets:
|
|
lines.extend(_widget_lines(widget))
|
|
actions = f"[{request.submit_label}]"
|
|
if request.cancelable:
|
|
actions += f" [{request.cancel_label}]"
|
|
lines.append("")
|
|
lines.append(actions)
|
|
lines.append(f"<!-- ai-interaction:{interaction_id} -->")
|
|
return "\n".join(lines).strip() + "\n"
|
|
|
|
|
|
def project_plain_menu(request: InteractionRequest) -> str:
|
|
lines: list[str] = [request.title]
|
|
if request.description:
|
|
lines.append(request.description)
|
|
lines.append("")
|
|
widgets = [
|
|
w
|
|
for w in flatten_widgets(request.widgets)
|
|
if w.type != "//"
|
|
]
|
|
if len(widgets) == 1 and widgets[0].type == "confirm":
|
|
lines.append(f"Reply: yes | no | cancel")
|
|
return "\n".join(lines).strip() + "\n"
|
|
if len(widgets) == 1 and widgets[0].type in ("choice", "select"):
|
|
options = widgets[0].options[:12]
|
|
lines.append(f"{widgets[0].label}")
|
|
for index, option in enumerate(options, start=1):
|
|
lines.append(f"{index}. {option.label} (`{option.value}`)")
|
|
lines.append("")
|
|
lines.append(f"Reply with a number (1-{len(options)}) or `cancel`.")
|
|
return "\n".join(lines).strip() + "\n"
|
|
for widget in widgets:
|
|
if widget.type in ("choice", "choice_multi", "select"):
|
|
lines.append(f"{widget.label}:")
|
|
for index, option in enumerate(widget.options[:12], start=1):
|
|
lines.append(f" {index}. {option.label} (`{option.value}`)")
|
|
elif widget.type == "confirm":
|
|
lines.append(f"{widget.label}: yes | no")
|
|
else:
|
|
lines.append(f"{widget.label}: (free text)")
|
|
lines.append("")
|
|
lines.append("Reply with values, or `cancel`.")
|
|
return "\n".join(lines).strip() + "\n"
|
|
|
|
|
|
def _widget_lines(widget: WidgetModel, indent: str = "") -> list[str]:
|
|
if widget.type == "//":
|
|
return [f"{indent}{widget.text or widget.label}", ""]
|
|
if widget.type == "group":
|
|
lines = [f"{indent}**{widget.label}**", ""]
|
|
for child in widget.widgets:
|
|
lines.extend(_widget_lines(child, indent + " "))
|
|
return lines
|
|
req = "required" if widget.required else "optional"
|
|
lines = [f"{indent}- [ ] **{widget.name}** ({req}) — {widget.label}"]
|
|
if widget.help:
|
|
lines.append(f"{indent} _{widget.help}_")
|
|
if widget.type == "confirm":
|
|
default = widget.default
|
|
yes = "•" if default is True else " "
|
|
no = "•" if default is False else " "
|
|
lines.append(f"{indent} - ({yes}) `true` — Yes")
|
|
lines.append(f"{indent} - ({no}) `false` — No")
|
|
elif widget.type in ("choice", "select"):
|
|
default = str(widget.default) if widget.default is not None else ""
|
|
for option in widget.options:
|
|
mark = "•" if option.value == default else " "
|
|
desc = f" — {option.description}" if option.description else ""
|
|
lines.append(
|
|
f"{indent} - ({mark}) `{option.value}` — {option.label}{desc}"
|
|
)
|
|
elif widget.type == "choice_multi":
|
|
defaults = set(widget.default or []) if isinstance(widget.default, list) else set()
|
|
for option in widget.options:
|
|
mark = "x" if option.value in defaults else " "
|
|
desc = f" — {option.description}" if option.description else ""
|
|
lines.append(
|
|
f"{indent} - [{mark}] `{option.value}` — {option.label}{desc}"
|
|
)
|
|
elif widget.type == "text":
|
|
extra = f", max {widget.max_length}" if widget.max_length else ""
|
|
lines.append(f"{indent} - _free text{extra}_")
|
|
elif widget.type == "number":
|
|
parts = []
|
|
if widget.min is not None:
|
|
parts.append(f"min {widget.min}")
|
|
if widget.max is not None:
|
|
parts.append(f"max {widget.max}")
|
|
hint = (", " + ", ".join(parts)) if parts else ""
|
|
lines.append(f"{indent} - _number{hint}_")
|
|
elif widget.type == "date":
|
|
lines.append(f"{indent} - _date DD/MM/YYYY_")
|
|
return lines
|