feat: expose graph orchestration mode, fix pipeline multi-agent, add Feishu tools (Phase 3)

增强编排 + 飞书深度集成:
- Graph 模式:暴露 orchestrator._graph() 到 run() 方法,workflow_integration 支持 graph nodes/edges
- Pipeline 修复:多 Agent 按步骤轮转分配,不再只用 agents[0]
- 4个飞书操作工具: feishu_create_doc / feishu_create_calendar_event / feishu_search_contacts / feishu_send_approval
- 飞书 @mention→Goal:feishu/ orange WS handler 支持 "目标: xxx" 触发自动创建 Goal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renjianbo
2026-05-08 20:08:26 +08:00
parent 926ec6c0a1
commit d0b55f2b16
6 changed files with 490 additions and 27 deletions

View File

@@ -115,6 +115,27 @@ def _reply_card(open_id: str, title: str, content: str, status: str = "info"):
logger.warning("飞书回复卡片失败: %s", e)
async def _handle_goal_creation(db, user_id: str, goal_title: str, open_id: str):
"""从飞书消息中创建 Goal 并异步启动执行。"""
from app.services.goal_service import create_goal
from app.tasks.goal_tasks import execute_goal_task
try:
goal = create_goal(db=db, creator_id=user_id, title=goal_title, priority=5)
_reply_to_feishu(open_id, f"✅ 目标已创建: **{goal.title}**\n正在分解任务并启动执行...")
# 异步执行目标
task = execute_goal_task.delay(str(goal.id))
logger.info("飞书触发 Goal 创建: goal_id=%s celery_task=%s", goal.id, task.id)
# 更新状态
from app.services.goal_service import update_goal
update_goal(db, str(goal.id), status="active")
except Exception as e:
logger.error("飞书 Goal 创建失败: %s", e)
_reply_to_feishu(open_id, f"创建目标失败: {e}")
async def _handle_message_async(data):
"""异步处理飞书消息。"""
open_id = _get_sender_open_id(data)
@@ -225,6 +246,22 @@ async def _handle_message_async(data):
memory_scope_id=str(agent.id),
)
# ── 目标/任务意图检测:创建 Goal 并异步执行 ──
goal_triggers = ["创建目标:", "目标:", "创建任务:", "new goal:", "goal:"]
triggered_goal = False
goal_title = ""
for trigger in goal_triggers:
if text.lower().startswith(trigger.lower()):
trigger_text = text[len(trigger):].strip()
if trigger_text:
goal_title = trigger_text[:500]
triggered_goal = True
break
if triggered_goal and goal_title:
await _handle_goal_creation(db, user.id, goal_title, open_id)
return
on_llm_call = _make_llm_logger(db, agent_id=str(agent.id), user_id=user.id)
runtime = AgentRuntime(config=config, on_llm_call=on_llm_call)
result = await runtime.run(text)