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:
renjianbo
2026-05-02 16:17:49 +08:00
parent 0bbf68d5bb
commit 7ee80c74b2
29 changed files with 4288 additions and 5 deletions

View File

@@ -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: