代码修改

This commit is contained in:
fengxiangdebaozi committed 2026-06-05 18:58:28 +08:00
1 parent 9bbd04d6cf
commit b0fdeab995
15 files changed
+467 -90

No files matched your search

@@ -288,6 +288,8 @@ class RoundtableJobExecutor:
idx = next((i for i, r in enumerate(runs) if r.get("id") == run_id), -1)
created = runs[idx].get("createdAt") if idx >= 0 else datetime.now(UTC).isoformat()
prev_step3 = runs[idx].get("step3") if idx >= 0 else None
# 本次有效 step3:新报告优先,否则保留上次(running 中间态 step3=None 不抹掉已存的)。
effective_step3 = step3 if step3 is not None else prev_step3
run = {
"id": run_id,
"title": "后台研讨",
@@ -308,17 +310,21 @@ class RoundtableJobExecutor:
"seatStubMessages": _seat_stub_messages(dialogues),
"orchestrationMode": params.mode,
"chain": params.chain,
"step3": step3 if step3 is not None else prev_step3,
"step3": effective_step3,
"jobId": params.job_id,
"jobStatus": status,
}
runs = [run if i == idx else r for i, r in enumerate(runs)] if idx >= 0 else [*runs, run]
step2["runs"] = runs
step2["activeRunId"] = run_id
# 顶层 draft.step3 也写一份(同 Step2 把对话写进 run 的同一次落库一并带上)。
# 前端 hydrateStep3 用**顶层** draft.step3 重建报告气泡(结果绘制的聊天记录 + HTML 预览);
# 只存 run 内 step3 时,加载会被 hydrateStep3(draft.step3=None) 覆盖成空 → 报告聊天记录丢失。
update_kwargs: dict[str, Any] = {"step2": step2, "furthest_step": 3 if status == "done" else 2}
if effective_step3 is not None:
update_kwargs["step3"] = effective_step3
try:
await self._draft_store.update_draft(
params.draft_id, params.user_id, step2=step2, furthest_step=3 if status == "done" else 2
)
await self._draft_store.update_draft(params.draft_id, params.user_id, **update_kwargs)
except Exception: # noqa: BLE001 — 写草稿失败不影响作业本身
logger.warning("write run to draft %s failed", params.draft_id, exc_info=True)
@@ -138,7 +138,11 @@ async def run_orchestration(
_SEAT_NO_ASK = (
"注意:这是自动化圆桌研讨,没有用户在线应答——**请勿向用户提问或等待确认**,"
"直接基于已知信息做出合理假设并产出完整的结构化交付(Markdown)。"
"直接基于已知信息做出合理假设,产出完整的结构化交付。\n"
"**交付方式(与前端手动研讨一致)**:请用 write_file 工具把你这一轮的完整交付整理成一份 "
"Markdown 文件,写入 /mnt/user-data/outputs/ 下(文件名体现你的职责,如 `情报收集.md`、"
"`风险评估.md`);同时在回复正文里给出这份交付的内容本身(供总控汇总),"
"不要只回复『已写入文件』这类空话。"
)
@@ -0,0 +1,114 @@
"""一次性巡检:把最新圆桌草稿里「后台作业 run」的关键字段 dump 到文件,
用于验证维度3 存储 + 报告 HTML + 席位 md 文件是否都对齐了。
用法(在 backend 目录):
PYTHONPATH=. uv run python scripts/inspect_latest_roundtable_run.py
输出写到 scripts/_roundtable_run_report.txt(UTF-8),直接打开看,避免 PowerShell GBK 乱码。
"""
from __future__ import annotations
import json
import sqlite3
from pathlib import Path
DB = Path(".deer-flow/data/deerflow.db")
OUT = Path("scripts/_roundtable_run_report.txt")
def _loads(v):
if isinstance(v, (bytes, bytearray)):
v = v.decode("utf-8", "replace")
if isinstance(v, str):
try:
return json.loads(v)
except Exception:
return v
return v
def main() -> None:
con = sqlite3.connect(str(DB))
con.row_factory = sqlite3.Row
lines: list[str] = []
# 最新一条有 step2.runs 的草稿
rows = con.execute(
"SELECT id, step2, step3 FROM roundtable_drafts ORDER BY updated_at DESC LIMIT 5"
).fetchall()
draft = None
top_step3 = None
for r in rows:
s2 = _loads(r["step2"]) or {}
if isinstance(s2, dict) and s2.get("runs"):
draft = (r["id"], s2)
top_step3 = _loads(r["step3"])
break
if not draft:
lines.append("没找到带 step2.runs 的草稿。")
OUT.write_text("\n".join(lines), encoding="utf-8")
print(f"written: {OUT}")
return
draft_id, s2 = draft
runs = s2.get("runs") or []
job_run = next((x for x in runs if str(x.get("id", "")).startswith("job-")), runs[-1])
lines.append(f"draft_id = {draft_id}")
lines.append(f"run.id = {job_run.get('id')} jobStatus = {job_run.get('jobStatus')} hasConsensus = {job_run.get('hasConsensus')}")
lines.append("")
# ── 维度3:threadIds ──
lines.append("【threadIds】(应为真实 map,不是 null)")
lines.append(json.dumps(job_run.get("threadIds"), ensure_ascii=False, indent=2))
lines.append("")
# ── 维度3:各对话的 steps / agentThreadId / time ──
lines.append("【step2RoundtableDialogues 摘要】")
for d in job_run.get("step2RoundtableDialogues") or []:
steps = d.get("steps") or []
step_keys = [s.get("key") for s in steps]
lines.append(
f"- [{d.get('sender')}] time={d.get('time')!r} thread={d.get('agentThreadId')!r} "
f"steps={step_keys} content_len={len(d.get('content') or '')}"
)
lines.append("")
# ── 席位 md 文件:seatStubMessages 里有没有 write_file ──
lines.append("【seatStubMessages】(席位写的文件 → 文件卡片数据源)")
stubs = job_run.get("seatStubMessages") or {}
if not stubs:
lines.append(" (空 —— 席位没有写文件 / 没采集到)")
for tid, msgs in stubs.items():
for m in msgs:
for tc in m.get("tool_calls") or []:
args = tc.get("args") or {}
lines.append(f" thread={tid} {tc.get('name')} path={args.get('path')!r} content_len={len(str(args.get('content') or ''))}")
lines.append("")
# ── 报告 HTML(P0)──
lines.append("【step3 报告】")
step3 = job_run.get("step3") or {}
html = step3.get("html") or ""
lines.append(f" html_len = {len(html)}")
lines.append(f" 含 <html 标签 = {'<html' in html.lower()} (True=真 HTML / False=纯文字回退=P0未解决)")
lines.append(f" summary = {(step3.get('summary') or '')[:120]!r}")
lines.append("")
# ── 顶层 draft.step3(结果绘制聊天记录靠它重建报告气泡)──
lines.append("【顶层 draft.step3】(前端 hydrateStep3 用它重建报告聊天记录气泡)")
if not top_step3:
lines.append(" ❌ 空 —— 报告聊天记录加载后会丢失(本次修复点:应非空)")
else:
th = (top_step3.get("html") or "") if isinstance(top_step3, dict) else ""
lines.append(f" ✅ 已存 html_len={len(th)} summary={(top_step3.get('summary') or '')[:80]!r}" if isinstance(top_step3, dict) else f" {top_step3!r}")
OUT.write_text("\n".join(lines), encoding="utf-8")
print(f"written: {OUT.resolve()}")
if __name__ == "__main__":
main()