Merge remote-tracking branch 'origin/master' into ji

# Conflicts:
#	frontend-web/src/contexts/ThemeContext.tsx
#	offline-backend-20260512/backend/config.yaml
This commit is contained in:
吉鑫升 committed 2026-05-26 19:34:43 +08:00
commit 1642c3e694
10 files changed
+1454 -167

No files matched your search

@@ -590,8 +590,18 @@ async def init_multi_agent(request: Request, payload: dict = Body(...)) -> Strea
"当你觉得已有信息支持回答用户问题时候,停止调度,并输出最后的结果\n"
"#调度方法:\n"
"通过使用agent_orchestration技能调用其他智能体干活,使用技能时传入agent_name和需要做的活。"
"注意:agent_name 必须严格使用下方列出的英文 id(例如 roundtable-intelligence),"
"注意:agent_name 必须严格使用下方列出的英文 id(例如 roundtable-intelligence,"
"或形如 02714cbe6e64406a8a4659f0e3d9c0b8 这样的 UUID),"
"不要把括号里的中文显示名拼进 agent_name 里。\n"
"#关键约束(必读):\n"
"1. **不要对同一子智能体重复派同样的活**:每次派活前回顾对话历史,"
"如果某个子智能体已经针对你正要派的任务完成过交付("
"看到形如\"子智能体[名称]完成XX工作,交付内容为:...\"的 human 消息),"
"就直接基于已有交付推进,**不要重复派活**,除非你确实有**具体的、不一样的**补充问题。\n"
"2. **看到交付要会用**:子智能体的交付内容会作为 human 消息追加到你的对话历史里,"
"你能完整看见。当各方信息已足够形成结论时,**直接综合输出最终方案**(此时不再调用任何工具),"
"让讨论收敛。\n"
"3. **避免无意义循环**:如果连续两轮都没有新信息流入,立刻停止派活并基于现有素材给出最终结论。\n"
"#可调度智能体:\n"
+ "\n".join(descriptions)
)
@@ -940,6 +950,8 @@ async def _special_run(
new_message: str,
skill_stop_names: list[str],
model_name: str,
*,
display_name: str = "",
) -> AsyncIterator[str | dict[str, Any]]:
"""子智能体(special)单轮:执行总控下发的 task 文本,交付 content。
@@ -1007,18 +1019,21 @@ async def _special_run(
# closes; the SSE connection stays open a bit longer but the frontend has
# already consumed the result.
t_before_post = time.perf_counter()
# 优先用 display_name(中文友好,例如"情报收集")提示 leader,id 放括号备查;
# display_name 缺失时退化为仅 agent_name —— 与旧行为一致。
speaker_label = f"{display_name}({agent_name})" if display_name else agent_name
post_broadcast_task = asyncio.create_task(
_broadcast(
client,
base,
headers,
f"子智能体{agent_name}完成{new_message}工作,交付内容为:" + content,
f"子智能体{speaker_label}完成{new_message}工作,交付内容为:" + content,
agent_threads,
[agent_name],
)
)
yield {
"status": f"子智能体{agent_name}完成{new_message}工作",
"status": f"子智能体{speaker_label}完成{new_message}工作",
"content": content,
"agent_name": agent_name,
}
@@ -1059,6 +1074,11 @@ async def run_multi_agent_stream(request: Request, payload: dict = Body(...)) ->
agent_type: str = str(payload.get("agent_type") or "leader").lower()
agent_threads: dict[str, str] = payload.get("d_agent_thread_id") or {}
agent_name: str = str(payload.get("agent_name") or "").lower()
# 人类可读名,仅 special 用 —— 后端把它拼进 post-broadcast 文本,这样 leader
# 下一轮看到的是"子智能体[中文名](id)完成..."而非"子智能体[UUID]完成...";
# LLM 对 UUID 不友好,只用 id 会导致总控认不出已完成的子智能体,无限循环派活。
# 缺失时 fallback 到 agent_name,旧前端不传也不破坏。
display_name: str = str(payload.get("display_name") or "").strip()
new_message: str = str(payload.get("new_message") or "")
skill_stop_names: list[str] = payload.get("skill_stop_names") or []
# 不写死任何默认模型;空串会让 lead_agent._resolve_model_name() 回退到
@@ -1089,6 +1109,7 @@ async def run_multi_agent_stream(request: Request, payload: dict = Body(...)) ->
else:
gen = _special_run(
client, base, headers, agent_threads, agent_name, new_message, skill_stop_names, model_name,
display_name=display_name,
)
async for chunk in gen:
if isinstance(chunk, dict):