import html as html_mod
import re
from time import time as _time
ALLOWED_TAGS = {
"p",
"br",
"b",
"strong",
"i",
"em",
"u",
"s",
"del",
"ul",
"ol",
"li",
"a",
"img",
"table",
"tr",
"td",
"th",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"hr",
"blockquote",
"code",
"pre",
"span",
}
ALLOWED_ATTRS = {
"a": {"href", "rel", "target"},
"img": {"src", "alt", "width", "height"},
"td": {"colspan", "rowspan"},
"th": {"colspan", "rowspan"},
}
FORBIDDEN_TAGS = {"script", "style", "iframe", "object", "embed", "form", "input"}
def sanitize_html(html_body: str) -> str:
for tag in FORBIDDEN_TAGS:
html_body = re.sub(
rf"<\s*{tag}[^>]*>.*?<\s*/\s*{tag}\s*>",
"",
html_body,
flags=re.DOTALL | re.IGNORECASE,
)
html_body = re.sub(
rf"<\s*{tag}[^>]*/?\s*>",
"",
html_body,
flags=re.IGNORECASE,
)
return html_body
def markdown_to_html(md_text: str) -> str:
text = html_mod.escape(md_text)
text = re.sub(r"```(\w+)?\n?(.*?)```", r"
\2
", text, flags=re.DOTALL)
text = re.sub(r"`([^`]+)`", r"\1", text)
text = re.sub(r"\*\*(.+?)\*\*", r"\1", text)
text = re.sub(r"\*(.+?)\*", r"\1", text)
text = re.sub(r"~~(.+?)~~", r"\1", text)
text = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", r'\1', text)
text = re.sub(r"^[\-\*]\s+(.+)$", r"\1", text, flags=re.MULTILINE)
text = re.sub(r"(.*?(\n?.*?)*)", r"", text)
text = re.sub(r"^\d+\.\s+(.+)$", r"\1", text, flags=re.MULTILINE)
text = re.sub(r"(.*?(\n?.*?)*)", r"\1
", text)
lines = text.split("\n")
result_lines = []
in_table = False
table_rows = []
for line in lines:
if line.strip().startswith("|") and line.strip().endswith("|"):
cells = [c.strip() for c in line.strip().strip("|").split("|")]
if all(c.startswith("-") and len(c) > 1 for c in cells):
continue
table_rows.append("" + "".join(f"| {c} | " for c in cells) + "
")
in_table = True
else:
if in_table and table_rows:
result_lines.append("" + "".join(table_rows) + "
")
table_rows = []
in_table = False
result_lines.append(line)
if in_table and table_rows:
result_lines.append("" + "".join(table_rows) + "
")
text = "\n".join(result_lines)
text = re.sub(r"^>\s+(.+)$", r"\1
", text, flags=re.MULTILINE)
text = re.sub(r"^---+$", r"
", text, flags=re.MULTILINE)
text = re.sub(r"^#{1,2}\s+(.+)$", r"\1
", text, flags=re.MULTILINE)
text = re.sub(r"^#{3,6}\s+(.+)$", r"\1
", text, flags=re.MULTILINE)
lines = text.split("\n")
result = []
for line in lines:
stripped = line.strip()
if not stripped:
result.append("
")
elif stripped.startswith("<") and not stripped.startswith("
{stripped}")
return "\n".join(result)
def message_parts_to_text(parts: list[dict]) -> str:
texts = []
for part in parts:
if "text" in part:
texts.append(part["text"].get("content", ""))
elif "image" in part:
img = part["image"]
texts.append(f"[图片: {img.get('name', img.get('url', ''))}]")
elif "file" in part:
f = part["file"]
texts.append(f"[文件: {f.get('name', f.get('url', ''))}]")
elif "card" in part:
card = part["card"]
texts.append(f"[卡片: {card.get('title', '')}]")
return "\n".join(texts)
def get_agent_prompt_rules(mode: str = "both") -> list[str]:
rules = [
"Your response will be sent to Freshdesk/Freshworks as an AI agent reply.",
]
if mode in ("freshdesk", "both"):
rules.extend(
[
"--- Freshdesk (Ticket System) Format Rules ---",
"The message body is HTML. Use for bold, for italic.",
'Use text for links.',
"Use for unordered lists.",
"Use - item
for ordered lists.",
"Use for inline code and for code blocks.",
"Use text
for quotations.",
"Use or for headings.",
"Use
for tables.",
"Do NOT use