ForcePilot/backend/package/yuxi/channel/extensions/intercom/format.py

107 lines
3.2 KiB
Python
Raw Normal View History

import html
import re
from html.parser import HTMLParser
class HTMLToTextParser(HTMLParser):
def __init__(self):
super().__init__()
self._parts: list[str] = []
self._skip_depth = 0
self._current_href: str | None = None
def handle_starttag(self, tag, attrs):
if tag in ("script", "style", "head", "meta", "link"):
self._skip_depth += 1
if tag == "a":
for name, value in attrs:
if name == "href":
self._current_href = value
break
def handle_endtag(self, tag):
if tag in ("script", "style", "head", "meta", "link") and self._skip_depth > 0:
self._skip_depth -= 1
if tag in ("p", "br", "li", "div", "tr", "h1", "h2", "h3", "h4", "h5", "h6"):
self._parts.append("\n")
if tag == "a" and self._current_href:
self._parts.append(f" ({self._current_href})")
self._current_href = None
def handle_data(self, data):
if self._skip_depth == 0:
self._parts.append(data)
def get_text(self) -> str:
return "".join(self._parts).strip()
def html_to_text(html_body: str) -> str:
parser = HTMLToTextParser()
parser.feed(html_body)
return parser.get_text()
def markdown_to_html(md_text: str) -> str:
text = html.escape(md_text)
text = re.sub(r"```(\w+)?\n?(.*?)```", r"<pre><code>\2</code></pre>", text, flags=re.DOTALL)
text = re.sub(r"`([^`]+)`", r"<code>\1</code>", text)
text = re.sub(r"\*\*(.+?)\*\*", r"<strong>\1</strong>", text)
text = re.sub(r"\*(.+?)\*", r"<em>\1</em>", text)
text = re.sub(r"~~(.+?)~~", r"<s>\1</s>", text)
text = re.sub(r"\[([^\]]+)\]\(([^)]+)\)", r'<a href="\2">\1</a>', text)
lines = text.split("\n")
result: list[str] = []
list_buffer: list[str] = []
in_list = False
for line in lines:
stripped = line.strip()
ul_match = re.match(r"^[\-\*]\s+(.+)$", stripped)
ol_match = re.match(r"^\d+\.\s+(.+)$", stripped)
if ul_match:
if not in_list:
in_list = True
list_buffer = []
list_buffer.append(f"<li>{ul_match.group(1)}</li>")
continue
if ol_match:
if not in_list:
in_list = True
list_buffer = []
list_buffer.append(f"<li>{ol_match.group(1)}</li>")
continue
if in_list:
in_list = False
result.append(f"<ul>{''.join(list_buffer)}</ul>")
list_buffer = []
heading_match = re.match(r"^#{1,6}\s+(.+)$", stripped)
if heading_match:
result.append(f"<p><strong>{heading_match.group(1)}</strong></p>")
continue
if not stripped:
result.append("<br>")
elif stripped.startswith("<") and not stripped.startswith("<br"):
result.append(stripped)
else:
result.append(f"<p>{stripped}</p>")
if in_list and list_buffer:
result.append(f"<ul>{''.join(list_buffer)}</ul>")
return "\n".join(result)
def get_agent_prompt_rules() -> list[str]:
from yuxi.channel.extensions.intercom.constants import INTERCOM_AGENT_PROMPT_RULES
return INTERCOM_AGENT_PROMPT_RULES