package acp import "regexp" // DefaultToolLabel 未命中任何规则时的兜底简述 const DefaultToolLabel = "调用工具" // mcpIdentRe 判断 title 是否为 MCP 工具标识名(service_/data_/storage_/plane_/util_ 前缀)。 // 仅在标识名形态下才走「动作 + 对象」组合,避免误伤内置工具的自然语言 title。 var mcpIdentRe = regexp.MustCompile(`(?i)(^|[^a-z])(service|data|storage|plane|util)_[a-z]`) // domainNoiseRe 域名中会误触发动作识别的噪声片段(其中的 update 属于对象名而非动作)。 // 在动作识别前先剔除,避免 auto_update / update_log 等被误判为“更新”动作。 var domainNoiseRe = regexp.MustCompile(`(?i)auto_update|system_update|ahub_update|update_log`) // objectRule 对象词识别规则(title 片段 → 对象中文名) type objectRule struct { re *regexp.Regexp noun string } // objectRules 顺序即优先级,更具体的对象必须排在更宽泛的之前。 var objectRules = []objectRule{ // —— Plane 项目管理相关对象 —— {regexp.MustCompile(`(?i)fault_record`), "故障工单"}, {regexp.MustCompile(`(?i)intake_issue`), "收件箱工作项"}, {regexp.MustCompile(`(?i)sub_issue`), "子工作项"}, {regexp.MustCompile(`(?i)issue_relation|_relation`), "工作项关联"}, {regexp.MustCompile(`(?i)issue_link`), "工作项链接"}, {regexp.MustCompile(`(?i)work_item|_issues?(_|$)|_issue(_|$)|issue`), "工作项"}, {regexp.MustCompile(`(?i)cycle`), "周期"}, {regexp.MustCompile(`(?i)module`), "模块"}, {regexp.MustCompile(`(?i)page`), "页面"}, {regexp.MustCompile(`(?i)workspace_member`), "工作空间成员"}, {regexp.MustCompile(`(?i)project_member`), "项目成员"}, {regexp.MustCompile(`(?i)project_asset`), "项目资源"}, {regexp.MustCompile(`(?i)workspace`), "工作空间"}, {regexp.MustCompile(`(?i)project`), "项目"}, {regexp.MustCompile(`(?i)label`), "标签"}, {regexp.MustCompile(`(?i)state`), "状态"}, {regexp.MustCompile(`(?i)comment`), "评论"}, {regexp.MustCompile(`(?i)sticky|stickies`), "便签"}, {regexp.MustCompile(`(?i)assets?|entity`), "资源"}, // —— 站点 / 监控 / 数据相关对象 —— {regexp.MustCompile(`(?i)alarm_snapshot`), "告警快照"}, {regexp.MustCompile(`(?i)alarm_statistic`), "告警统计"}, {regexp.MustCompile(`(?i)event_alarm`), "事件告警"}, {regexp.MustCompile(`(?i)alarm`), "告警"}, {regexp.MustCompile(`(?i)shutdown`), "停机"}, {regexp.MustCompile(`(?i)power_flow`), "功率流"}, {regexp.MustCompile(`(?i)mode_info`), "运行模式"}, {regexp.MustCompile(`(?i)base_info`), "基础信息"}, {regexp.MustCompile(`(?i)tou_template`), "电价模板"}, {regexp.MustCompile(`(?i)apower_version`), "APower版本"}, {regexp.MustCompile(`(?i)auto_update|_package|升级包`), "升级包"}, {regexp.MustCompile(`(?i)batch_download`), "批量下载"}, {regexp.MustCompile(`(?i)background_task`), "后台任务"}, {regexp.MustCompile(`(?i)site_analysis`), "站点分析"}, {regexp.MustCompile(`(?i)site_monitor`), "站点监控"}, {regexp.MustCompile(`(?i)_tag|tags_`), "站点标签"}, {regexp.MustCompile(`(?i)site`), "站点"}, {regexp.MustCompile(`(?i)data_pool`), "数据池"}, {regexp.MustCompile(`(?i)_card|_sim|sim_`), "SIM卡"}, {regexp.MustCompile(`(?i)dashboard`), "看板"}, {regexp.MustCompile(`(?i)feedback`), "反馈"}, {regexp.MustCompile(`(?i)monitor`), "监控"}, {regexp.MustCompile(`(?i)snapshot`), "快照数据"}, {regexp.MustCompile(`(?i)system_update_log|ahub_update_log|update_log`), "升级日志"}, {regexp.MustCompile(`(?i)ems_log|mqtt_log|_log(_|$)`), "日志"}, {regexp.MustCompile(`(?i)pid_info|vid_info|emspara`), "EMS参数"}, // —— 数据库 / 存储 —— {regexp.MustCompile(`(?i)mongo`), "MongoDB"}, {regexp.MustCompile(`(?i)redis`), "Redis缓存"}, {regexp.MustCompile(`(?i)pgsql`), "PostgreSQL"}, {regexp.MustCompile(`(?i)file|minio|object`), "文件"}, } // actionRule 动作词识别规则(title 片段 → 动词 + 后缀) type actionRule struct { re *regexp.Regexp verb string suffix string } // actionRules 顺序即优先级。变更类动作先于查询类;unarchive 先于 archive;list 先于 get。 var actionRules = []actionRule{ {regexp.MustCompile(`(?i)unarchive`), "取消归档", ""}, {regexp.MustCompile(`(?i)archive`), "归档", ""}, {regexp.MustCompile(`(?i)create`), "创建", ""}, {regexp.MustCompile(`(?i)update|mark`), "更新", ""}, {regexp.MustCompile(`(?i)delete`), "删除", ""}, {regexp.MustCompile(`(?i)remove`), "移除", ""}, {regexp.MustCompile(`(?i)accept`), "受理", ""}, {regexp.MustCompile(`(?i)reject`), "驳回", ""}, {regexp.MustCompile(`(?i)add`), "添加", ""}, {regexp.MustCompile(`(?i)bind`), "绑定", ""}, {regexp.MustCompile(`(?i)trigger`), "触发", ""}, {regexp.MustCompile(`(?i)upload`), "上传", ""}, {regexp.MustCompile(`(?i)write`), "写入", ""}, {regexp.MustCompile(`(?i)read`), "读取", ""}, {regexp.MustCompile(`(?i)search`), "搜索", ""}, {regexp.MustCompile(`(?i)_list(_|$)|list_|_tree|name_list`), "查询", "列表"}, // 查询类兜底动词(get/detail/info/find/query/count/exists 等) {regexp.MustCompile(`(?i)get|detail|info|find|query|count|exists|options|config|summary|activit`), "查询", ""}, } // fallbackRules 非 MCP 标识名(内置工具 / 中文描述 / 通用关键词)的兜底映射表。 type toolLabelRule struct { re *regexp.Regexp label string } var fallbackRules = []toolLabelRule{ {regexp.MustCompile(`(?i)web_search|联网搜索`), "联网搜索"}, {regexp.MustCompile(`(?i)web_fetch|fetch|抓取|网页`), "抓取网页"}, {regexp.MustCompile(`(?i)knowledge|知识库|检索`), "知识库检索"}, {regexp.MustCompile(`(?i)subagent|子任务`), "子任务处理"}, {regexp.MustCompile(`(?i)todo|任务清单`), "任务清单"}, {regexp.MustCompile(`(?i)introspect`), "功能查询"}, {regexp.MustCompile(`(?i)\bcode\b|代码`), "代码分析"}, {regexp.MustCompile(`(?i)grep|搜索|查找`), "搜索内容"}, {regexp.MustCompile(`(?i)glob|查找文件`), "查找文件"}, {regexp.MustCompile(`(?i)read|cat|查看|读取`), "读取文件"}, {regexp.MustCompile(`(?i)write|create|edit|写入|修改`), "写入文件"}, {regexp.MustCompile(`(?i)util_|parse_sn`), "解析序列号"}, {regexp.MustCompile(`(?i)execut|bash|shell|command|执行|运行`), "执行命令"}, } // DescribeTool 根据工具调用 title 返回详细描述(动作 + 对象)。 // // MCP 标识名形态:组合「动作 + 对象」,如 create_issue -> “创建工作项”, // list_work_items -> “查询工作项列表”。 // 其他形态:回退到关键词兜底表;无命中返回 DefaultToolLabel。 func DescribeTool(title string) string { if title == "" { return DefaultToolLabel } // MCP 标识名 → 动作 + 对象 组合 if mcpIdentRe.MatchString(title) { obj := "" for _, r := range objectRules { if r.re.MatchString(title) { obj = r.noun break } } if obj != "" { // 默认动作为“查询”(大多数无动词的工具是读取类) verb, suffix := "查询", "" // 剔除域名噪声后再识别动作,避免 auto_update / update_log 误判为“更新” actionSrc := domainNoiseRe.ReplaceAllString(title, "_") for _, a := range actionRules { if a.re.MatchString(actionSrc) { verb, suffix = a.verb, a.suffix break } } return verb + obj + suffix } } // 回退:内置工具 / 中文描述 / 通用关键词 for _, r := range fallbackRules { if r.re.MatchString(title) { return r.label } } return DefaultToolLabel } // NormalizeStatus 将 ACP / 各来源的工具状态归一化为前端使用的三态: // running / completed / error。 // // pending, in_progress, running -> running // completed -> completed // failed, error -> error // 其他(未知) -> running(先按运行中处理,避免误判为错误) func NormalizeStatus(raw string) string { switch raw { case "pending", "in_progress", "running": return "running" case "completed": return "completed" case "failed", "error": return "error" default: return "running" } }