from __future__ import annotations from datetime import UTC, datetime from sqlalchemy import select from app.core.agent_enums import ( AgentAssetContentType, AgentAssetDomain, AgentAssetStatus, AgentAssetType, AgentName, AgentReviewStatus, ) from app.core.logging import get_logger from app.models.agent_asset import AgentAsset, AgentAssetReview, AgentAssetVersion from app.services.agent_asset_spreadsheet import ( COMPANY_COMMUNICATION_EXPENSE_RULE_CODE, COMPANY_TRAVEL_EXPENSE_RULE_CODE, FINANCE_RULES_LIBRARY, AgentAssetSpreadsheetManager, ) from app.services.agent_foundation_constants import ( ATTACHMENT_RULE_ASSET_CODE, ATTACHMENT_RULE_RUNTIME_CONFIG, COMPANY_COMMUNICATION_RULE_SCENARIO_JSON, COMPANY_COMMUNICATION_RULE_VERSION, COMPANY_TRAVEL_RULE_SCENARIO_JSON, COMPANY_TRAVEL_RULE_VERSION, ) logger = get_logger("app.services.agent_foundation") class AgentFoundationAssetSeedMixin: def _seed_agent_assets(self) -> None: existing_codes = set(self.db.scalars(select(AgentAsset.code)).all()) if existing_codes: self._top_up_agent_assets(existing_codes) return attachment_rule = AgentAsset( asset_type=AgentAssetType.RULE.value, code=ATTACHMENT_RULE_ASSET_CODE, name="报销附件与单据完整性规则", description="统一定义报销提交时的附件数量、票据类型和补件处理口径,作为上线前待审核规则。", domain=AgentAssetDomain.EXPENSE.value, scenario_json=["expense", "risk_check", "attachment_policy", "invoice_anomaly"], owner="财务制度管理组", reviewer="高嘉禾", status=AgentAssetStatus.REVIEW.value, current_version="v1.0.0", published_version=None, working_version="v1.0.0", config_json={ "severity": "high", "enabled": False, "runtime_kind": "policy_rule_draft", "rule_template_key": "attachment_requirement_v1", "rule_template_label": "附件要求模板", "runtime_rule": ATTACHMENT_RULE_RUNTIME_CONFIG, }, ) scene_submission_rule = AgentAsset( asset_type=AgentAssetType.RULE.value, code="rule.expense.scene_submission_standard", name="报销场景提交与附件标准", description="统一定义各报销场景的必填字段、附件类型要求和金额阈值。", domain=AgentAssetDomain.EXPENSE.value, scenario_json=["expense", "risk_check", "scene_policy", "attachment_policy"], owner="费用运营组", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={ "severity": "high", "enabled": True, "runtime_kind": "scene_matrix", "rule_template_label": "系统内置场景矩阵规则", }, ) travel_policy_rule = AgentAsset( asset_type=AgentAssetType.RULE.value, code="rule.expense.travel_risk_control_standard", name="差旅报销风险管控制度", description="统一定义差旅报销的行程闭环、酒店地点一致性、职级差标和风险处置口径。", domain=AgentAssetDomain.EXPENSE.value, scenario_json=["expense", "risk_check", "travel_policy", "travel_standard"], owner="风控与审计部", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.1.0", published_version="v1.1.0", working_version="v1.1.0", config_json={ "severity": "high", "enabled": True, "block_on_high_risk": True, "warning_on_medium_risk": True, "source_doc": "document/development/risks/travel-risk-control-standard.md", "runtime_kind": "travel_policy", "rule_template_key": "travel_standard_v1", "rule_template_label": "差旅标准模板", }, ) company_travel_rule = AgentAsset( asset_type=AgentAssetType.RULE.value, code=COMPANY_TRAVEL_EXPENSE_RULE_CODE, name="公司差旅费报销规则", description="通过 Excel 明细表维护差旅费报销标准、票据要求和审批口径。", domain=AgentAssetDomain.EXPENSE.value, scenario_json=list(COMPANY_TRAVEL_RULE_SCENARIO_JSON), owner="财务制度管理组", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version=COMPANY_TRAVEL_RULE_VERSION, published_version=COMPANY_TRAVEL_RULE_VERSION, working_version=COMPANY_TRAVEL_RULE_VERSION, config_json={ "severity": "medium", "enabled": True, "tag": "财务规则", "detail_mode": "spreadsheet", "rule_library": FINANCE_RULES_LIBRARY, "scenario_category": COMPANY_TRAVEL_RULE_SCENARIO_JSON[0], "ai_review_category": COMPANY_TRAVEL_RULE_SCENARIO_JSON[0], "rule_template_label": "差旅报销 Excel 模板", }, ) platform_risk_assets = self._build_platform_risk_seed_assets() company_communication_rule = AgentAsset( asset_type=AgentAssetType.RULE.value, code=COMPANY_COMMUNICATION_EXPENSE_RULE_CODE, name="公司通信费报销规则", description="通过 Excel 明细表维护员工通信费报销标准、专项补充口径和审批要求。", domain=AgentAssetDomain.EXPENSE.value, scenario_json=list(COMPANY_COMMUNICATION_RULE_SCENARIO_JSON), owner="财务制度管理组", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version=COMPANY_COMMUNICATION_RULE_VERSION, published_version=COMPANY_COMMUNICATION_RULE_VERSION, working_version=COMPANY_COMMUNICATION_RULE_VERSION, config_json={ "severity": "medium", "enabled": True, "tag": "财务规则", "detail_mode": "spreadsheet", "rule_library": FINANCE_RULES_LIBRARY, "scenario_category": COMPANY_COMMUNICATION_RULE_SCENARIO_JSON[0], "ai_review_category": COMPANY_COMMUNICATION_RULE_SCENARIO_JSON[0], "rule_template_label": "通信费报销 Excel 模板", }, ) skill_expense_asset = AgentAsset( asset_type=AgentAssetType.SKILL.value, code="skill.expense.summary_lookup", name="报销汇总查询技能", description="根据时间、员工和部门汇总报销金额与单据数量。", domain=AgentAssetDomain.EXPENSE.value, scenario_json=["expense", "query", "summary"], owner="平台研发组", reviewer="陈硕", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"input_schema": ["time_range", "employee", "department"]}, ) skill_ar_asset = AgentAsset( asset_type=AgentAssetType.SKILL.value, code="skill.ar.aging_summary", name="应收账龄汇总技能", description="按客户、账龄和逾期状态汇总应收风险分布。", domain=AgentAssetDomain.AR.value, scenario_json=["accounts_receivable", "query", "aging_summary"], owner="平台研发组", reviewer="陈硕", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"input_schema": ["customer", "aging_bucket", "status"]}, ) invoice_mcp_asset = AgentAsset( asset_type=AgentAssetType.MCP.value, code="mcp.invoice.verify_mock", name="发票验真 Mock 服务", description="模拟发票验真、发票状态查询和异常降级说明。", domain=AgentAssetDomain.SYSTEM.value, scenario_json=["expense", "invoice_validation"], owner="平台研发组", reviewer="周悦宁", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"endpoint": "mock://invoice/verify", "timeout_ms": 1200}, ) ledger_mcp_asset = AgentAsset( asset_type=AgentAssetType.MCP.value, code="mcp.ledger.snapshot_mock", name="总账快照 Mock 服务", description="模拟返回应收、应付和费用汇总快照,供 Agent 查询和巡检。", domain=AgentAssetDomain.SYSTEM.value, scenario_json=["expense", "accounts_receivable", "accounts_payable"], owner="平台研发组", reviewer="周悦宁", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"endpoint": "mock://ledger/snapshot", "timeout_ms": 1500}, ) task_asset = AgentAsset( asset_type=AgentAssetType.TASK.value, code="task.hermes.daily_risk_scan", name="Hermes 每日风险巡检", description="每天早上巡检重复报销、金额超标、逾期应收和异常付款。", domain=AgentAssetDomain.SYSTEM.value, scenario_json=["schedule", "risk_check"], owner="风控与审计部", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"cron": "0 9 * * *", "agent": AgentName.HERMES.value}, ) ar_summary_task = AgentAsset( asset_type=AgentAssetType.TASK.value, code="task.hermes.weekly_ar_summary", name="Hermes 每周应收账龄汇总", description="每周汇总逾期应收、账龄分布和客户风险变化。", domain=AgentAssetDomain.SYSTEM.value, scenario_json=["schedule", "accounts_receivable", "summary"], owner="风控与审计部", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"cron": "0 10 * * 1", "agent": AgentName.HERMES.value}, ) rule_digest_task = AgentAsset( asset_type=AgentAssetType.TASK.value, code="task.hermes.rule_review_digest", name="Hermes 规则待审摘要", description="每天汇总待审规则、待补样例和被拒规则修订建议。", domain=AgentAssetDomain.SYSTEM.value, scenario_json=["schedule", "rule_center", "review_digest"], owner="风控与审计部", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"cron": "0 18 * * *", "agent": AgentName.HERMES.value}, ) knowledge_index_task = AgentAsset( asset_type=AgentAssetType.TASK.value, code="task.hermes.knowledge_index_sync", name="Hermes ??????", description="?????????? LightRAG ???????", domain=AgentAssetDomain.SYSTEM.value, scenario_json=["schedule", "knowledge", "rule_center"], owner="财务制度管理组", reviewer="顾承宇", status=AgentAssetStatus.ACTIVE.value, current_version="v1.0.0", published_version="v1.0.0", working_version="v1.0.0", config_json={"cron": "0 0 * * *", "agent": AgentName.HERMES.value}, ) self.db.add_all( [ attachment_rule, scene_submission_rule, travel_policy_rule, *platform_risk_assets, company_travel_rule, company_communication_rule, skill_expense_asset, skill_ar_asset, invoice_mcp_asset, ledger_mcp_asset, task_asset, ar_summary_task, rule_digest_task, knowledge_index_task, ] ) self.db.flush() company_travel_rule_meta = self._ensure_company_travel_rule_spreadsheet_seed( company_travel_rule, version=COMPANY_TRAVEL_RULE_VERSION, actor_name="系统初始化", ) company_communication_rule_meta = self._ensure_company_communication_rule_spreadsheet_seed( company_communication_rule, version=COMPANY_COMMUNICATION_RULE_VERSION, actor_name="系统初始化", ) self._hide_deprecated_finance_rule_assets() self.db.add_all( [ AgentAssetVersion( asset=attachment_rule, version="v0.9.0", content=self._attachment_submission_requirement_markdown( version_note="首版附件完整性规则草稿,覆盖基础票据与补件口径。", include_review_note=True, ), content_type=AgentAssetContentType.MARKDOWN.value, change_note="首版草稿。", created_by="高嘉禾", ), AgentAssetVersion( asset=attachment_rule, version="v1.0.0", content=self._attachment_submission_requirement_markdown( version_note="补充票据缺失、收据替代和差旅等效凭证口径,待审核。", include_review_note=True, ), content_type=AgentAssetContentType.MARKDOWN.value, change_note="补充票据替代与差旅等效凭证口径,待审核。", created_by="高嘉禾", ), AgentAssetVersion( asset=scene_submission_rule, version="v1.0.0", content=self._scene_submission_standard_markdown(), content_type=AgentAssetContentType.MARKDOWN.value, change_note="首版报销场景提交标准,覆盖附件类型、必填字段和金额阈值。", created_by="系统初始化", ), AgentAssetVersion( asset=travel_policy_rule, version="v1.0.0", content=self._travel_risk_control_standard_markdown(version="v1.0.0"), content_type=AgentAssetContentType.MARKDOWN.value, change_note="首版差旅制度执行规则,覆盖行程闭环与基础差标校验。", created_by="系统初始化", ), AgentAssetVersion( asset=travel_policy_rule, version="v1.1.0", content=self._travel_risk_control_standard_markdown(version="v1.1.0"), content_type=AgentAssetContentType.MARKDOWN.value, change_note="补充可执行规则块,供审核引擎直接消费差旅制度标准。", created_by="系统初始化", ), *[ AgentAssetVersion( asset=asset, version="v1.0.0", content=self._platform_risk_rule_markdown(asset), content_type=AgentAssetContentType.MARKDOWN.value, change_note=f"平台通用风险规则:{asset.name}", created_by="系统初始化", ) for asset in platform_risk_assets ], AgentAssetVersion( asset=company_travel_rule, version=COMPANY_TRAVEL_RULE_VERSION, content=AgentAssetSpreadsheetManager.build_version_markdown( rule_name=company_travel_rule.name, version=COMPANY_TRAVEL_RULE_VERSION, metadata=company_travel_rule_meta, ), content_type=AgentAssetContentType.MARKDOWN.value, change_note="初始化差旅费报销 Excel 规则表。", created_by="系统初始化", ), AgentAssetVersion( asset=company_communication_rule, version=COMPANY_COMMUNICATION_RULE_VERSION, content=AgentAssetSpreadsheetManager.build_version_markdown( rule_name=company_communication_rule.name, version=COMPANY_COMMUNICATION_RULE_VERSION, metadata=company_communication_rule_meta, ), content_type=AgentAssetContentType.MARKDOWN.value, change_note="初始化通信费报销 Excel 规则表。", created_by="系统初始化", ), AgentAssetVersion( asset=skill_expense_asset, version="v1.0.0", content=self._json_content( { "inputs": ["time_range", "employee", "department"], "outputs": ["total_amount", "claim_count"], "dependencies": ["database.expense_claims"], } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化技能快照。", created_by="系统初始化", ), AgentAssetVersion( asset=skill_ar_asset, version="v1.0.0", content=self._json_content( { "inputs": ["customer", "aging_bucket", "status"], "outputs": ["receivable_total", "overdue_total", "customer_count"], "dependencies": ["database.accounts_receivable"], } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化应收账龄技能快照。", created_by="系统初始化", ), AgentAssetVersion( asset=invoice_mcp_asset, version="v1.0.0", content=self._json_content( { "service_type": "mock", "auth_mode": "none", "degrade_strategy": "return_stub_with_warning", } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化 MCP 快照。", created_by="系统初始化", ), AgentAssetVersion( asset=ledger_mcp_asset, version="v1.0.0", content=self._json_content( { "service_type": "mock", "auth_mode": "service_account", "degrade_strategy": "return_cached_snapshot_with_warning", } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化总账快照 MCP。", created_by="系统初始化", ), AgentAssetVersion( asset=task_asset, version="v1.0.0", content=self._json_content( { "task_type": "daily_risk_scan", "schedule": "0 9 * * *", "target_agent": AgentName.HERMES.value, } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化任务快照。", created_by="系统初始化", ), AgentAssetVersion( asset=ar_summary_task, version="v1.0.0", content=self._json_content( { "task_type": "weekly_ar_summary", "schedule": "0 10 * * 1", "target_agent": AgentName.HERMES.value, } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化应收账龄汇总任务。", created_by="系统初始化", ), AgentAssetVersion( asset=rule_digest_task, version="v1.0.0", content=self._json_content( { "task_type": "rule_review_digest", "schedule": "0 18 * * *", "target_agent": AgentName.HERMES.value, } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化规则待审摘要任务。", created_by="系统初始化", ), AgentAssetVersion( asset=knowledge_index_task, version="v1.0.0", content=self._json_content( { "task_type": "knowledge_index_sync", "schedule": "0 0 * * *", "target_agent": AgentName.HERMES.value, "folder": "报销制度", "changed_only": True, "index_engine": "lightrag", } ), content_type=AgentAssetContentType.JSON.value, change_note="初始化制度知识与规则草稿形成任务。", created_by="系统初始化", ), ] ) self.db.add_all( [ AgentAssetReview( asset=attachment_rule, version="v1.0.0", reviewer="高嘉禾", review_status=AgentReviewStatus.PENDING.value, review_note="等待制度管理员确认收据替代与补件时限口径。", reviewed_at=None, ), AgentAssetReview( asset=scene_submission_rule, version="v1.0.0", reviewer="顾承宇", review_status=AgentReviewStatus.APPROVED.value, review_note="可作为报销场景统一审核标准正式执行。", reviewed_at=datetime.now(UTC), ), AgentAssetReview( asset=travel_policy_rule, version="v1.1.0", reviewer="顾承宇", review_status=AgentReviewStatus.APPROVED.value, review_note="制度口径已确认,并已补充可执行配置供审核引擎读取。", reviewed_at=datetime.now(UTC), ), AgentAssetReview( asset=company_travel_rule, version=COMPANY_TRAVEL_RULE_VERSION, reviewer="顾承宇", review_status=AgentReviewStatus.APPROVED.value, review_note="首版 Excel 规则表已确认,可作为财务规则使用。", reviewed_at=datetime.now(UTC), ), AgentAssetReview( asset=company_communication_rule, version=COMPANY_COMMUNICATION_RULE_VERSION, reviewer="顾承宇", review_status=AgentReviewStatus.APPROVED.value, review_note="首版 Excel 规则表已确认,可作为财务规则使用。", reviewed_at=datetime.now(UTC), ), ] )