| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896 |
- from __future__ import annotations
- import re
- from typing import Any, Iterable, Mapping
- from .business_detail_text import business_text
- _SUCCESS_STATUSES = {"ok", "success", "succeeded", "completed", "complete"}
- _DECISION_BASIS_TITLE = "根据以下信息做出的决策"
- _RELATIONS = {
- "direct-read": "read-by-actor",
- "read-by-actor": "read-by-actor",
- "returned-report": "returned-to-actor",
- "returned-to-actor": "returned-to-actor",
- "persisted-record": "persisted-before-decision",
- "persisted-before-decision": "persisted-before-decision",
- "standing-constraint": "standing-constraint",
- }
- class AgentDecisionProjector:
- """Create the V8 decision union from already-associated, plain records.
- The projector deliberately does not scan event timelines or infer causal
- links. Callers must first establish ownership/association, then pass those
- facts here. In particular an observed read remains a read unless its input
- explicitly records ``decisionUse=explicit-basis``.
- """
- def direction(self, payload: Mapping[str, Any]) -> dict[str, Any]:
- subtype = _machine(payload.get("subtype")) or "direction"
- actor = _actor(payload.get("actor"), default_role="main", default_label="主 Agent")
- decision_items = _strings(
- payload.get("decisionItems") or payload.get("decisions")
- )
- reasoning = _text(payload.get("reasoning") or payload.get("explicitReasoning"))
- constraints = _strings(payload.get("constraints"))
- inputs = _inputs(payload.get("inputs"))
- primary = decision_items[0] if decision_items else _text(payload.get("decision"))
- secondary = []
- if inputs:
- secondary.append(_card_line("inputs", _DECISION_BASIS_TITLE, _input_labels(inputs)))
- if constraints:
- secondary.append(_card_line("constraints", "关键约束", _join(constraints, 2)))
- if reasoning:
- secondary.append(_card_line("reasoning", "决策理由", reasoning))
- body = {
- "type": "direction",
- "decisionItems": decision_items,
- "reasoning": reasoning,
- "constraints": constraints,
- }
- if subtype == "implementation-plan":
- implementation_plan = _implementation_plan(payload.get("implementationPlan"), reasoning)
- body["implementationPlan"] = implementation_plan
- blocks = [
- _implementation_plan_block(implementation_plan),
- _items_block(_DECISION_BASIS_TITLE, [_input_business_item(item) for item in inputs], visual_role="evidence"),
- _items_block("关键约束", constraints),
- ]
- elif subtype == "objective" and _source_text(payload.get("sourceDocument")):
- source_document = _source_text(payload.get("sourceDocument"))
- body["sourceDocument"] = source_document
- blocks = [
- _source_document_block(
- "当前保存的创作方向",
- source_document,
- ),
- _items_block(
- _DECISION_BASIS_TITLE,
- [_input_business_item(item) for item in inputs],
- visual_role="evidence",
- ),
- ]
- elif subtype == "round-goal" and _source_text(payload.get("sourceDocument")):
- source_document = _source_text(payload.get("sourceDocument"))
- body["sourceDocument"] = source_document
- blocks = [
- _source_document_block(
- "本轮目标构成",
- source_document,
- ),
- _items_block(
- _DECISION_BASIS_TITLE,
- [_input_business_item(item) for item in inputs],
- visual_role="evidence",
- ),
- _summary_block("目标来源", reasoning, visual_role="reason"),
- ]
- else:
- blocks = [
- _decision_items_block("最终方向", decision_items or ([primary] if primary else []), visual_role="key-result"),
- _items_block(_DECISION_BASIS_TITLE, [_input_business_item(item) for item in inputs], visual_role="evidence"),
- _items_block("关键约束", constraints),
- _summary_block("明确理由", reasoning, visual_role="reason"),
- ]
- return _decision(
- payload,
- decision_type="direction",
- subtype=subtype,
- actor=actor,
- authority="final",
- question=_text(payload.get("question")) or _direction_question(subtype),
- inputs=inputs,
- body=body,
- primary_label=_text(payload.get("primaryLabel")) or "最终方向",
- primary=primary,
- secondary=secondary,
- blocks=blocks,
- )
- def data_tradeoff(self, row: Mapping[str, Any]) -> dict[str, Any]:
- inputs = _inputs(row.get("inputs") or _source_inputs(row.get("sources")))
- decision_text = _text(row.get("decision"))
- reasoning = _text(row.get("reasoning"))
- scope_items = _strings(row.get("scopeItems"))
- body = {
- "type": "tradeoff",
- "scopeItems": scope_items,
- "decision": decision_text,
- "selected": _strings(row.get("selected")),
- "combined": _strings(row.get("combined")),
- "parked": _strings(row.get("parked")),
- "rejected": _strings(row.get("rejected")),
- "reasoning": reasoning,
- }
- secondary = []
- if inputs:
- secondary.append(_card_line("scope", "参与判断", f"{len(inputs)} 类信息"))
- if reasoning:
- secondary.append(_card_line("reasoning", "理由", reasoning))
- return _decision(
- row,
- decision_type="tradeoff",
- subtype="data-tradeoff",
- actor=_actor(
- row.get("actor"),
- default_role="implementer",
- default_label="实现 Agent",
- ),
- authority="implementation-scope",
- question=_text(row.get("question")) or "哪些信息用于当前实现方案?",
- inputs=inputs,
- body=body,
- primary_label="取舍结论",
- primary=decision_text,
- secondary=secondary,
- blocks=[
- _items_block("取舍对象", scope_items),
- _items_block("参与判断", [_input_business_item(item) for item in inputs], visual_role="evidence", collapsible=True),
- _summary_block("明确取舍", decision_text, visual_role="key-result"),
- _summary_block("理由", reasoning, visual_role="reason"),
- ],
- )
- def multipath_tradeoff(self, row: Mapping[str, Any]) -> dict[str, Any]:
- branch_ids = _unique_values(row.get("branchIds") or row.get("branch_ids"))
- inputs = _inputs(row.get("inputs"))
- decision_text = _text(row.get("decision"))
- reasoning = _text(row.get("reasoning"))
- selected = _strings(row.get("selected"))
- rejected = _strings(row.get("rejected"))
- body = {
- "type": "tradeoff",
- "scopeItems": _strings(row.get("scopeItems")),
- "decision": decision_text,
- "selected": selected,
- "combined": _strings(row.get("combined")),
- "parked": _strings(row.get("parked")),
- "rejected": rejected,
- "reasoning": reasoning,
- # Identity is useful to flow wiring but is not rendered as business copy.
- "branchIds": branch_ids,
- "reviewComparison": row.get("reviewComparison"),
- }
- secondary = []
- if branch_ids:
- secondary.append(
- _card_line("scope", "取舍范围", f"比较 {len(branch_ids)} 个候选方案")
- )
- if reasoning:
- secondary.append(_card_line("reasoning", "决策理由", reasoning))
- if row.get("reviewComparison"):
- secondary.append(_card_line("review", "评审对照", "可在详情中查看"))
- return _decision(
- row,
- decision_type="tradeoff",
- subtype="multipath-tradeoff",
- actor=_actor(row.get("actor"), default_role="main", default_label="主 Agent"),
- authority="final",
- question=_text(row.get("question")) or "多个候选方案最终如何处理?",
- inputs=inputs,
- body=body,
- primary_label="最终决定",
- primary=decision_text,
- secondary=secondary,
- blocks=[
- _summary_block(
- "取舍对象",
- f"{len(branch_ids)} 个候选方案" if branch_ids else None,
- ),
- _items_block("参与判断", [_input_business_item(item) for item in inputs], visual_role="evidence", collapsible=True),
- _summary_block("最终决定", decision_text, visual_role="key-result"),
- _summary_block("决策理由", reasoning, visual_role="reason"),
- _comparison_block(row.get("reviewComparison")),
- ],
- )
- def evaluation(self, payload: Mapping[str, Any]) -> dict[str, Any]:
- subtype = _machine(payload.get("subtype")) or "overall-evaluation"
- is_multipath = subtype == "multipath-evaluation"
- inputs = _inputs(payload.get("inputs"))
- conclusion = _text(payload.get("conclusion"))
- recommendation = _text(payload.get("recommendation"))
- subjects = _strings(payload.get("subjects"))
- criteria = _strings(payload.get("criteria"))
- item_conclusions = _business_dicts(payload.get("itemConclusions"))
- achievements = _strings(payload.get("achievements"))
- problems = _business_dicts(payload.get("problems"))
- branch_evaluations = _mapping_list(payload.get("branchEvaluations"))
- comparison_rows = _mapping_list(payload.get("comparisonRows"))
- body = {
- "type": "evaluation",
- "subjects": subjects,
- "criteria": criteria,
- "itemConclusions": item_conclusions,
- "achievements": achievements,
- "problems": problems,
- "branchEvaluations": branch_evaluations,
- "comparisonRows": comparison_rows,
- "conclusion": conclusion,
- "recommendation": recommendation,
- "nextGoal": _text(payload.get("nextGoal")),
- }
- secondary = []
- if achievements:
- secondary.append(_card_line("achievement", "已达成", _join(achievements, 2)))
- if problems:
- secondary.append(
- _card_line("problems", "需要关注", _problem_summary(problems), "warning")
- )
- if recommendation:
- secondary.append(_card_line("recommendation", "评审建议", recommendation))
- primary = conclusion or _item_conclusion_summary(item_conclusions) or recommendation
- if is_multipath and branch_evaluations:
- detail_blocks = [
- _evaluation_branches_block(branch_evaluations),
- _evaluation_matrix_block(comparison_rows) or _items_block("评审标准", criteria),
- _summary_block("评审建议", recommendation),
- ]
- else:
- detail_blocks = [
- _items_block("评审对象", subjects),
- _items_block("评审标准", criteria),
- _items_block("逐项结论", item_conclusions),
- _items_block("已达成", achievements),
- _items_block("问题", problems),
- _summary_block("总结论", conclusion, visual_role="key-result"),
- _summary_block("评审建议", recommendation),
- ]
- return _decision(
- payload,
- decision_type="evaluation",
- subtype=subtype,
- actor=_actor(
- payload.get("actor"),
- default_role=("multipath-evaluator" if is_multipath else "overall-evaluator"),
- default_label=("多方案评审 Agent" if is_multipath else "整体评审 Agent"),
- ),
- authority="recommendation",
- question=_text(payload.get("question"))
- or ("哪些候选方案更值得采用?" if is_multipath else "当前主脚本是否达到目标?"),
- inputs=inputs,
- body=body,
- primary_label="评审结论",
- primary=primary,
- secondary=secondary,
- blocks=detail_blocks,
- )
- def creative(self, payload: Mapping[str, Any]) -> dict[str, Any] | None:
- """Project an implementer creative decision only from a safe event link.
- An artifact reference may be attached to a real creative record, but it
- is never sufficient to create that record. This avoids inferring the
- implementer's plan from the eventual candidate script.
- """
- if payload.get("safeLink") is not True:
- return None
- event = payload.get("event")
- event = event if isinstance(event, Mapping) else payload
- if not _is_successful_think_and_plan(event):
- return None
- raw_input = event.get("inputData") or event.get("input")
- if not isinstance(raw_input, Mapping):
- return None
- thought = _text(
- payload.get("reasoning")
- or raw_input.get("thought")
- or raw_input.get("thought_summary")
- )
- steps = _creative_steps(payload.get("steps"))
- actions = _strings(payload.get("actions"))
- if not steps:
- fallback_action = _text(raw_input.get("action"))
- fallback_plan = _source_text(raw_input.get("plan"))
- if fallback_action or fallback_plan or thought:
- steps = [{
- "stepIndex": 1,
- "action": fallback_action or "创作处理",
- "summary": _text(raw_input.get("thought_summary")),
- "plan": fallback_plan,
- "reasoning": _source_text(raw_input.get("thought")),
- }]
- if not actions:
- actions = [str(step["action"]) for step in steps if step.get("action")]
- if not any((thought, actions, steps)):
- return None
- task = _text(payload.get("task"))
- explicit_basis = _strings(payload.get("basis"))
- uncertainties = _strings(payload.get("uncertainties"))
- body = {
- "type": "creative",
- "task": task,
- "basis": explicit_basis,
- "actions": actions,
- "steps": steps,
- "reasoning": thought,
- "output": _text(payload.get("output")),
- "uncertainties": uncertainties,
- }
- secondary = []
- projected_payload = dict(payload)
- projected_payload.setdefault("id", f"creative-event:{event.get('id')}")
- return _decision(
- projected_payload,
- decision_type="creative",
- subtype="creative-handling",
- actor=_actor(
- payload.get("actor"),
- default_role="implementer",
- default_label="实现 Agent",
- ),
- authority="implementation-scope",
- question=_text(payload.get("question")) or "当前实现方案如何形成候选产出?",
- inputs=_inputs(payload.get("inputs")),
- body=body,
- primary_label="创作处理",
- primary=actions[0] if actions else thought,
- secondary=secondary,
- blocks=[
- _items_block("明确依据", explicit_basis, visual_role="evidence", collapsible=True),
- _creative_process_block(steps) or _items_block("创作处理", actions),
- _summary_block("产出的候选表", body["output"], visual_role="key-result"),
- _items_block("存疑项", uncertainties, visual_role="notice"),
- ],
- )
- def _decision(
- payload: Mapping[str, Any],
- *,
- decision_type: str,
- subtype: str,
- actor: dict[str, str],
- authority: str,
- question: str,
- inputs: list[dict[str, Any]],
- body: dict[str, Any],
- primary_label: str,
- primary: str | None,
- secondary: list[dict[str, Any]],
- blocks: list[dict[str, Any] | None],
- ) -> dict[str, Any]:
- completeness = _completeness(payload.get("completeness"), primary)
- notices = _notices(payload.get("notices"))
- if not primary and not any(item.get("code") == "record-missing" for item in notices):
- notices.append({"code": "record-missing", "message": "没有找到结构化决策结论。"})
- decision_id = _machine(payload.get("id") or payload.get("detailRef")) or f"{subtype}:unknown"
- detail_ref = _machine(payload.get("detailRef")) or decision_id
- result = {
- "id": decision_id,
- "semanticKind": "decision",
- "decisionType": decision_type,
- "subtype": subtype,
- "actor": actor,
- "authority": authority,
- "question": question,
- "inputs": inputs,
- "body": body,
- "card": {
- "primary": {
- "label": primary_label,
- "value": primary or "决策结论未记录",
- },
- "secondary": [item for item in secondary if item.get("value")][:3],
- },
- "detailRef": detail_ref,
- "promptRef": _machine(payload.get("promptRef")),
- "artifactRef": _machine(payload.get("artifactRef")),
- "completeness": completeness,
- "notices": notices,
- "detail": {
- "detailKind": "agent-decision",
- "decisionType": decision_type,
- "actor": actor,
- "authority": authority,
- "question": question,
- "blocks": [block for block in blocks if block],
- },
- }
- return result
- def _inputs(value: Any) -> list[dict[str, Any]]:
- if not isinstance(value, Iterable) or isinstance(value, (str, bytes, Mapping)):
- return []
- result: list[dict[str, Any]] = []
- for raw in value:
- if not isinstance(raw, Mapping):
- continue
- observed = _RELATIONS.get(
- _text(raw.get("observedRelation") or raw.get("relation")) or "",
- "persisted-before-decision",
- )
- explicit_use = _machine(raw.get("decisionUse"))
- decision_use = explicit_use if explicit_use in {"explicit-basis", "not-recorded"} else "not-recorded"
- if not (raw.get("observedRelation") or raw.get("relation")):
- continue
- label = _text(raw.get("label") or raw.get("name") or raw.get("type"))
- if not label:
- continue
- result.append(
- {
- "label": label,
- "summary": _text(raw.get("summary")),
- "observedRelation": observed,
- "decisionUse": decision_use,
- "detailRef": _text(raw.get("detailRef")),
- }
- )
- return result
- def _source_inputs(value: Any) -> list[dict[str, Any]]:
- if not isinstance(value, list):
- return []
- result = []
- for index, item in enumerate(value, 1):
- if isinstance(item, Mapping):
- label = _text(
- item.get("label")
- or item.get("data_type")
- or item.get("source_type")
- or item.get("type")
- )
- summary = _text(
- item.get("summary")
- or item.get("data_content")
- or item.get("title")
- or item.get("name")
- )
- explicit_use = item.get("decisionUse")
- else:
- label, summary, explicit_use = _text(item), None, None
- result.append(
- {
- "label": label or f"信息来源 {index}",
- "summary": summary,
- "observedRelation": "persisted-before-decision",
- "decisionUse": explicit_use or "not-recorded",
- }
- )
- return result
- def _actor(value: Any, *, default_role: str, default_label: str) -> dict[str, str]:
- if isinstance(value, Mapping):
- return {
- "role": _machine(value.get("role")) or default_role,
- "label": _text(value.get("label")) or default_label,
- }
- return {"role": default_role, "label": default_label}
- def _summary_block(
- title: str,
- value: Any,
- *,
- visual_role: str = "section",
- presentation: str = "prose",
- ) -> dict[str, Any] | None:
- text = _text(value)
- return {
- "type": "summary",
- "title": title,
- "value": text,
- "visualRole": visual_role,
- "presentation": presentation,
- } if text else None
- def _source_document_block(title: str, value: Any) -> dict[str, Any] | None:
- text = _source_text(value)
- return {
- "type": "summary",
- "title": title,
- "value": text,
- "visualRole": "key-result",
- "presentation": "document",
- } if text else None
- def _items_block(
- title: str,
- items: Any,
- *,
- visual_role: str = "section",
- presentation: str = "list",
- collapsible: bool = False,
- default_open: bool = False,
- ) -> dict[str, Any] | None:
- if not isinstance(items, list) or not items:
- return None
- return {
- "type": "items",
- "title": title,
- "items": items,
- "visualRole": visual_role,
- "presentation": presentation,
- "collapsible": collapsible,
- "defaultOpen": default_open,
- }
- def _creative_process_block(steps: list[dict[str, Any]]) -> dict[str, Any] | None:
- if not steps:
- return None
- return {
- "type": "creative-process",
- "title": "创作处理",
- "steps": steps,
- "visualRole": "section",
- "presentation": "process",
- }
- def _evaluation_branches_block(branches: list[dict[str, Any]]) -> dict[str, Any] | None:
- if not branches:
- return None
- return {
- "type": "evaluation-branches",
- "title": "逐方案评审",
- "branches": branches,
- "visualRole": "section",
- "presentation": "grouped-review",
- }
- def _evaluation_matrix_block(rows: list[dict[str, Any]]) -> dict[str, Any] | None:
- if not rows:
- return None
- return {
- "type": "evaluation-matrix",
- "title": "评审标准与方案对比",
- "rows": rows,
- "visualRole": "section",
- "presentation": "matrix",
- }
- def _decision_items_block(
- title: str,
- items: list[str],
- *,
- visual_role: str = "section",
- ) -> dict[str, Any] | None:
- if not items:
- return None
- if len(items) == 1:
- return _summary_block(title, items[0], visual_role=visual_role)
- return _items_block(title, items, visual_role=visual_role)
- def _implementation_plan(value: Any, reasoning: str | None) -> dict[str, Any]:
- plan = value if isinstance(value, Mapping) else {}
- routes = plan.get("routes") if isinstance(plan.get("routes"), list) else []
- return {
- "mode": _text(plan.get("mode")) or _text(plan.get("rawMode")),
- "reasoning": _text(plan.get("reasoning")) or reasoning,
- "routes": [
- {
- "pathIndex": route.get("pathIndex") or index,
- "pathType": _business_text(route.get("pathType")),
- "action": _business_text(route.get("action")),
- "target": _business_text(route.get("target")),
- "method": _business_text(route.get("method")),
- "emphasis": _business_text(route.get("emphasis")),
- }
- for index, route in enumerate(routes, 1)
- if isinstance(route, Mapping)
- ],
- }
- def _implementation_plan_block(plan: Mapping[str, Any]) -> dict[str, Any] | None:
- routes = plan.get("routes") if isinstance(plan.get("routes"), list) else []
- if not routes and not plan.get("reasoning"):
- return None
- return {
- "type": "implementation-plan",
- "title": "本轮实施路线",
- "visualRole": "section",
- "presentation": "plan",
- "mode": plan.get("mode"),
- "routes": routes,
- "reasoning": plan.get("reasoning"),
- }
- def _item_conclusion_summary(items: list[dict[str, Any]]) -> str | None:
- summaries = []
- for item in items[:3]:
- subject = _text(item.get("subject") or item.get("label"))
- conclusion = _text(item.get("conclusion") or item.get("value"))
- if subject and conclusion:
- summaries.append(f"{subject}:{conclusion}")
- if not summaries:
- return None
- suffix = f";另有 {len(items) - 3} 项" if len(items) > 3 else ""
- return ";".join(summaries) + suffix
- def _comparison_block(value: Any) -> dict[str, Any] | None:
- if not isinstance(value, list) or not value:
- return None
- return {
- "type": "comparison",
- "title": "评审建议与最终决定",
- "visualRole": "section",
- "presentation": "comparison",
- "rows": _business_value(value),
- }
- def _input_business_item(item: Mapping[str, Any]) -> dict[str, str]:
- result = {"label": str(item.get("label") or "信息")}
- summary = _business_text(item.get("summary"))
- if summary:
- result["value"] = summary
- relation = {
- "read-by-actor": "决策前直接读取",
- "returned-to-actor": "评审返回给决策者",
- "persisted-before-decision": "此前已保存",
- "standing-constraint": "持续约束",
- }.get(str(item.get("observedRelation") or ""))
- use = (
- "本轮必须遵守"
- if item.get("observedRelation") == "standing-constraint"
- else "明确作为决策依据"
- if item.get("decisionUse") == "explicit-basis"
- else "是否采用未记录"
- )
- result["note"] = ";".join(part for part in (relation, use) if part)
- return result
- def _business_text(value: Any) -> str | None:
- text = business_text(value)
- return text or None
- def _card_line(key: str, label: str, value: Any, tone: str | None = None) -> dict[str, Any]:
- line = {"key": key, "label": label, "value": _preview(value, 160)}
- if tone:
- line["tone"] = tone
- return line
- def _notices(value: Any) -> list[dict[str, str]]:
- if not isinstance(value, list):
- return []
- result = []
- for item in value:
- if isinstance(item, Mapping):
- code = _machine(item.get("code"))
- message = _text(item.get("message"))
- else:
- code, message = "notice", _text(item)
- if code and message:
- result.append({"code": code, "message": message})
- return result
- def _business_dicts(value: Any) -> list[Any]:
- if not isinstance(value, list):
- return []
- result: list[Any] = []
- for item in value:
- if isinstance(item, Mapping):
- cleaned = {
- key: _business_value(item[key])
- for key in (
- "label",
- "subject",
- "conclusion",
- "summary",
- "severity",
- "recommendation",
- "achievements",
- "problems",
- )
- if item.get(key) not in (None, "")
- }
- if cleaned:
- result.append(cleaned)
- elif text := _text(item):
- result.append(text)
- return result
- def _mapping_list(value: Any) -> list[dict[str, Any]]:
- if not isinstance(value, list):
- return []
- return [
- _business_value(dict(item))
- for item in value
- if isinstance(item, Mapping)
- ]
- def _creative_steps(value: Any) -> list[dict[str, Any]]:
- if not isinstance(value, list):
- return []
- result: list[dict[str, Any]] = []
- for fallback_index, item in enumerate(value, start=1):
- if not isinstance(item, Mapping):
- continue
- action = _text(item.get("action"))
- plan = _source_text(item.get("plan"))
- summary = _text(item.get("summary"))
- reasoning = _source_text(item.get("reasoning"))
- if not any((action, plan, summary, reasoning)):
- continue
- result.append(
- {
- "stepIndex": int(item.get("stepIndex") or fallback_index),
- "action": action or f"步骤 {fallback_index}",
- "summary": summary,
- "plan": plan,
- "reasoning": reasoning,
- "eventRef": _text(item.get("eventRef")),
- }
- )
- return result
- def _problem_summary(problems: list[Any]) -> str:
- values = []
- for item in problems[:2]:
- if isinstance(item, Mapping):
- values.append(_text(item.get("summary") or item.get("label")) or "待处理问题")
- else:
- values.append(str(item))
- return _join(values, 2)
- def _input_labels(inputs: list[dict[str, Any]]) -> str:
- return _join([str(item["label"]) for item in inputs], 3)
- def _direction_question(subtype: str) -> str:
- return {
- "objective": "这次构建要形成什么创作方向?",
- "round-goal": "本轮优先解决什么问题?",
- "implementation-plan": "本轮应如何组织实现方案?",
- }.get(subtype, "这一步确定了什么方向?")
- def _is_successful_think_and_plan(event: Mapping[str, Any]) -> bool:
- return (
- str(event.get("event_type") or "") == "tool_call"
- and str(event.get("event_name") or "") == "think_and_plan"
- and str(event.get("agent_role") or "")
- in {"script_implementer", "implementer"}
- and str(event.get("status") or "").lower() in _SUCCESS_STATUSES
- )
- def _completeness(value: Any, primary: str | None) -> str:
- explicit = _machine(value)
- if explicit in {"complete", "partial", "missing"}:
- return explicit
- return "complete" if primary else "missing"
- def _strings(value: Any) -> list[str]:
- if not isinstance(value, list):
- return []
- return [text for item in value if (text := _text(item))]
- def _unique_values(value: Any) -> list[Any]:
- if not isinstance(value, list):
- return []
- result = []
- for item in value:
- if item not in result:
- result.append(item)
- return result
- def _join(values: list[str], limit: int) -> str:
- kept = [value for value in values if value][:limit]
- suffix = f" · 另有 {len(values) - limit} 项" if len(values) > limit else ""
- return " · ".join(kept) + suffix
- def _preview(value: Any, limit: int) -> str:
- text = _text(value) or ""
- if len(text) <= limit:
- return text
- cut = text[:limit]
- boundary = max(cut.rfind(mark) for mark in "。!?;")
- if boundary >= max(24, limit // 2):
- return cut[: boundary + 1]
- return cut.rstrip() + "…"
- def _text(value: Any) -> str | None:
- if value is None:
- return None
- if isinstance(value, (dict, list, tuple, set)):
- return None
- text = str(value).replace("\\n", "\n")
- text = re.sub(r"[`*_#]+", "", text)
- text = re.sub(r"\s+", " ", text).strip(" ::")
- return _business_copy(text) or None
- def _source_text(value: Any) -> str | None:
- """Keep authoritative saved Markdown intact for source-document rendering."""
- if value is None or isinstance(value, (dict, list, tuple, set)):
- return None
- text = str(value).replace("\\n", "\n").strip()
- return text or None
- def _business_value(value: Any) -> Any:
- if isinstance(value, str):
- return _business_copy(value)
- if isinstance(value, list):
- return [_business_value(item) for item in value]
- if isinstance(value, Mapping):
- return {key: _business_value(item) for key, item in value.items()}
- return value
- def _business_copy(text: str) -> str:
- """Translate machine-facing tokens without deleting ordinary numbers."""
- replacements = (
- (r"\bretrieve_data_decode_case\b|\bretrievedatadecodecase\b", "解构案例取数"),
- (r"\bretrieve_data_knowledge\b|\bretrievedataknowledge\b", "知识取数"),
- (r"\bget_account_script_persona_points\b|\bgetaccountscriptpersonapoints\b", "账号人设"),
- (r"\bget_account_script_section_patterns\b", "账号段落模式"),
- (r"\bget_topic_detail\b", "选题内容"),
- (r"\bget_script_snapshot\b", "当前主脚本"),
- (r"\brecord_data_decision\b", "记录数据取舍"),
- (r"\bthink_and_plan\b", "实现思考与计划"),
- )
- for pattern, label in replacements:
- text = re.sub(pattern, label, text, flags=re.IGNORECASE)
- text = re.sub(
- r"\bpost_?id\s*[:=]?(?:\s*[A-Za-z0-9-]+)?",
- "账号内容样本",
- text,
- flags=re.IGNORECASE,
- )
- text = re.sub(r"\bscript_build_id\s*[:=]\s*\d+\b", "", text, flags=re.IGNORECASE)
- text = re.sub(r"\bround_index\s*[:=]\s*(\d+)\b", r"第 \1 轮", text, flags=re.IGNORECASE)
- text = re.sub(r"\bbranch[_\s-]*(\d+)\b", r"方案 \1", text, flags=re.IGNORECASE)
- text = re.sub(r"\bP(\d+)\b", r"段落 \1", text)
- text = re.sub(r"\bD(\d+)\b", r"评估维度 \1", text)
- text = re.sub(r"\bbase\b", "主脚本", text, flags=re.IGNORECASE)
- return re.sub(r"\s+", " ", text).strip(" ::")
- def _machine(value: Any) -> str | None:
- if value is None or isinstance(value, (dict, list, tuple, set)):
- return None
- text = str(value).strip()
- return text or None
|