feat: 集成飞书通知和机器人对话系统
- 新增通知系统 (notifications 表、服务、API) - 新增飞书定时任务结果推送 (webhook + 应用消息) - 新增飞书应用消息发送服务 (feishu_app_service) - 新增飞书 WebSocket 长连接事件监听 (苹果应用) - 新增飞书账号绑定/解绑 API - 新增橙子飞书机器人 (独立 WS 连接,固定路由到橙子助手 Agent) - 执行记录添加 schedule_id,用户添加飞书绑定字段 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ from app.models.agent import Agent
|
||||
from app.models.workflow import Workflow
|
||||
from app.services.execution_budget import merge_budget_for_execution
|
||||
from app.services.agent_workspace_chat_log import try_append_agent_dialogue_after_success
|
||||
from app.services.notification_service import create_notification
|
||||
import asyncio
|
||||
import time
|
||||
from typing import Any, Dict, Optional
|
||||
@@ -54,6 +55,92 @@ def _trusted_user_for_execution(db, execution: Optional[Execution]) -> Optional[
|
||||
return None
|
||||
|
||||
|
||||
def _notify_schedule_result(
|
||||
db,
|
||||
execution,
|
||||
status: str,
|
||||
error_message: Optional[str] = None,
|
||||
):
|
||||
"""如果 execution 关联了定时任务,创建通知推送结果给用户。"""
|
||||
if not execution or not execution.schedule_id:
|
||||
return
|
||||
try:
|
||||
from app.models.agent_schedule import AgentSchedule
|
||||
|
||||
schedule = db.query(AgentSchedule).filter(AgentSchedule.id == execution.schedule_id).first()
|
||||
if not schedule:
|
||||
return
|
||||
|
||||
if status == "completed":
|
||||
title = f"定时任务「{schedule.name}」执行成功"
|
||||
content = f"Agent 已按计划执行完成。"
|
||||
else:
|
||||
title = f"定时任务「{schedule.name}」执行失败"
|
||||
content = f"错误信息: {error_message or '未知错误'}"
|
||||
|
||||
create_notification(
|
||||
db,
|
||||
user_id=schedule.user_id,
|
||||
title=title,
|
||||
content=content,
|
||||
category="schedule",
|
||||
ref_type="execution",
|
||||
ref_id=str(execution.id),
|
||||
)
|
||||
db.commit()
|
||||
|
||||
# 如果配置了飞书 webhook,发送飞书通知(非阻塞,失败不影响主流程)
|
||||
if schedule.webhook_url:
|
||||
try:
|
||||
from app.services.feishu_notifier import send_feishu_card
|
||||
|
||||
detail_link = None
|
||||
# 如果系统配置了外部访问地址,拼接 execution 详情链接
|
||||
try:
|
||||
from app.core.config import settings
|
||||
if settings.EXTERNAL_URL:
|
||||
detail_link = f"{settings.EXTERNAL_URL}/executions/{execution.id}"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
send_feishu_card(
|
||||
webhook_url=schedule.webhook_url,
|
||||
title=title,
|
||||
body=content,
|
||||
status=status,
|
||||
detail_link=detail_link,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("飞书 webhook 通知发送失败: %s", e)
|
||||
|
||||
# 如果用户绑定了飞书账号,通过飞书应用发送通知
|
||||
try:
|
||||
from app.models.user import User
|
||||
from app.services.feishu_app_service import send_message_to_user
|
||||
|
||||
schedule_user = db.query(User).filter(User.id == schedule.user_id).first()
|
||||
if schedule_user and schedule_user.feishu_open_id:
|
||||
detail_link = None
|
||||
try:
|
||||
from app.core.config import settings
|
||||
if settings.EXTERNAL_URL:
|
||||
detail_link = f"{settings.EXTERNAL_URL}/executions/{execution.id}"
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
send_message_to_user(
|
||||
open_id=schedule_user.feishu_open_id,
|
||||
title=title,
|
||||
content=content,
|
||||
status=status,
|
||||
detail_link=detail_link,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.warning("飞书应用通知发送失败: %s", e)
|
||||
except Exception as e:
|
||||
logger.warning("创建定时任务通知失败: %s", e)
|
||||
|
||||
|
||||
@celery_app.task(bind=True)
|
||||
def execute_workflow_task(
|
||||
self,
|
||||
@@ -172,7 +259,10 @@ def execute_workflow_task(
|
||||
except Exception as e:
|
||||
# 告警检测失败不影响执行结果
|
||||
execution_logger.warn(f"告警检测失败: {str(e)}")
|
||||
|
||||
|
||||
# 定时任务结果通知
|
||||
_notify_schedule_result(db, execution, "completed")
|
||||
|
||||
return {
|
||||
'status': 'completed',
|
||||
'result': result,
|
||||
@@ -213,7 +303,10 @@ def execute_workflow_task(
|
||||
# 告警检测失败不影响错误处理
|
||||
if execution_logger:
|
||||
execution_logger.warn(f"告警检测失败: {str(e2)}")
|
||||
|
||||
|
||||
# 定时任务失败通知
|
||||
_notify_schedule_result(db, execution, "failed", error_message=err_text)
|
||||
|
||||
raise
|
||||
|
||||
finally:
|
||||
|
||||
Reference in New Issue
Block a user