feat: 重构了智能思维导图和摘要插件的事件发射逻辑,并新增了插件开发指南。

This commit is contained in:
fujie
2025-12-20 17:03:40 +08:00
parent afaa25d441
commit 3ddddb69d7
9 changed files with 587 additions and 473 deletions

View File

@@ -394,11 +394,11 @@ SCRIPT_TEMPLATE_MINDMAP = """
class Action:
class Valves(BaseModel):
show_status: bool = Field(
SHOW_STATUS: bool = Field(
default=True,
description="Whether to show action status updates in the chat interface.",
)
LLM_MODEL_ID: str = Field(
MODEL_ID: str = Field(
default="",
description="Built-in LLM model ID for text analysis. If empty, uses the current conversation's model.",
)
@@ -434,6 +434,20 @@ class Action:
extracted_content = llm_output.strip()
return extracted_content.replace("</script>", "<\\/script>")
async def _emit_status(self, emitter, description: str, done: bool = False):
"""Emits a status update event."""
if self.valves.SHOW_STATUS and emitter:
await emitter(
{"type": "status", "data": {"description": description, "done": done}}
)
async def _emit_notification(self, emitter, content: str, ntype: str = "info"):
"""Emits a notification event (info/success/warning/error)."""
if emitter:
await emitter(
{"type": "notification", "data": {"type": ntype, "content": content}}
)
def _remove_existing_html(self, content: str) -> str:
"""Removes existing plugin-generated HTML code blocks from the content."""
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
@@ -523,16 +537,11 @@ class Action:
current_year = now.strftime("%Y")
current_timezone_str = "Unknown"
if __event_emitter__:
await __event_emitter__(
{
"type": "notification",
"data": {
"type": "info",
"content": "Smart Mind Map is starting, generating mind map for you...",
},
}
)
await self._emit_notification(
__event_emitter__,
"Smart Mind Map is starting, generating mind map for you...",
"info",
)
messages = body.get("messages")
if (
@@ -541,13 +550,7 @@ class Action:
or not messages[-1].get("content")
):
error_message = "Unable to retrieve valid user message content."
if __event_emitter__:
await __event_emitter__(
{
"type": "notification",
"data": {"type": "error", "content": error_message},
}
)
await self._emit_notification(__event_emitter__, error_message, "error")
return {
"messages": [{"role": "assistant", "content": f"{error_message}"}]
}
@@ -565,30 +568,20 @@ class Action:
if len(long_text_content) < self.valves.MIN_TEXT_LENGTH:
short_text_message = f"Text content is too short ({len(long_text_content)} characters), unable to perform effective analysis. Please provide at least {self.valves.MIN_TEXT_LENGTH} characters of text."
if __event_emitter__:
await __event_emitter__(
{
"type": "notification",
"data": {"type": "warning", "content": short_text_message},
}
)
await self._emit_notification(
__event_emitter__, short_text_message, "warning"
)
return {
"messages": [
{"role": "assistant", "content": f"⚠️ {short_text_message}"}
]
}
if self.valves.show_status and __event_emitter__:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "Smart Mind Map: Analyzing text structure in depth...",
"done": False,
"hidden": False,
},
}
)
await self._emit_status(
__event_emitter__,
"Smart Mind Map: Analyzing text structure in depth...",
False,
)
try:
unique_id = f"id_{int(time.time() * 1000)}"
@@ -603,7 +596,7 @@ class Action:
)
# Determine model to use
target_model = self.valves.LLM_MODEL_ID
target_model = self.valves.MODEL_ID
if not target_model:
target_model = body.get("model")
@@ -684,26 +677,14 @@ class Action:
html_embed_tag = f"```html\n{final_html}\n```"
body["messages"][-1]["content"] = f"{long_text_content}\n\n{html_embed_tag}"
if self.valves.show_status and __event_emitter__:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "Smart Mind Map: Drawing completed!",
"done": True,
"hidden": False,
},
}
)
await __event_emitter__(
{
"type": "notification",
"data": {
"type": "success",
"content": f"Mind map has been generated, {user_name}!",
},
}
)
await self._emit_status(
__event_emitter__, "Smart Mind Map: Drawing completed!", True
)
await self._emit_notification(
__event_emitter__,
f"Mind map has been generated, {user_name}!",
"success",
)
logger.info("Action: Smart Mind Map (v0.7.2) completed successfully")
except Exception as e:
@@ -714,26 +695,13 @@ class Action:
"content"
] = f"{long_text_content}\n\n❌ **Error:** {user_facing_error}"
if __event_emitter__:
if self.valves.show_status:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "Smart Mind Map: Processing failed.",
"done": True,
"hidden": False,
},
}
)
await __event_emitter__(
{
"type": "notification",
"data": {
"type": "error",
"content": f"Smart Mind Map generation failed, {user_name}!",
},
}
)
await self._emit_status(
__event_emitter__, "Smart Mind Map: Processing failed.", True
)
await self._emit_notification(
__event_emitter__,
f"Smart Mind Map generation failed, {user_name}!",
"error",
)
return body

View File

@@ -394,10 +394,10 @@ SCRIPT_TEMPLATE_MINDMAP = """
class Action:
class Valves(BaseModel):
show_status: bool = Field(
SHOW_STATUS: bool = Field(
default=True, description="是否在聊天界面显示操作状态更新。"
)
LLM_MODEL_ID: str = Field(
MODEL_ID: str = Field(
default="",
description="用于文本分析的内置LLM模型ID。如果为空则使用当前对话的模型。",
)
@@ -433,6 +433,20 @@ class Action:
extracted_content = llm_output.strip()
return extracted_content.replace("</script>", "<\\/script>")
async def _emit_status(self, emitter, description: str, done: bool = False):
"""发送状态更新事件。"""
if self.valves.SHOW_STATUS and emitter:
await emitter(
{"type": "status", "data": {"description": description, "done": done}}
)
async def _emit_notification(self, emitter, content: str, ntype: str = "info"):
"""发送通知事件 (info/success/warning/error)。"""
if emitter:
await emitter(
{"type": "notification", "data": {"type": ntype, "content": content}}
)
def _remove_existing_html(self, content: str) -> str:
"""移除内容中已有的插件生成 HTML 代码块 (通过标记识别)。"""
pattern = r"```html\s*<!-- OPENWEBUI_PLUGIN_OUTPUT -->[\s\S]*?```"
@@ -522,16 +536,9 @@ class Action:
current_year = now.strftime("%Y")
current_timezone_str = "未知时区"
if __event_emitter__:
await __event_emitter__(
{
"type": "notification",
"data": {
"type": "info",
"content": "智绘心图已启动,正在为您生成思维导图...",
},
}
)
await self._emit_notification(
__event_emitter__, "智绘心图已启动,正在为您生成思维导图...", "info"
)
messages = body.get("messages")
if (
@@ -540,13 +547,7 @@ class Action:
or not messages[-1].get("content")
):
error_message = "无法获取有效的用户消息内容。"
if __event_emitter__:
await __event_emitter__(
{
"type": "notification",
"data": {"type": "error", "content": error_message},
}
)
await self._emit_notification(__event_emitter__, error_message, "error")
return {
"messages": [{"role": "assistant", "content": f"{error_message}"}]
}
@@ -564,30 +565,18 @@ class Action:
if len(long_text_content) < self.valves.MIN_TEXT_LENGTH:
short_text_message = f"文本内容过短({len(long_text_content)}字符),无法进行有效分析。请提供至少{self.valves.MIN_TEXT_LENGTH}字符的文本。"
if __event_emitter__:
await __event_emitter__(
{
"type": "notification",
"data": {"type": "warning", "content": short_text_message},
}
)
await self._emit_notification(
__event_emitter__, short_text_message, "warning"
)
return {
"messages": [
{"role": "assistant", "content": f"⚠️ {short_text_message}"}
]
}
if self.valves.show_status and __event_emitter__:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "智绘心图: 深入分析文本结构...",
"done": False,
"hidden": False,
},
}
)
await self._emit_status(
__event_emitter__, "智绘心图: 深入分析文本结构...", False
)
try:
unique_id = f"id_{int(time.time() * 1000)}"
@@ -602,7 +591,7 @@ class Action:
)
# 确定使用的模型
target_model = self.valves.LLM_MODEL_ID
target_model = self.valves.MODEL_ID
if not target_model:
target_model = body.get("model")
@@ -682,26 +671,10 @@ class Action:
html_embed_tag = f"```html\n{final_html}\n```"
body["messages"][-1]["content"] = f"{long_text_content}\n\n{html_embed_tag}"
if self.valves.show_status and __event_emitter__:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "智绘心图: 绘制完成!",
"done": True,
"hidden": False,
},
}
)
await __event_emitter__(
{
"type": "notification",
"data": {
"type": "success",
"content": f"思维导图已生成,{user_name}",
},
}
)
await self._emit_status(__event_emitter__, "智绘心图: 绘制完成!", True)
await self._emit_notification(
__event_emitter__, f"思维导图已生成,{user_name}", "success"
)
logger.info("Action: 智绘心图 (v12) completed successfully")
except Exception as e:
@@ -712,26 +685,9 @@ class Action:
"content"
] = f"{long_text_content}\n\n❌ **错误:** {user_facing_error}"
if __event_emitter__:
if self.valves.show_status:
await __event_emitter__(
{
"type": "status",
"data": {
"description": "智绘心图: 处理失败。",
"done": True,
"hidden": False,
},
}
)
await __event_emitter__(
{
"type": "notification",
"data": {
"type": "error",
"content": f"智绘心图生成失败, {user_name}",
},
}
)
await self._emit_status(__event_emitter__, "智绘心图: 处理失败。", True)
await self._emit_notification(
__event_emitter__, f"智绘心图生成失败, {user_name}", "error"
)
return body