""" Built-in agent Chinese display normalization. """ from __future__ import annotations from copy import deepcopy from typing import Any, Dict, Iterable, Optional class BuiltinAgentText: def __init__( self, *, name: str, code_label: str, description: str, role: str = "", skills: Optional[list[str]] = None, constraints: Optional[list[str]] = None, background: str = "", keys: Iterable[str], description_keywords: Iterable[str] = (), persona_keywords: Iterable[str] = (), ): self.name = name self.code_label = code_label self.description = description self.role = role self.skills = skills or [] self.constraints = constraints or [] self.background = background self.keys = list(keys) self.description_keywords = list(description_keywords) self.persona_keywords = list(persona_keywords) BUILTIN_AGENT_TEXTS = [ BuiltinAgentText( name="项目经理", code_label="项目管理", description="协调交付状态、进度风险和跨角色协作,确保项目按计划推进。", keys=("project manager", "project_manager", "project-manager", "projectmanager"), description_keywords=("coordinates delivery status",), ), BuiltinAgentText( name="Multica 产品经理", code_label="产品管理", description="负责产品需求分诊、优先级判断和方案澄清,推动产品决策落地。", role="负责 Multica 协作工作的产品需求分诊、范围澄清、验收标准和质量推进决策。", skills=["范围澄清", "验收标准设计", "优先级取舍分析", "干系人沟通"], constraints=[ "需求必须能追溯到具体 issue 或用户请求。", "没有明确验收标准时,不推进下游工作。", "遇到未决产品决策时要明确指出,不能擅自假设。", ], background="擅长把模糊的平台需求转化为责任清晰、可评审、可交付的 Multica issue。", keys=( "multica product manager", "multica_product_manager", "multica-product-manager", "product manager", "product_manager", "product-manager", ), description_keywords=("owns product triage",), persona_keywords=( "product manager for multica", "scope clarification", "acceptance criteria design", "priority tradeoff analysis", "stakeholder communication", "keep requirements traceable", ), ), BuiltinAgentText( name="业务需求分析师", code_label="需求分析", description="将业务诉求转化为清晰需求、验收标准和可执行的交付范围。", keys=( "business requirements analyst", "business_requirements_analyst", "business-requirements-analyst", "business analyst", "business_analyst", "business-analyst", ), description_keywords=("translates business needs",), ), BuiltinAgentText( name="系统架构师", code_label="系统架构", description="设计系统边界、模块职责和技术方案,保障架构一致性与可演进性。", keys=("system architect", "system_architect", "system-architect"), ), BuiltinAgentText( name="前端工程师", code_label="前端开发", description="负责前端页面、组件交互、路由状态和浏览器端体验实现。", keys=("frontend engineer", "frontend_engineer", "frontend-engineer"), ), BuiltinAgentText( name="后端工程师", code_label="后端开发", description="负责后端接口、业务服务、数据模型和系统集成能力建设。", keys=("backend engineer", "backend_engineer", "backend-engineer"), ), BuiltinAgentText( name="测试工程师", code_label="质量保障", description="负责测试策略、用例设计、缺陷验证和发布质量把关。", keys=("qa engineer", "qa_engineer", "qa-engineer"), ), ] def _normalize_text(value: Any) -> str: return " ".join(str(value or "").strip().lower().replace("-", " ").replace("_", " ").split()) def _iter_persona_values(persona: Any) -> Iterable[str]: if not isinstance(persona, dict): return [] values: list[str] = [] for key in ("role", "background"): value = persona.get(key) if isinstance(value, str): values.append(value) for key in ("personality", "skills", "constraints"): values.extend(item for item in persona.get(key) or [] if isinstance(item, str)) return values def find_builtin_agent_text(data: Dict[str, Any]) -> Optional[BuiltinAgentText]: name = _normalize_text(data.get("name")) code = _normalize_text(data.get("code")) description = _normalize_text(data.get("description")) persona_text = _normalize_text(" ".join(_iter_persona_values(data.get("persona")))) for display in BUILTIN_AGENT_TEXTS: keys = {_normalize_text(key) for key in display.keys} if name in keys or code in keys: return display if any(keyword in description for keyword in display.description_keywords): return display if any(keyword in persona_text for keyword in display.persona_keywords): return display return None def normalize_builtin_agent_payload(data: Dict[str, Any], *, include_code_label: bool = False) -> Dict[str, Any]: display = find_builtin_agent_text(data) if not display: return data normalized = deepcopy(data) normalized["name"] = display.name normalized["description"] = display.description if include_code_label: normalized["code_label"] = display.code_label persona = deepcopy(normalized.get("persona") or {}) if display.role: persona["role"] = display.role if display.skills: persona["skills"] = list(display.skills) if display.constraints: persona["constraints"] = list(display.constraints) if display.background: persona["background"] = display.background normalized["persona"] = persona return normalized