| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646 |
- from __future__ import annotations
- import re
- from typing import Any
- from .business_detail_text import (
- assessment_text,
- batches_markdown,
- branch_task_sections,
- branch_task_text,
- branches_markdown,
- business_text,
- decisions_markdown,
- event_business_sections,
- source_markdown,
- clean_report,
- )
- from .sanitizer import sanitize
- from .retrieval_detail_projection import (
- is_retrieval_detail_event,
- project_retrieval_event,
- )
- def project_round_detail(
- script_build_id: int,
- round_: dict[str, Any],
- bundle: dict[str, Any] | None = None,
- ) -> dict[str, Any]:
- raw_round = next(
- (
- item
- for item in (bundle or {}).get("rounds", [])
- if int(item.get("round_index") or 0) == int(round_.get("roundIndex") or 0)
- ),
- None,
- )
- sections = [
- _section(
- "goal",
- "本轮目标",
- (raw_round or {}).get("goal")
- or (round_.get("summary", {}).get("goal") or {}).get("headline"),
- ),
- _section("plan", "当前保存的规划", _plan_text(round_.get("plan") or {})),
- _section("branches", "候选方案", branches_markdown(round_.get("branches") or [])),
- _section(
- "decisions",
- "候选评审与主 Agent 决策",
- _convergence_markdown(round_.get("convergenceBatches") or []),
- ),
- _section(
- "evaluation",
- "主脚本整体评审",
- _node_value(round_.get("overallEvaluation")) or "未找到明确整轮评审结论",
- ),
- _section("result", "本轮产出", _node_value(round_.get("result"))),
- ]
- result = round_.get("result") or {}
- changes = None
- if result.get("hasChanges"):
- changes = {
- "summary": _node_value(result),
- "sections": [
- item
- for item in [
- _section(
- "content",
- "内容方案",
- _round_content_changes(round_.get("branches") or []),
- ),
- _section(
- "domain",
- "领域信息",
- _round_domain_changes(round_.get("branches") or []),
- ),
- ]
- if item
- ],
- "artifactRef": "artifact:base:current",
- "exactness": "current-only",
- }
- return _payload(
- sections,
- {
- "scriptBuildId": script_build_id,
- "round": raw_round,
- "multipathDecisions": [
- item
- for item in (bundle or {}).get("multipathDecisions", [])
- if int(item.get("round_index") or 0) == int(round_.get("roundIndex") or 0)
- ],
- },
- changes,
- )
- def project_activity_detail(
- script_build_id: int,
- activity_id: str,
- view: dict[str, Any],
- bundle: dict[str, Any],
- event_detail: dict[str, Any] | None = None,
- ) -> dict[str, Any]:
- if activity_id == "run:final-result":
- return _final_result_detail(script_build_id, view, bundle)
- missing_convergence = _find_missing_convergence(view, activity_id)
- if missing_convergence is not None:
- node, batch = missing_convergence
- return _payload(
- [
- _section(
- "status",
- str(node.get("title") or "记录状态"),
- _node_value(node),
- "summary",
- )
- ],
- {
- "scriptBuildId": script_build_id,
- "roundIndex": batch.get("roundIndex"),
- "branchIds": batch.get("branchIds") or [],
- "association": batch.get("association"),
- "unscopedReviewRefs": node.get("unscopedReviewRefs") or [],
- },
- )
- decision = _find_decision_projection(view, activity_id)
- if decision is not None:
- return _decision_detail_payload(
- script_build_id, decision, bundle, activity_id, event_detail
- )
- if activity_id.startswith("domain-info:"):
- record_id = _suffix_int(activity_id)
- row = _find_by_id(bundle.get("domainInfo") or [], record_id)
- if not row:
- raise KeyError(activity_id)
- return _payload(
- [
- _section("fact", "已核实领域事实", row.get("content")),
- _section("verification", "核实说明", row.get("note")),
- _section("source", "信息出处", _source_value(row.get("source"))),
- _section(
- "use",
- "用途与存疑状态",
- "已作为领域事实独立保存;是否进入具体候选脚本文案未记录。",
- ),
- ],
- {"scriptBuildId": script_build_id, "table": "script_build_domain_info", "record": row},
- {
- "summary": "这条领域事实已经独立写入领域信息库。",
- "sections": [],
- "exactness": "exact",
- },
- )
- if activity_id.startswith("retrieval-direct:"):
- group = _find_retrieval_item(view, "directToolGroups", activity_id)
- if not group:
- raise KeyError(activity_id)
- calls = group.get("calls") or []
- payload = _payload(
- [
- _section("purpose", "读取方式", "实现 Agent 直接调用只读工具,补齐创作所需的上下文。"),
- _section("sources", "读取了什么", _direct_sources_markdown(group)),
- _section("result", "得到什么", _direct_result_markdown(calls), "summary"),
- ],
- {
- "scriptBuildId": script_build_id,
- "retrievalGroup": group,
- "events": _events_for_ids(bundle, [item.get("eventId") for item in calls]),
- },
- )
- payload.update(
- {
- "detailKind": "retrieval-group",
- "retrievalKind": "direct-tools",
- "activities": [
- {
- "id": item.get("id") or item.get("detailRef"),
- "kind": "tool",
- "label": item.get("businessLabel") or "读取相关信息",
- "status": item.get("status") or "unknown",
- "summary": item.get("resultSummary") or "",
- "detailRef": item.get("detailRef"),
- }
- for item in calls
- ],
- }
- )
- return payload
- if activity_id.startswith("retrieval-agent:"):
- run = _find_retrieval_item(view, "agentRuns", activity_id)
- if not run:
- raise KeyError(activity_id)
- event = event_detail or _event_by_id(bundle, run.get("eventId"))
- screening = run.get("screening") or {}
- full_task = _event_nested_value(event, "input", "task")
- raw_screening_text = _event_nested_value(event, "output", "summary")
- if not raw_screening_text:
- raw_screening_text = screening.get("preview")
- screening_text = clean_report(raw_screening_text)
- payload = _payload(
- [
- _section("task", "完整取数任务", full_task or run.get("taskPreview") or "取数目标未记录"),
- _section("queries", "查询过程", _agent_query_markdown(run)),
- _section("hits", "原始命中", _agent_hit_markdown(run)),
- _section(
- "screening",
- "初筛整理",
- screening_text or _screening_fallback(screening.get("state")),
- "report",
- ),
- ],
- {
- "scriptBuildId": script_build_id,
- "agentRun": run,
- "agentEvent": event,
- "queryEvents": _events_for_ids(bundle, [item.get("eventId") for item in run.get("attempts") or []]),
- },
- )
- activities = [
- {
- "id": item.get("id") or item.get("detailRef"),
- "kind": "query",
- "label": item.get("queryLabel") or "查询内容详见详情",
- "status": item.get("status") or "unknown",
- "resultCount": item.get("resultCount"),
- "detailRef": item.get("detailRef"),
- }
- for item in run.get("attempts") or []
- ]
- payload.update(
- {
- "detailKind": "retrieval-agent",
- "retrievalKind": "agent",
- "activities": activities,
- }
- )
- if not activities:
- if script_build_id <= 433:
- payload["missingActivityNotice"] = "该历史运行没有结构化查询明细。"
- elif run.get("agentType") == "retrieve_data_pattern_relation":
- payload["missingActivityNotice"] = (
- "本次运行未保存可下钻的结构化查询记录。"
- )
- return payload
- round_index, branch_id, role = _activity_parts(activity_id)
- round_ = _find_round(view, round_index) if round_index is not None else None
- if round_ is None:
- raise KeyError(activity_id)
- if branch_id is None:
- if role is None:
- return project_round_detail(script_build_id, round_, bundle)
- node = _round_node(round_, role)
- if not node:
- raise KeyError(activity_id)
- raw_round = next(
- (
- item
- for item in bundle.get("rounds") or []
- if int(item.get("round_index") or 0) == round_index
- ),
- None,
- )
- if role == "result":
- return _round_result_detail(script_build_id, round_, raw_round, bundle)
- return _node_detail(script_build_id, node, raw_round)
- branch = next(
- (
- item
- for item in round_.get("branches") or []
- if int(item.get("branchId") or 0) == branch_id
- ),
- None,
- )
- raw_branch = next(
- (
- item
- for item in bundle.get("branches") or []
- if int(item.get("branch_id") or 0) == branch_id
- ),
- None,
- )
- if not branch:
- raise KeyError(activity_id)
- if role is None:
- return _branch_detail(script_build_id, branch, raw_branch, bundle)
- if role == "retrieval":
- return _retrieval_stage_detail(script_build_id, branch, raw_branch, bundle)
- node = _branch_node(branch, role)
- if not node:
- raise KeyError(activity_id)
- if role == "output":
- return _branch_output_detail(script_build_id, branch, raw_branch, bundle)
- if role == "task":
- return _branch_task_detail(
- script_build_id,
- branch,
- raw_branch,
- bundle,
- round_index=round_index,
- branch_id=branch_id,
- )
- return _node_detail(script_build_id, node, raw_branch)
- def project_event_detail(
- script_build_id: int,
- event: dict[str, Any],
- *,
- run_status: str | None = None,
- ) -> dict[str, Any]:
- if is_retrieval_detail_event(event):
- payload = project_retrieval_event(event, run_status=run_status)
- payload["technical"] = sanitize(
- {
- "source": {
- "scriptBuildId": script_build_id,
- "table": "script_build_event / script_build_event_body",
- "detailRef": f"event:{event.get('id')}",
- },
- **_event_technical_groups(event),
- },
- max_text=None,
- )
- return sanitize(payload, max_text=None)
- if (
- event.get("event_name") == "think_and_plan"
- and event.get("agent_role") == "main"
- and int(event.get("agent_depth") or 0) == 0
- ):
- raw_input = event.get("input")
- content = raw_input.get("content") if isinstance(raw_input, dict) else None
- data = content if isinstance(content, dict) else event.get("inputData")
- data = data if isinstance(data, dict) else {}
- return _payload(
- [
- _section(
- "summary",
- "规划概要",
- data.get("thought_summary"),
- "summary",
- visual_role="key-result",
- ),
- _section(
- "thought",
- "完整思考",
- data.get("thought"),
- "report",
- visual_role="section",
- ),
- _section(
- "plan",
- "执行计划",
- data.get("plan"),
- visual_role="section",
- ),
- _section(
- "action",
- "下一步",
- data.get("action"),
- visual_role="reason",
- ),
- ],
- {
- "scriptBuildId": script_build_id,
- "table": "script_build_event / script_build_event_body",
- "event": event,
- },
- )
- return _payload(
- event_business_sections(event),
- {"scriptBuildId": script_build_id, "table": "script_build_event / script_build_event_body", "event": event},
- )
- def project_artifact_detail(
- script_build_id: int, snapshot_ref: str, artifact: dict[str, Any]
- ) -> dict[str, Any]:
- paragraphs, elements, links = _normalized_artifact_records(artifact)
- exactness = "current-only" if "base:current" in snapshot_ref else _artifact_exactness(artifact)
- context = artifact.get("artifactContext") if isinstance(artifact.get("artifactContext"), dict) else {}
- context = {
- "type": context.get("type") or ("final" if "base:current" in snapshot_ref else "candidate"),
- **context,
- "exactness": exactness,
- }
- candidate = context.get("type") == "candidate"
- scale_title = "候选脚本规模" if candidate else "主脚本规模"
- content_summary = "候选脚本内容" if candidate else "当前主脚本内容"
- payload = _payload(
- [
- _section("summary", scale_title, f"{len(paragraphs)} 个段落、{len(elements)} 个元素、{len(links)} 条关联"),
- ],
- {
- "scriptBuildId": script_build_id,
- "snapshotRef": snapshot_ref,
- "sourceOrigin": artifact.get("sourceOrigin") or "database",
- "exactness": exactness,
- "artifactContext": context,
- "recordCounts": {
- "paragraphs": len(paragraphs),
- "elements": len(elements),
- "links": len(links),
- },
- },
- {
- "summary": content_summary,
- "sections": [
- _section(
- "counts",
- "内容规模",
- f"{len(paragraphs)} 个段落、{len(elements)} 个元素、{len(links)} 条关联",
- ),
- ],
- "artifactRef": snapshot_ref,
- "exactness": exactness,
- },
- )
- payload["scriptTable"] = sanitize(
- _script_table_projection(snapshot_ref, artifact, exactness),
- max_text=None,
- )
- payload["artifactContext"] = sanitize(context, max_text=None)
- return payload
- _ELEMENT_REFERENCE = re.compile(r"\[([^\]:]+):(\d+)\]")
- _SCRIPT_SECTIONS = (
- ("theme", "主题"),
- ("form", "形式"),
- ("function", "作用"),
- ("feeling", "感受"),
- )
- def _script_table_projection(
- snapshot_ref: str, artifact: dict[str, Any], exactness: str
- ) -> dict[str, Any]:
- snapshot = artifact.get("snapshot") if isinstance(artifact.get("snapshot"), dict) else artifact
- snapshot = snapshot if isinstance(snapshot, dict) else {}
- paragraphs, elements, links = _normalized_artifact_records(artifact)
- element_names: dict[int, str] = {}
- for element in elements:
- element_id = _as_int(element.get("effectiveId") or element.get("id"))
- row_id = _as_int(element.get("rowId") or element.get("id"))
- name = str(element.get("name") or "").strip()
- if element_id is not None:
- element_names[element_id] = name
- if row_id is not None:
- element_names[row_id] = name
- paragraph_rows = _ordered_paragraphs(
- [_script_paragraph(row, element_names) for row in paragraphs]
- )
- paragraph_lookup: dict[int, dict[str, Any]] = {}
- for paragraph in paragraph_rows:
- for key in ("id", "rowId"):
- value = _as_int(paragraph.get(key))
- if value is not None:
- paragraph_lookup[value] = paragraph
- linked_paragraphs: dict[int, list[dict[str, Any]]] = {}
- for link in links:
- element_id = _as_int(link.get("element_id") or link.get("elementId"))
- paragraph_id = _as_int(link.get("paragraph_id") or link.get("paragraphId"))
- paragraph = paragraph_lookup.get(paragraph_id) if paragraph_id is not None else None
- if element_id is None or paragraph is None:
- continue
- linked_paragraphs.setdefault(element_id, []).append(
- {
- "id": paragraph.get("id"),
- "index": paragraph.get("index"),
- "name": paragraph.get("name"),
- }
- )
- element_rows = []
- for element in elements:
- element_id = element.get("effectiveId") or element.get("id")
- row_id = element.get("rowId") or element.get("id")
- link_keys = {
- value
- for value in (_as_int(row_id), _as_int(element_id))
- if value is not None
- }
- linked = [
- paragraph
- for key in link_keys
- for paragraph in linked_paragraphs.get(key, [])
- ]
- element_rows.append(
- {
- "id": element_id,
- "rowId": row_id,
- "name": element.get("name") or "未命名元素",
- "primaryDimension": element.get("dimension_primary"),
- "secondaryDimension": element.get("dimension_secondary"),
- "paragraphs": _unique_records(linked, "id"),
- }
- )
- element_rows.sort(key=lambda row: (str(row.get("name") or ""), _sort_number(row.get("id"))))
- return {
- "snapshotRef": snapshot_ref,
- "exactness": exactness,
- "sourceOrigin": artifact.get("sourceOrigin") or snapshot.get("sourceOrigin") or "database",
- "counts": {
- "paragraphs": len(paragraph_rows),
- "elements": len(element_rows),
- "links": len(links),
- },
- "maxDepth": (
- max((int(row.get("depth") or 0) for row in paragraph_rows), default=0) + 1
- if paragraph_rows
- else 0
- ),
- "paragraphs": paragraph_rows,
- "elements": element_rows,
- }
- def _normalized_artifact_records(
- artifact: dict[str, Any],
- ) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[dict[str, Any]]]:
- """Normalize current overlays and frozen branch snapshots to one table shape.
- Current overlays store a flat ``paragraphs`` list plus top-level
- ``paragraphElements``. Frozen ``content_snapshot`` rows store second-level
- paragraphs under ``sub_paragraphs`` and links under each paragraph's
- ``linked_elements``. The visualizer must preserve both without pretending
- that a truncated top-level list is the complete candidate script.
- """
- snapshot = artifact.get("snapshot") if isinstance(artifact.get("snapshot"), dict) else artifact
- snapshot = snapshot if isinstance(snapshot, dict) else {}
- paragraphs: list[dict[str, Any]] = []
- seen_paragraphs: set[tuple[str, str]] = set()
- def visit(row: Any, parent_id: Any = None) -> None:
- if not isinstance(row, dict):
- return
- current = dict(row)
- children = current.pop("sub_paragraphs", None) or current.pop("subParagraphs", None) or []
- if parent_id is not None and current.get("parent_id") is None and current.get("parentId") is None:
- current["parent_id"] = parent_id
- row_id = current.get("rowId") or current.get("id")
- key = (str(row_id), str(current.get("baseRefId") or current.get("base_ref_id") or ""))
- if key not in seen_paragraphs:
- seen_paragraphs.add(key)
- paragraphs.append(current)
- effective_parent = current.get("effectiveId") or current.get("id") or row_id
- for child in children if isinstance(children, list) else []:
- visit(child, effective_parent)
- for paragraph in snapshot.get("paragraphs") or []:
- visit(paragraph)
- elements = [item for item in snapshot.get("elements") or [] if isinstance(item, dict)]
- links: list[dict[str, Any]] = []
- seen_links: set[tuple[str, str]] = set()
- def append_link(link: Any, paragraph_id: Any = None) -> None:
- if not isinstance(link, dict):
- return
- current = dict(link)
- if paragraph_id is not None and current.get("paragraph_id") is None and current.get("paragraphId") is None:
- current["paragraph_id"] = paragraph_id
- element_id = current.get("element_id") or current.get("elementId")
- linked_paragraph = current.get("paragraph_id") or current.get("paragraphId")
- if element_id is None or linked_paragraph is None:
- return
- key = (str(linked_paragraph), str(element_id))
- if key in seen_links:
- return
- seen_links.add(key)
- links.append(current)
- for link in snapshot.get("paragraphElements") or snapshot.get("paragraph_elements") or []:
- append_link(link)
- for paragraph in paragraphs:
- paragraph_id = paragraph.get("effectiveId") or paragraph.get("id") or paragraph.get("rowId")
- nested_links = paragraph.get("linked_elements") or paragraph.get("linkedElements") or []
- if isinstance(nested_links, list) and nested_links:
- for link in nested_links:
- append_link(link, paragraph_id)
- else:
- for element_id in paragraph.get("linked_element_ids") or paragraph.get("linkedElementIds") or []:
- append_link({"element_id": element_id}, paragraph_id)
- return paragraphs, elements, links
- def _script_paragraph(row: dict[str, Any], element_names: dict[int, str]) -> dict[str, Any]:
- full_description = str(row.get("full_description") or "")
- return {
- "id": row.get("effectiveId") or row.get("id"),
- "rowId": row.get("rowId") or row.get("id"),
- "parentId": row.get("parent_id"),
- "depth": 0,
- "index": row.get("paragraph_index"),
- "level": row.get("level"),
- "name": row.get("name") or "未命名段落",
- "contentRange": _content_range(row.get("content_range")),
- "sections": {
- key: {
- "label": label,
- "description": row.get(key),
- "descriptionParts": _description_parts(
- str(row.get(key) or ""), element_names
- ),
- "dimensions": _dimensions(row.get(f"{key}_elements")),
- }
- for key, label in _SCRIPT_SECTIONS
- },
- "description": row.get("description"),
- "fullDescription": full_description,
- "fullDescriptionParts": _description_parts(full_description, element_names),
- }
- def _ordered_paragraphs(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
- """Keep every child next to its real parent without guessing from level labels."""
- by_reference: dict[int, dict[str, Any]] = {}
- for row in rows:
- for value in (row.get("rowId"), row.get("id")):
- reference = _as_int(value)
- if reference is not None:
- by_reference[reference] = row
- children: dict[int, list[dict[str, Any]]] = {}
- roots: list[dict[str, Any]] = []
- for row in rows:
- parent = by_reference.get(_as_int(row.get("parentId")))
- if parent is None or parent is row:
- row["parentId"] = None
- roots.append(row)
- continue
- row["parentId"] = parent.get("id")
- children.setdefault(id(parent), []).append(row)
- ordered: list[dict[str, Any]] = []
- visited: set[int] = set()
- def visit(row: dict[str, Any], depth: int, ancestry: set[int]) -> None:
- marker = id(row)
- if marker in visited:
- return
- if marker in ancestry:
- row["parentId"] = None
- depth = 0
- visited.add(marker)
- row["depth"] = depth
- ordered.append(row)
- next_ancestry = {*ancestry, marker}
- for child in sorted(children.get(marker, []), key=_paragraph_sort_key):
- visit(child, depth + 1, next_ancestry)
- for root in sorted(roots, key=_paragraph_sort_key):
- visit(root, 0, set())
- for row in sorted(rows, key=_paragraph_sort_key):
- if id(row) not in visited:
- row["parentId"] = None
- visit(row, 0, set())
- return ordered
- def _paragraph_sort_key(row: dict[str, Any]) -> tuple[Any, ...]:
- return (_sort_number(row.get("index")), _sort_number(row.get("id")))
- def _content_range(value: Any) -> list[str]:
- if not isinstance(value, dict):
- return [_display_value(value)] if value not in (None, "") else []
- tags: list[str] = []
- for key, item in value.items():
- if key == "标题":
- tags.append("标题")
- elif key == "图片" and isinstance(item, list):
- if not item:
- continue
- values = [str(entry) for entry in item]
- tags.append(f"图{values[0]}" if len(values) == 1 else f"图{values[0]}-{values[-1]}")
- elif key == "视频":
- tags.append(_display_value(item))
- elif key == "正文":
- body = "\n".join(str(entry) for entry in item) if isinstance(item, list) else _display_value(item)
- tags.append(f"正文: {body}")
- else:
- rendered = ",".join(str(entry) for entry in item) if isinstance(item, list) else _display_value(item)
- tags.append(f"{key}: {rendered}")
- return tags
- def _dimensions(value: Any) -> list[dict[str, Any]]:
- rows = value if isinstance(value, list) else [value] if isinstance(value, dict) else []
- return [
- {
- "type": row.get("维度类型") or row.get("dimension_type"),
- "name": row.get("维度") or row.get("dimension"),
- "value": row.get("原子点") or row.get("value"),
- **({"id": row.get("id")} if row.get("id") is not None else {}),
- }
- for row in rows
- if isinstance(row, dict)
- ]
- def _description_parts(value: str, element_names: dict[int, str]) -> list[dict[str, Any]]:
- parts: list[dict[str, Any]] = []
- cursor = 0
- for match in _ELEMENT_REFERENCE.finditer(value):
- if match.start() > cursor:
- parts.append({"type": "text", "text": value[cursor : match.start()]})
- element_id = int(match.group(2))
- name = element_names.get(element_id)
- parts.append(
- {
- "type": "element",
- "id": element_id,
- "name": name,
- "resolved": name is not None,
- "text": match.group(0),
- }
- )
- cursor = match.end()
- if name:
- duplicate = re.match(r"\s*" + re.escape(name), value[cursor:])
- if duplicate:
- cursor += duplicate.end()
- if cursor < len(value):
- parts.append({"type": "text", "text": value[cursor:]})
- return parts
- def _display_value(value: Any) -> str:
- if value is True:
- return "包含"
- if value is False:
- return "不包含"
- if value is None:
- return ""
- return str(value)
- def _as_int(value: Any) -> int | None:
- try:
- return int(value) if value is not None else None
- except (TypeError, ValueError):
- return None
- def _sort_number(value: Any) -> tuple[int, str]:
- number = _as_int(value)
- return (0, str(number).zfill(12)) if number is not None else (1, str(value or ""))
- def _unique_records(rows: list[dict[str, Any]], key: str) -> list[dict[str, Any]]:
- seen: set[Any] = set()
- result = []
- for row in rows:
- value = row.get(key)
- if value in seen:
- continue
- seen.add(value)
- result.append(row)
- return result
- def _branch_detail(script_build_id: int, branch: dict[str, Any], raw: Any, bundle: dict[str, Any]) -> dict[str, Any]:
- facts = _branch_facts(branch, bundle)
- return _payload(
- [
- _section("task", "实现任务", branch_task_text(branch.get("summary", {}).get("task"))),
- _section("data", "数据取舍", decisions_markdown([item.get("decision") for item in branch.get("dataDecisions") or []])),
- _section("output", "候选产出", branch.get("summary", {}).get("output")),
- ],
- {"scriptBuildId": script_build_id, "branch": raw},
- {
- "summary": branch.get("summary", {}).get("output"),
- "sections": [_section("facts", "领域事实", _domain_facts_markdown(facts))] if facts else [],
- "artifactRef": branch.get("output", {}).get("snapshotRef"),
- "exactness": _output_exactness(branch.get("output") or {}),
- }
- if branch.get("output", {}).get("node", {}).get("hasChanges")
- else None,
- )
- def _branch_task_detail(
- script_build_id: int,
- branch: dict[str, Any],
- raw: Any,
- bundle: dict[str, Any],
- *,
- round_index: int,
- branch_id: int,
- ) -> dict[str, Any]:
- task_event = next(
- (
- event
- for event in reversed(bundle.get("events") or [])
- if str(event.get("event_type") or "") == "agent_invoke"
- and str(event.get("event_name") or "") == "script_implementer"
- and int(event.get("round_index") or 0) == round_index
- and int(event.get("branch_id") or 0) == branch_id
- ),
- None,
- )
- event_input = (task_event or {}).get("inputData")
- event_task = event_input.get("task") if isinstance(event_input, dict) else None
- raw_task = (raw or {}).get("impl_task") if isinstance(raw, dict) else None
- complete_task = branch_task_text(
- event_task
- or raw_task
- or branch.get("summary", {}).get("task")
- )
- task_sections = branch_task_sections(
- event_task
- or raw_task
- or branch.get("summary", {}).get("task")
- )
- visual_roles = {
- "goal": ("summary", "key-result"),
- "materials": ("report", "evidence"),
- "avoid": ("report", "notice"),
- "context": ("report", "evidence"),
- }
- return _payload(
- [
- _section(
- f"task-{section['kind']}-{index}",
- section["title"],
- section["content"],
- visual_roles.get(section["kind"], ("default", "section"))[0],
- visual_role=visual_roles.get(section["kind"], ("default", "section"))[1],
- presentation="document" if section["kind"] in {"materials", "constraints", "avoid", "context"} else "prose",
- )
- for index, section in enumerate(task_sections, 1)
- ] or [_section("task-notes-1", "任务说明", complete_task)],
- {
- "scriptBuildId": script_build_id,
- "branch": raw,
- "taskEvent": task_event,
- "taskSource": (
- "script_build_event.inputData.task"
- if event_task
- else "script_build_branch.impl_task"
- if raw_task
- else "execution-view summary"
- ),
- },
- )
- def _branch_output_detail(script_build_id: int, branch: dict[str, Any], raw: Any, bundle: dict[str, Any]) -> dict[str, Any]:
- output = branch.get("output") or {}
- facts = _branch_facts(branch, bundle)
- changes = {
- "summary": output.get("summary"),
- "sections": [_section("facts", "已核实领域事实", _domain_facts_markdown(facts))] if facts else [],
- "artifactRef": output.get("snapshotRef"),
- "exactness": _output_exactness(output),
- }
- return _payload(
- [
- _section("output", "形成了什么", output.get("summary")),
- _section("assessment", "实现者说明", assessment_text((raw or {}).get("self_assessment")), "report"),
- ],
- {"scriptBuildId": script_build_id, "branch": raw, "output": output},
- changes if output.get("node", {}).get("hasChanges") else None,
- )
- def _retrieval_stage_detail(script_build_id: int, branch: dict[str, Any], raw: Any, bundle: dict[str, Any]) -> dict[str, Any]:
- stage = branch.get("retrievalStage") or {}
- direct = stage.get("directToolGroups") or []
- agents = stage.get("agentRuns") or []
- return _payload(
- [
- _section(
- "purpose",
- "取数目的",
- branch_task_text(branch.get("summary", {}).get("task"))
- or "为当前实现任务补齐可用的上游信息。",
- ),
- _section("mode", "执行方式", _retrieval_mode_text(stage.get("observedMode"))),
- _section("waves", "执行波次", _retrieval_waves_markdown(stage.get("waves") or [])),
- _section("direct", "工具取数", _direct_groups_markdown(direct)),
- _section("agents", "Agent 取数", _agent_runs_markdown(agents)),
- _section("result", "阶段结果与失败", _retrieval_stage_result(stage)),
- ],
- {
- "scriptBuildId": script_build_id,
- "branch": raw,
- "retrievalStage": stage,
- "note": "取数和初筛来自结构化运行事件;正式数据取舍来自独立业务表,不在本详情内反推。",
- },
- )
- def _node_detail(script_build_id: int, node: dict[str, Any], technical: Any) -> dict[str, Any]:
- fields = []
- primary = node.get("card", {}).get("primary")
- if primary:
- fields.append(_section("primary", primary.get("label") or node.get("title"), primary.get("value")))
- for line in node.get("card", {}).get("secondary") or []:
- fields.append(_section(str(line.get("key")), line.get("label") or "补充说明", line.get("value")))
- return _payload(fields, {"scriptBuildId": script_build_id, "record": technical})
- def _round_result_detail(
- script_build_id: int,
- round_: dict[str, Any],
- raw_round: dict[str, Any] | None,
- bundle: dict[str, Any],
- ) -> dict[str, Any]:
- result = round_.get("result") or {}
- branches = round_.get("branches") or []
- round_index = int(round_.get("roundIndex") or 0)
- facts = [
- item
- for item in bundle.get("domainInfo") or []
- if int(item.get("round_index") or 0) == round_index
- ]
- evaluation = round_.get("overallEvaluation") or {}
- next_step = next(
- (
- line.get("value")
- for line in (result.get("card") or {}).get("secondary") or []
- if line.get("key") == "next"
- ),
- None,
- )
- sections = [
- _section(
- "goal",
- "本轮目标完成情况",
- "\n".join(
- part
- for part in (
- business_text((raw_round or {}).get("goal")),
- f"收口状态:{result.get('status') or round_.get('state') or '未记录'}",
- )
- if part
- ),
- ),
- _section("outcomes", "方案处置", _branch_outcomes_markdown(branches)),
- _section("facts", "领域事实", _domain_facts_markdown(facts) or "本轮没有新增领域事实记录。"),
- _section(
- "evaluation",
- "整体评审",
- _node_value(evaluation) or "未找到明确的本轮整体评审结论。",
- ),
- _section(
- "changes",
- "主脚本变化",
- _round_content_changes(branches),
- ),
- _section("next", "下一步", next_step or "下一步未记录。"),
- ]
- changes = None
- if result.get("hasChanges"):
- changes = {
- "summary": _node_value(result),
- "sections": [
- _section("content", "内容方案", _round_content_changes(branches)),
- _section("domain", "领域信息", f"本轮独立保存 {len(facts)} 条领域事实。"),
- ],
- "artifactRef": "artifact:base:current",
- "exactness": "current-only",
- }
- return _payload(
- sections,
- {
- "scriptBuildId": script_build_id,
- "round": raw_round,
- "resultProjection": result,
- "note": "本轮主脚本历史快照无法完整还原,产物入口指向当前主脚本。",
- },
- changes,
- )
- def _final_result_detail(
- script_build_id: int, view: dict[str, Any], bundle: dict[str, Any]
- ) -> dict[str, Any]:
- final = view.get("finalResult") or {}
- record = bundle.get("record") or {}
- branches = final.get("branchCounts") or {}
- artifact = final.get("artifact") or {}
- status = str(final.get("status") or record.get("status") or "unknown")
- conclusion = {
- "success": "构建已完成。",
- "completed": "构建已完成。",
- "partial": "构建部分完成。",
- "failed": "构建失败。",
- "stopped": "构建已停止。",
- "running": "构建仍在进行。",
- }.get(status.lower(), f"构建状态:{status}。")
- summary_or_error = final.get("summary")
- if final.get("errorMessage"):
- summary_or_error = f"失败原因:{final['errorMessage']}"
- sections = [
- _section("conclusion", "构建结论", conclusion, "summary"),
- _section("summary", "构建摘要或失败原因", summary_or_error or "未另外记录构建摘要。"),
- _section(
- "statistics",
- "轮次与方案统计",
- (
- f"共 {int(final.get('roundCount') or 0)} 轮,"
- f"{int(branches.get('total') or 0)} 个方案;"
- f"采用 {int(branches.get('merged') or 0)},"
- f"暂存 {int(branches.get('parked') or 0)},"
- f"未采用 {int(branches.get('discarded') or 0)},"
- f"待处理 {int(branches.get('open') or 0)}。"
- ),
- ),
- _section(
- "artifact",
- "最终主脚本规模",
- (
- f"{int(artifact.get('paragraphCount') or 0)} 个段落、"
- f"{int(artifact.get('elementCount') or 0)} 个元素、"
- f"{int(artifact.get('linkCount') or 0)} 条关联。"
- ),
- ),
- _section(
- "version",
- "版本说明",
- "当前只能确认数据库保存的最新主脚本,不将它伪装成某一轮结束时的历史快照。",
- ),
- ]
- return _payload(
- sections,
- {
- "scriptBuildId": script_build_id,
- "table": "script_build_record",
- "record": record,
- "finalResultProjection": final,
- },
- {
- "summary": "打开当前主脚本。",
- "sections": [],
- "artifactRef": artifact.get("snapshotRef") or "artifact:base:current",
- "exactness": "current-only",
- },
- )
- def _find_decision_projection(
- view: dict[str, Any], detail_ref: str
- ) -> dict[str, Any] | None:
- candidates: list[dict[str, Any]] = []
- objective = view.get("objective") or {}
- if isinstance(objective.get("decision"), dict):
- candidates.append(objective["decision"])
- for round_ in view.get("rounds") or []:
- for node in (
- round_.get("goal"),
- (round_.get("plan") or {}).get("node"),
- round_.get("overallEvaluation"),
- ):
- if isinstance(node, dict) and isinstance(node.get("decision"), dict):
- candidates.append(node["decision"])
- for branch in round_.get("branches") or []:
- for item in branch.get("dataDecisions") or []:
- projection = item.get("decisionProjection")
- if isinstance(projection, dict):
- candidates.append(projection)
- output_node = (branch.get("output") or {}).get("node") or {}
- if isinstance(output_node.get("decision"), dict):
- candidates.append(output_node["decision"])
- for batch in round_.get("convergenceBatches") or []:
- review = batch.get("review") or {}
- decision = batch.get("decision") or {}
- if isinstance(review.get("decisionProjection"), dict):
- candidates.append(review["decisionProjection"])
- if isinstance(decision.get("decisionProjection"), dict):
- candidates.append(decision["decisionProjection"])
- return next(
- (
- item
- for item in candidates
- if detail_ref in {item.get("id"), item.get("detailRef")}
- ),
- None,
- )
- def _find_missing_convergence(
- view: dict[str, Any], detail_ref: str
- ) -> tuple[dict[str, Any], dict[str, Any]] | None:
- for round_ in view.get("rounds") or []:
- for batch in round_.get("convergenceBatches") or []:
- for key in ("missingReview", "missingDecision"):
- node = batch.get(key)
- if isinstance(node, dict) and detail_ref in {
- node.get("id"),
- node.get("detailRef"),
- }:
- return node, batch
- return None
- def _decision_detail_payload(
- script_build_id: int,
- decision: dict[str, Any],
- bundle: dict[str, Any],
- activity_id: str,
- event_detail: dict[str, Any] | None = None,
- ) -> dict[str, Any]:
- detail = decision.get("detail") if isinstance(decision.get("detail"), dict) else {}
- blocks = [
- block
- for block in detail.get("blocks") or []
- if isinstance(block, dict)
- ]
- for notice in decision.get("notices") or []:
- if not isinstance(notice, dict) or not notice.get("message"):
- continue
- blocks.append(
- {
- "type": "notice",
- "level": "warning" if "missing" in str(notice.get("code")) else "info",
- "title": "记录说明",
- "value": notice["message"],
- "visualRole": "notice",
- "presentation": "prose",
- }
- )
- event_refs = [
- ref
- for ref in [
- *(decision.get("eventRefs") or []),
- *(decision.get("technicalRefs") or []),
- ]
- if isinstance(ref, str) and ref.startswith("event:")
- ]
- event_refs = list(dict.fromkeys(event_refs))
- technical: dict[str, Any] = {
- "source": {
- "scriptBuildId": script_build_id,
- "detailRef": activity_id,
- "technicalRefs": event_refs,
- },
- "association": {
- "completeness": decision.get("completeness"),
- "notices": decision.get("notices") or [],
- },
- "rawDecisionProjection": decision,
- "rawBusinessRecord": _decision_raw_record(bundle, activity_id),
- }
- if event_refs:
- technical["runtimeEvents"] = _events_for_ids(
- bundle, [_suffix_int(ref) for ref in event_refs]
- )
- if event_detail:
- technical.update(_event_technical_groups(event_detail))
- payload: dict[str, Any] = {
- "detailKind": "agent-decision",
- "decisionType": decision.get("decisionType"),
- "actor": decision.get("actor"),
- "authority": decision.get("authority"),
- "question": decision.get("question"),
- "promptRef": decision.get("promptRef"),
- "blocks": sanitize(blocks, max_text=None),
- "technical": sanitize(technical, max_text=None),
- }
- artifact_ref = decision.get("artifactRef")
- if artifact_ref:
- payload["changes"] = {
- "summary": (decision.get("body") or {}).get("output")
- or "已形成可查看的候选产出。",
- "sections": [],
- "artifactRef": artifact_ref,
- "exactness": "historical-snapshot",
- }
- return payload
- def _event_technical_groups(event: dict[str, Any]) -> dict[str, Any]:
- """Split a lazily loaded event body into the Inspector's technical groups.
- The execution bundle only carries bounded previews. Once a user opens an
- event-backed decision, the full (sanitized) body belongs here rather than
- being silently replaced by those previews.
- """
- metadata = {
- key: value
- for key, value in event.items()
- if key not in {"input", "output", "duration_ms"}
- }
- groups: dict[str, Any] = {
- "input": event.get("input"),
- "output": event.get("output"),
- "rawEvent": metadata,
- }
- if event.get("duration_ms") is not None:
- groups["cost"] = {"durationMs": event.get("duration_ms")}
- return groups
- def _decision_raw_record(bundle: dict[str, Any], activity_id: str) -> Any:
- if activity_id.startswith("data-decision:"):
- return _find_by_id(bundle.get("dataDecisions") or [], _suffix_int(activity_id))
- if activity_id.startswith("multipath-decision:"):
- return _find_by_id(
- bundle.get("multipathDecisions") or [], _suffix_int(activity_id)
- )
- if activity_id.startswith("event:"):
- return _event_by_id(bundle, _suffix_int(activity_id))
- if activity_id.startswith("creative:"):
- event_id = _suffix_int(activity_id)
- event = _event_by_id(bundle, event_id)
- branch_id = int((event or {}).get("branch_id") or 0)
- branch = next(
- (
- item
- for item in bundle.get("branches") or []
- if int(item.get("branch_id") or 0) == branch_id
- ),
- None,
- )
- return {
- "anchorEvent": event,
- "candidateSnapshot": (branch or {}).get("candidate_snapshot"),
- }
- if activity_id == "run:objective":
- return bundle.get("record")
- round_index, _, role = _activity_parts(activity_id)
- if role in {"goal", "plan"}:
- return next(
- (
- item
- for item in bundle.get("rounds") or []
- if int(item.get("round_index") or 0) == int(round_index or 0)
- ),
- None,
- )
- return None
- def _payload(sections: list[dict[str, Any] | None], technical: Any, changes: dict[str, Any] | None = None) -> dict[str, Any]:
- payload: dict[str, Any] = {
- "businessSections": [item for item in sections if item],
- "technical": sanitize(technical, max_text=None),
- }
- if changes:
- changes["sections"] = [item for item in changes.get("sections", []) if item]
- payload["changes"] = sanitize(changes, max_text=None)
- return payload
- def _section(
- section_id: str,
- title: str,
- content: Any,
- variant: str = "default",
- *,
- visual_role: str | None = None,
- presentation: str = "prose",
- collapsible: bool = False,
- default_open: bool = False,
- ) -> dict[str, Any] | None:
- if content is None or content == "" or content == []:
- return None
- if not isinstance(content, str):
- return None
- content = business_text(content)
- if not content:
- return None
- return {
- "id": section_id,
- "title": title,
- "content": sanitize(content, max_text=None),
- "variant": variant,
- "visualRole": visual_role or ("key-result" if variant == "summary" else "section"),
- "presentation": presentation,
- "collapsible": collapsible,
- "defaultOpen": default_open,
- }
- def _items_section(
- section_id: str,
- title: str,
- items: list[dict[str, Any] | None],
- *,
- fallback: Any = None,
- variant: str = "default",
- visual_role: str | None = None,
- collapsible: bool = False,
- default_open: bool = False,
- ) -> dict[str, Any] | None:
- values = [item for item in items if item]
- if not values and fallback in (None, "", []):
- return None
- content = "\n".join(
- f"{item.get('label')}:{item.get('value')}" for item in values
- ) or str(fallback)
- section = _section(
- section_id,
- title,
- content,
- variant,
- visual_role=visual_role,
- presentation="list",
- collapsible=collapsible,
- default_open=default_open,
- )
- if section is not None and values:
- section["items"] = sanitize(values, max_text=None)
- return section
- def _detail_item(label: Any, value: Any) -> dict[str, Any] | None:
- if value in (None, "", []):
- return None
- return {
- "label": sanitize(business_text(str(label)), max_text=None),
- "value": sanitize(business_text(str(value)), max_text=None),
- }
- def _activity_parts(activity_id: str) -> tuple[int | None, int | None, str | None]:
- parts = activity_id.split(":")
- if len(parts) < 2 or parts[0] != "round":
- return None, None, None
- try:
- round_index = int(parts[1])
- except ValueError:
- return None, None, None
- if len(parts) >= 4 and parts[2] == "branch":
- try:
- branch_id = int(parts[3])
- except ValueError:
- return round_index, None, None
- return round_index, branch_id, parts[4] if len(parts) > 4 else None
- return round_index, None, parts[2] if len(parts) > 2 else None
- def _round_node(round_: dict[str, Any], role: str) -> dict[str, Any] | None:
- if role == "goal":
- return round_.get("goal")
- if role == "plan":
- return (round_.get("plan") or {}).get("node")
- if role == "result":
- return round_.get("result")
- if role == "evaluation":
- return round_.get("overallEvaluation")
- return None
- def _branch_node(branch: dict[str, Any], role: str) -> dict[str, Any] | None:
- if role == "task":
- return branch.get("task")
- if role == "output":
- return branch.get("output", {}).get("node")
- return None
- def _convergence_markdown(batches: list[dict[str, Any]]) -> str:
- if not batches:
- return "未找到候选评审或主 Agent 多路决策记录。"
- rows: list[str] = []
- for index, batch in enumerate(batches, 1):
- review = batch.get("review") or {}
- decision = batch.get("decision") or {}
- branch_ids = batch.get("branchIds") or []
- rows.append(
- f"### 第 {index} 批 · "
- + ("、".join(f"方案 {value}" for value in branch_ids) or "方案范围未记录")
- )
- rows.append(
- f"**多方案评审:** {review.get('recommendation') or review.get('comparison') or review.get('conclusion') or '评审结论未记录'}"
- )
- rows.append(
- f"**主 Agent 决策:** {business_text(decision.get('decision')) or '决策尚未记录'}"
- )
- return "\n\n".join(rows)
- def _find_retrieval_item(view: dict[str, Any], collection: str, item_id: str) -> dict[str, Any] | None:
- for round_ in view.get("rounds") or []:
- for branch in round_.get("branches") or []:
- for item in (branch.get("retrievalStage") or {}).get(collection) or []:
- if item.get("id") == item_id:
- return item
- return None
- def _event_by_id(bundle: dict[str, Any], event_id: Any) -> dict[str, Any] | None:
- return next(
- (item for item in bundle.get("events") or [] if int(item.get("id") or 0) == int(event_id or 0)),
- None,
- )
- def _events_for_ids(bundle: dict[str, Any], event_ids: list[Any]) -> list[dict[str, Any]]:
- wanted = {int(value) for value in event_ids if value is not None}
- return [item for item in bundle.get("events") or [] if int(item.get("id") or 0) in wanted]
- def _event_nested_value(
- event: dict[str, Any] | None, side: str, key: str
- ) -> Any:
- if not isinstance(event, dict):
- return None
- aliases = (
- ("inputData", "input_data")
- if side == "input"
- else ("agentOutputData", "outputData", "output_data")
- )
- for alias in aliases:
- value = event.get(alias)
- if isinstance(value, dict) and value.get(key) not in (None, ""):
- return value.get(key)
- wrapped = event.get(side)
- if isinstance(wrapped, dict):
- content = wrapped.get("content")
- if isinstance(content, dict):
- return content.get(key)
- if key == "summary" and isinstance(content, str):
- return content
- return None
- def _direct_sources_markdown(group: dict[str, Any]) -> str:
- rows = group.get("sources") or []
- return "\n".join(
- f"- {item.get('businessLabel') or '相关信息'}:{int(item.get('callCount') or 0)} 次"
- for item in rows
- ) or "未记录具体读取项"
- def _direct_result_markdown(calls: list[dict[str, Any]]) -> str:
- success = sum(1 for item in calls if item.get("status") == "success")
- failure = sum(1 for item in calls if item.get("status") == "failure")
- running = sum(1 for item in calls if item.get("status") == "running")
- interrupted = sum(1 for item in calls if item.get("status") == "interrupted")
- return f"共 {len(calls)} 次读取:{success} 次完成,{failure} 次失败,{running} 次进行中,{interrupted} 次因构建中断。"
- def _agent_query_markdown(run: dict[str, Any]) -> str:
- summary = run.get("querySummary") or {}
- total = int(summary.get("total") or 0)
- if total == 0 and not (run.get("attempts") or []):
- return "Agent 已完成,没有发起查询。"
- header = (
- f"共 {total} 次查询:"
- f"{int(summary.get('hit') or 0)} 次命中,"
- f"{int(summary.get('empty') or 0)} 次无结果,"
- f"{int(summary.get('failure') or 0)} 次失败,"
- f"{int(summary.get('interrupted') or 0)} 次因构建中断。"
- )
- rows = []
- for index, attempt in enumerate(run.get("attempts") or [], 1):
- query = attempt.get("queryLabel") or attempt.get("queryPreview") or attempt.get("businessLabel") or "查询"
- label = {"hit": "命中", "empty": "无结果", "failure": "失败", "running": "进行中", "interrupted": "构建中断", "unknown": "结果数不明"}.get(attempt.get("status"), "结果数不明")
- count = attempt.get("resultCount")
- suffix = f"· {count} 条" if isinstance(count, int) and count > 0 else f"· {label}"
- rows.append(f"{index:02d}. {query} {suffix}")
- return "\n".join([header, *rows])
- def _agent_hit_markdown(run: dict[str, Any]) -> str:
- attempts = run.get("attempts") or []
- hits = [item for item in attempts if item.get("status") == "hit"]
- empty = [item for item in attempts if item.get("status") == "empty"]
- failures = [
- item
- for item in attempts
- if item.get("status") in {"failure", "interrupted"}
- ]
- rows = [
- f"- {item.get('queryLabel') or '查询'}:{int(item.get('resultCount') or 0)} 条"
- for item in hits
- ]
- rows.append(f"成功命中 {len(hits)} 次,成功为空 {len(empty)} 次,技术失败或中断 {len(failures)} 次。")
- return "\n".join(rows)
- def _screening_fallback(state: Any) -> str:
- return {"running": "Agent 仍在整理查询结果。", "missing": "未找到 Agent 的初筛整理记录。"}.get(str(state), "初筛整理未记录。")
- def _retrieval_mode_text(mode: Any) -> str:
- return {
- "single": "本次只有一个取数操作。",
- "sequential": "各项取数依次执行。",
- "parallel": "各项取数在同一时间段并行执行。",
- "mixed": "本次同时存在并行取数和后续取数。",
- "unknown": "运行时间记录不足,无法确认执行先后。",
- }.get(str(mode), "执行方式未记录。")
- def _retrieval_waves_markdown(waves: list[dict[str, Any]]) -> str:
- if not waves:
- return "运行时间或并发信息不足,无法安全还原执行波次。"
- rows = []
- for index, wave in enumerate(waves, 1):
- operations = wave.get("operations") or wave.get("operationIds") or []
- rows.append(
- f"- 第 {index} 波:{len(operations)} 个取数操作"
- )
- return "\n".join(rows)
- def _retrieval_stage_result(stage: dict[str, Any]) -> str:
- direct_calls = [
- call
- for group in stage.get("directToolGroups") or []
- for call in group.get("calls") or []
- ]
- attempts = [
- attempt
- for run in stage.get("agentRuns") or []
- for attempt in run.get("attempts") or []
- ]
- failures = sum(
- 1
- for item in [*direct_calls, *attempts]
- if item.get("status") in {"failure", "interrupted"}
- )
- hits = sum(1 for item in attempts if item.get("status") == "hit")
- empty = sum(1 for item in attempts if item.get("status") == "empty")
- return (
- f"阶段状态:{stage.get('status') or '未记录'}。"
- f"工具读取 {len(direct_calls)} 次,Agent 查询 {len(attempts)} 次;"
- f"命中 {hits} 次,成功为空 {empty} 次,失败或中断 {failures} 次。"
- )
- def _direct_groups_markdown(groups: list[dict[str, Any]]) -> str:
- if not groups:
- return "本次未记录实现 Agent 直接读取工具。"
- return "\n".join(
- f"- 第 {index} 组:{'、'.join(item.get('businessLabel') or '相关信息' for item in group.get('sources') or [])}({int(group.get('callCount') or 0)} 次)"
- for index, group in enumerate(groups, 1)
- )
- def _agent_runs_markdown(runs: list[dict[str, Any]]) -> str:
- if not runs:
- return "本次未记录委派取数 Agent。"
- return "\n".join(
- f"- {item.get('businessLabel') or '取数 Agent'}:{int((item.get('querySummary') or {}).get('total') or 0)} 次查询,初筛{'已记录' if (item.get('screening') or {}).get('state') == 'available' else '未完整记录'}"
- for item in runs
- )
- def _find_round(view: dict[str, Any], round_index: int | None) -> dict[str, Any] | None:
- return next((item for item in view.get("rounds") or [] if int(item.get("roundIndex") or 0) == int(round_index or 0)), None)
- def _find_by_id(rows: list[dict[str, Any]], record_id: int) -> dict[str, Any] | None:
- return next((item for item in rows if int(item.get("id") or 0) == record_id), None)
- def _suffix_int(value: str) -> int:
- try:
- return int(value.rsplit(":", 1)[1])
- except (IndexError, ValueError) as exc:
- raise KeyError(value) from exc
- def _node_value(node: dict[str, Any] | None) -> str | None:
- return ((node or {}).get("card") or {}).get("primary", {}).get("value")
- def _plan_text(plan: dict[str, Any]) -> str:
- paths = plan.get("paths") or []
- parts = [f"方式:{plan.get('mode') or '未记录'}", f"当前保存 {len(paths)} 个方案"]
- if plan.get("note"):
- parts.append(f"说明:{plan['note']}")
- revisions = int(plan.get("runtimeRevisionCount") or 0)
- if revisions > 1:
- parts.append(f"运行事件中找到 {revisions} 次规划记录;历史版本只在技术详情中查看。")
- return "\n".join(parts)
- def _round_content_changes(branches: list[dict[str, Any]]) -> str:
- merged = [item for item in branches if item.get("pathType") != "领域信息" and item.get("status") == "merged"]
- return f"确认采用 {len(merged)} 个内容方案;无法据此还原本轮结束时的完整主脚本快照。"
- def _branch_outcomes_markdown(branches: list[dict[str, Any]]) -> str:
- if not branches:
- return "本轮没有可展示的方案处置记录。"
- rows = []
- for item in branches:
- outcome = item.get("outcome") or {}
- line = (
- f"- 方案 {item.get('branchId')}:"
- f"{outcome.get('label') or item.get('status') or '状态未记录'}"
- )
- if outcome.get("reasoning"):
- line += f"。{business_text(outcome.get('reasoning'))}"
- rows.append(line)
- return "\n".join(rows)
- def _round_domain_changes(branches: list[dict[str, Any]]) -> str:
- count = sum(int(item.get("output", {}).get("factCount") or 0) for item in branches if item.get("pathType") == "领域信息")
- return f"新增 {count} 条独立保存的领域事实。"
- def _branch_facts(branch: dict[str, Any], bundle: dict[str, Any]) -> list[dict[str, Any]]:
- refs = set(branch.get("output", {}).get("factRefs") or [])
- return [item for item in bundle.get("domainInfo") or [] if f"domain-info:{item.get('id')}" in refs]
- def _output_exactness(output: dict[str, Any]) -> str:
- if output.get("type") == "domain-info":
- return "exact"
- historical = output.get("accuracy", {}).get("historical")
- return "historical-snapshot" if historical == "exact" else "current-only" if output.get("snapshotRef") else "unknown"
- def _artifact_exactness(artifact: dict[str, Any]) -> str:
- return "historical-snapshot" if artifact.get("historicalAccuracy") == "exact" else "current-only"
- def _domain_facts_markdown(rows: list[dict[str, Any]]) -> str:
- values = [business_text(row.get("content")) for row in rows]
- return "\n".join(f"- {value}" for value in values if value)
- def _source_value(value: Any) -> str:
- if isinstance(value, str):
- return value
- if isinstance(value, list):
- return source_markdown(value)
- if isinstance(value, dict):
- return source_markdown([value]) or business_text(value.get("url") or value.get("name"))
- return ""
|