refactor: 收口技能与专员目录定义

统一 skill 与 specialist 清单,移除旧的 office 执行包与下线对象,并补入 text_to_speech、customer_followup 等当前目录定义与种子数据。
This commit is contained in:
eaiadmin
2026-09-22 23:38:56 +08:00
parent 90031b75f3
commit b7238ad667
148 changed files with 1230 additions and 1710 deletions
+10 -10
View File
@@ -12,7 +12,7 @@
## 2. 当前状态
### 已完成
- ✅ PRD V1.1 最终定稿(docs/PRD.md / 设计稿)
- ✅ PRD V1.1 最终定稿(docs/06_Product_Lines/Historical_PRD_And_Designs/产品需求文档.md / 设计稿)
- ✅ 文档架构搭建(docs/ 体系)
- ✅ 编码规范制定(TOP_CODING_RULES.md / CLAUDE.md / PROJECT_STATE.md)
- ✅ 知识入库体系(BE05)后端代码落地:knowledge_source 表 + 解析/扫描/摄入 + 审批 API + 脚本
@@ -35,7 +35,7 @@
社交社区/讨论区**定死不做**
### 待开始
- ⬜ 按 `docs/01_System_Overall/SY19_Universal_Digital_Worker_Product_Planning.md`
- ⬜ 按 `docs/01_System_Overall/History_And_Retrospectives/系统演进旧稿/SY19_通用数字员工产品规划.md`
将当前项目从“已有专员雏形”进一步收口为“通用数字员工平台 V1.0”
## 3. 已拍板决策
@@ -61,12 +61,12 @@
| D17 | 错题本(学员自助,非学情分析,自测/正式均写)+ 简答题 LLM 评分(`essay` 题型,复用 title_gen 路由,`essay_grade` 不扣点) | 已定(P2 落地) |
| D18 | 突破原「极致极简/杜绝学情分析」边界:新增学员成长体系 = 学习积分+排行榜(游戏化)+ 考试证书(认证)+ 学习档案/能力雷达(学情,学员自助视角);积分规则集中常量可调 | 已定(V1.6 落地) |
| D19 | 部门组织架构(department 字典表,用户以 department 字符串归属、改名同步)+ 按部门学情统计;站内消息通知(考试发布/通过发证/设岗三事件);**社交社区/讨论区定死不做** | 已定(V1.7 落地) |
| D20 | 当前阶段产品路线收口为「先通用、后定制」:先做标准化通用数字员工产品包,不直接追 WorkBuddy 的高自由度路线;第一批优先沉淀知识运营、培训考试、内容生成、任务推进 4 个通用数字员工,后续再长行业包与企业半定制 | 已定(见 `docs/01_System_Overall/SY19_Universal_Digital_Worker_Product_Planning.md`) |
| D20 | 当前阶段产品路线收口为「先通用、后定制」:先做标准化通用数字员工产品包,不直接追 WorkBuddy 的高自由度路线;第一批优先沉淀知识运营、培训考试、内容生成、任务推进 4 个通用数字员工,后续再长行业包与企业半定制 | 已定(见 `docs/01_System_Overall/History_And_Retrospectives/系统演进旧稿/SY19_通用数字员工产品规划.md`) |
| D21 | 前端曾短暂采用「冻结归档」机制保存停用代码;当前已取消该策略,早期历史代码直接删除,不再维护 `frontend/src/_frozen/`。站内通知如需恢复,按当前实现重新设计,不再依赖冻结稿。 | 已更新 |
| D22 | 任务记录**延迟到发出第一条消息时创建**(对齐 WorkBuddy:新建任务只是导航动作,不落库)。「新建任务」只做「回到 /home 开场画布 + 清空当前任务」,任务标题由第一句话决定、专员取输入框 `+` 里先选的那个(`pendingSpecialistKey` 暂存,建任务时作为 `specialist_key` 一并提交,后端已支持)。**不允许存在没聊过天的空任务** —— 原实现点一次落一条 `新任务`,是「最近任务」堆满空行的根因 | 已定(V1.8 落地) |
| D23 | 侧边栏「最近任务」的行菜单(对齐 ChatGPT 悬停 `⋯` + WorkBuddy 任务卡「更多」):**重命名**(就地编辑,回车提交/Esc 取消)、**置顶**(新增 `worker_task.pinned`,排序 `pinned DESC, updated_at DESC`)、**删除**(新增 `DELETE /api/worker/my-tasks/:id`,硬删、无回收站,确认框写明「无法恢复」)。对照后**不做**:分享任务(纯内网无意义)、打开文件夹(Web 无此能力)、保存到工作空间(项目无 workspace 概念)、归档(没有「已归档」入口可找回,等于软删陷阱)。`el-dropdown` 加 `:persistent="false"` —— 默认每行留一份隐藏菜单在 DOM 里,50 条任务就是 50 份 | 已定 |
| D24 | SQLite **定期备份内置进二进制**(不用外部 cron/systemd timer):启动时补一次 + 每小时查是否到期,默认间隔 24h、保留最近 7 份,落在 `data/backups/`(systemd 是 `ProtectSystem=strict`,只放开了 `data/` 可写)。快照用 `VACUUM INTO` 而非 `cp` 主库 —— 边服务边写时 `cp` 可能拷到写了一半的页。产出自检 SQLite 文件头,不合格即删。另提供 `-backup` 子命令供升级/迁移前手工备一份。**边界**:只防误删/误改/写坏,不防整盘损坏,跨机保存仍需人工 | 已定(见 `deploy/DELIVERY.md` 第 7 节) |
| D25 | 平台总架构继续采用 6 层,但第 5 层正式升级为 **对象层(Expert / Skill / App)**;新增与“专家 / 技能”并列的第三类一级对象 **App**,其定位是“长程任务运行壳”而非页面或大技能。任务统一定义为“工作实例容器”,可挂载主 `app`、右栏 `expert`、后台 `skill`;消息流降级为对话轨迹,长程状态由 `app_state + app_event + domain_data` 承载。产品一级导航目标态需完整描述为 **新建任务 / 项目 / 专家·技能·连接器 / 长程APP / 知识库 / 后台管理 / 我的**,其中 `知识库` 被确认为组织级默认必装的内建 App,拥有一级直达入口;其它专题型业务主导航后续应优先收敛为 `app` 并归入“长程APP”。文档锚点:`docs/01_System_Overall/SY22_Role_Skill_App_Unified_Task_Architecture.md` | 已定 |
| D25 | 平台总架构继续采用 6 层,但第 5 层正式升级为 **对象层(Expert / Skill / App)**;新增与“专家 / 技能”并列的第三类一级对象 **App**,其定位是“长程任务运行壳”而非页面或大技能。任务统一定义为“工作实例容器”,可挂载主 `app`、右栏 `expert`、后台 `skill`;消息流降级为对话轨迹,长程状态由 `app_state + app_event + domain_data` 承载。产品一级导航目标态需完整描述为 **新建任务 / 项目 / 专家·技能·连接器 / 长程APP / 知识库 / 后台管理 / 我的**,其中 `知识库` 被确认为组织级默认必装的内建 App,拥有一级直达入口;其它专题型业务主导航后续应优先收敛为 `app` 并归入“长程APP”。文档锚点:`docs/01_System_Overall/SY22_角色技能应用统一任务架构.md` | 已定 |
| D26 | 路由命名正式拆分为三类以避免混同:`ai_route_*` 专指 AI 模型路由;`object_entry_route` 专指 Expert / Skill / App 等业务对象的进入入口;`page_route` 专指普通页面导航。后端 API、前端对象配置与导航配置均按该口径收口;旧 `route / entry_route` 已降为启动时一次性迁移并随后删除的历史列,不再保留为日常兼容字段。 | 已定 |
| D27 | 后端「仓库层」正式更名为**数据访问层**,英文同步改:包 `internal/repository` → `internal/dal`,类型 `XxxRepo` → `XxxDAO`(`TaskRecordDAO` / `SpecialistDAO`…),日志前缀 `[repository]` → `[dal]`。理由是原名的「仓库」是 repository 的直译,中文里与「代码仓库 / git 仓库」同词,而这一层做的事就是数据访问。命名规范见 AR09 §3.1 / §5.6 | 已定 |
@@ -75,13 +75,13 @@
| 文档 | 路径 | 说明 |
|------|------|------|
| PRD | `../docs/PRD.md` | 产品需求文档(V1.1 最终版) |
| PRD | `../docs/06_Product_Lines/Historical_PRD_And_Designs/产品需求文档.md` | 产品需求文档(V1.1 最终版) |
| 设计稿 | `../docs/eaisalestrain_app设计稿.md` | 完整 PRD 中文原稿 |
| DB Schema | `../docs/db_schema.md` | 9 张核心表字段设计 |
| API 文档 | `../docs/api.md` | API 接口定义 |
| 部署文档 | `../docs/deploy.md` | 部署架构与步骤 |
| 变更日志 | `../docs/changelog.md` | 版本变更记录 |
| 知识入库体系 | `../docs/04_Backend/BE05_Knowledge_Ingest_Module.md` | 上传→生成→审批→入库总设计 |
| DB Schema | `../docs/04_Backend/数据库结构.md` | 9 张核心表字段设计 |
| API 文档 | `../docs/04_Backend/接口文档.md` | API 接口定义 |
| 部署文档 | `../docs/02_Architecture/部署文档.md` | 部署架构与步骤 |
| 变更日志 | `../docs/01_System_Overall/变更日志.md` | 版本变更记录 |
| 知识入库体系 | `../docs/04_Backend/BE05_知识导入模块.md` | 上传→生成→审批→入库总设计 |
| 知识源目录 | `assets/knowledge/source/` | 结构化知识源 md(5 份,28 产品 + 20 题) |
| 培训资料目录 | `assets/training/materials/` | 培训课程资产与种子源文件 |
| 编码准则 | `../TOP_CODING_RULES.md` | 编码与调试最高准则 |
@@ -1,7 +1,7 @@
# 知识源入库目录(Knowledge Source Ingest)
> 本目录是「结构化知识源文档」的唯一入库口,与「素材上传流水线」(backend-go/data/kb_data)并行。
> 数据权威源:`../../../../docs/博昇产品与渠道合作表.md`(对齐《客户介绍合作协议》第二条)。
> 数据权威源:`../../../../docs/06_Product_Lines/Business_Materials/博昇产品与渠道合作表.md`(对齐《客户介绍合作协议》第二条)。
---
@@ -68,7 +68,7 @@ pending ──审批通过──▶ approved ──▶ 生效(product active /
## 6. 代码侧已实现(Go)
> 完整设计见 `../../../../docs/04_Backend/BE05_Knowledge_Ingest_Module.md`(知识入库体系总设计)。
> 完整设计见 `../../../../docs/04_Backend/BE05_知识导入模块.md`(知识入库体系总设计)。
- [x] `internal/model/knowledge_source.go` —— 知识源文档表
- [x] `internal/model/knowledge_chunk.go` —— 来源扩展(media_file_id 可空 + knowledge_source_id)
@@ -0,0 +1,54 @@
# sampledata —— 全技能测试样例库
本目录为 **EAI 数字员工平台** 的测试样例数据,用于覆盖并验证平台全部技能(skill)的输入与预期产出。每个子目录对应一个技能(以技能的 key 命名),供接口联调、功能回归、演示与自动化测试复用。
## 目录约定
```
sampledata/
README.md # 本文件:总索引与使用说明
shared/ # 跨技能共用的背景素材(公司简介、业务上下文等)
<skill-key>/ # 每个技能一个子目录
README.md # 该技能:用途 / 样例文件 / 调用方式 / 期望产出
input.* # 输入样例(txt / md / json / 图片 / 音频)
expected/ # (可选)期望产出参考
```
## 技能清单与覆盖情况
| 技能 key | 技能名 | 样例目录 | 实现状态 |
| --- | --- | --- | --- |
| audio-transcribe | 语音转写 | `audio_transcribe/` | 占位 |
| batch-extract | 批量抽取 | `batch_extract/` | 占位 |
| contract-brief | 合同要点提炼 | `contract_brief/` | 已实现 |
| contract-review | 合同审查 | `contract_review/` | 占位 |
| copy-proofreading | 文案校对 | `copy_proofreading/` | 占位 |
| document-translate | 文档翻译 | `document_translate/` | 占位 |
| interview-summary | 面试纪要 | `interview_summary/` | 已实现 |
| longform-writing | 长文写作 | `longform_writing/` | 已实现 |
| meeting-minutes | 会议纪要 | `meeting_minutes/` | 已实现 |
| mind-map | 思维导图 | `mind_map/` | 已实现 |
| ocr-understanding | OCR 图文理解 | `ocr_understanding/` | 已实现 |
| policy-rewrite | 政策解读改写 | `policy_rewrite/` | 已实现 |
| ppt-generation | PPT 生成 | `ppt_generation/` | 已实现 |
| progress-report | 周报 / 日报 | `progress_report/` | 已实现 |
| report-generation | 报告生成 | `report_generation/` | 已实现 |
| smart-assistant | 通用助手 | `smart_assistant/` | 占位 |
| table-cleanup | 表格清理 | `table_cleanup/` | 已实现 |
| text-to-speech | 文字转语音 | `text_to_speech/` | 已实现 |
> 「占位」指该技能目前仅有 manifest 定义、尚无专属运行时实现,样例仍可用来预置输入。
## 使用方式
1. **人工联调**:直接以 `input.*` 内容作为相应接口的请求体,对照 `expected/` 检查产出。
2. **前端演示**:进入对应专员的画布,粘贴 `input.*` 文本,触发技能执行。
3. **自动化测试**:样例文件均为纯文本 / JSON / 标准格式,可直接被 Go 或脚本读取并断言结果。
## 公共背景
所有样例统一围绕以下业务背景,保证跨技能素材一致:
- 平台:博昇数字员工平台
- 业务线:资本咨询、资质认定辅导、AI 咨询与落地、企业级 AI 工具与平台
- 方法论:顾问式销售(FABE / SPIN / LSCPA)
- 详见 [shared/公司背景.md](shared/公司背景.md)
@@ -0,0 +1,16 @@
# 语音转写(audio-transcribe)样例
## 用途
把音频里的语音转成文字,用于会议口述、培训录音转文档。
## 样例文件
- `input/上午会议口述.mp3` —— 一段口述会议的语音(中文),内容涉及 10 月美国考察、云帆科技高企材料、销售培训新课表。
## 调用方式
- 接口:`POST /api/audio/transcribe`(multipart 上传 `file`,可选 `language=zh`)
- 把 `input/上午会议口述.mp3` 作为上传文件。
## 期望产出
一份转写文本,应包含「10月美国考察名单」「云帆科技高新认定材料」「销售培训新课表」三个要点。
> 说明:本技能当前为「占位」实现(仅有 manifest),实际转写依赖后端 Ollama whisper 服务;样例仍可用于接口预置。
@@ -0,0 +1,17 @@
# 批量抽取(batch-extract)样例
## 用途
从多份文档中批量抽取结构化字段(如金额、日期、企业名、条款),用于合同/报价/申报材料的批量录入。
## 样例文件
- `input/材料集/` 放置要批量抽取的文档;每个文档给一段可抽取的结构化表述。
- `input/期望字段.json` —— 声明每份文档应抽出的字段与示例值。
## 调用方式
- 接口:`POST /api/batch/extract` 或 `POST /api/batch/files`
- 把 `input/材料集/*.md` 作为待抽取输入。
## 期望产出
每份文档对应的 JSON 字段表,可与 `input/期望字段.json` 对照。
> 说明:本技能当前为「占位」实现,样例用于接口预置与契约设计。
@@ -0,0 +1,27 @@
{
"说明": "每份文档应抽取的字段,用于校验批量抽取结果",
"documents": [
{
"doc": "云帆科技",
"fields": [
{"字段": "企业名称", "类型": "string"},
{"字段": "所属行业", "类型": "string"},
{"字段": "营业收入", "类型": "number"},
{"字段": "研发费用", "类型": "number"},
{"字段": "科技人员占比", "类型": "percent"},
{"字段": "主要知识产权", "类型": "list"},
{"字段": "申请事项", "类型": "string"}
]
},
{
"doc": "星海资本",
"fields": [
{"字段": "机构名称", "类型": "string"},
{"字段": "联系人", "类型": "string"},
{"字段": "意向", "类型": "string"},
{"字段": "拟投资规模", "类型": "string"},
{"字段": "关注方向", "类型": "string"}
]
}
]
}
@@ -0,0 +1,10 @@
# 云帆科技申报材料(批量抽取样例文档 1)
企业名称:云帆科技
类型:民营有限责任公司
所属行业:软件与信息技术服务业
2025 年营业收入:4800 万元
研发费用:280 万元
科技人员占比:30%
主要知识产权:软件著作权 6 项
申请事项:高新技术企业认定
@@ -0,0 +1,7 @@
# 星海资本洽谈纪要(批量抽取样例文档 2)
机构名称:星海资本
联系人:周总监
意向:随行 2026-10-18 美国考察,评估投资标的
拟投资规模:单笔 1000 万元起
关注方向:AI 落地、渠道复制能力
@@ -0,0 +1,16 @@
# 合同要点提炼(contract-brief)样例
## 用途
从合同文本中提炼要点、关键条款与风险点,供决策与审批用。
## 样例文件
- `input/合同简介.md` —— 一份合作框架类合同的精简文本。
- `expected/` —— (可选)期望的要点与风险清单。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`contract-brief`,把 `input/合同简介.md` 作为 input_text 粘贴)—— 需在已建任务下执行。
## 期望产出
要点提炼(合作标的、付款条件、责任条款、保密、风险项)供后续决策。
> 说明:本技能为「已实现」技能,走 office 运行时,用 AI + 知识库生成要点。
@@ -0,0 +1,11 @@
# 合作框架合同(精简样例)
甲方:博昇数字员工平台(下称「甲方」)
乙方:云帆科技(下称「乙方」)
1. **合作内容**:甲方为乙方提供高新技术企业认定辅导及 AI 落地咨询服务,服务期自 2026-01-01 至 2026-06-30。
2. **费用与支付**:服务费总额 60 万元。合同签订后 3 日内支付 30% 作为启动款;高企申报受理后支付 40%;认定通过后 30 日内支付剩余 30%。
3. **交付**:甲方按里程碑交付《申报材料》《AI 试点方案》等成果,成果知识产权归甲方所有,乙方享有使用权。
4. **保密**:双方对合作中知悉的商业秘密负保密义务,保密期至合作结束后 3 年。
5. **违约责任**:任何一方逾期履行主要义务,应向对方支付合同金额 10% 的违约金;累计逾期超 30 日可解除合同。
6. **争议解决**:协商不成时,提交甲方所在地人民法院诉讼解决。
@@ -0,0 +1,16 @@
# 合同审查(contract-review)样例
## 用途
对完整合同做合规审查、识别风险条款并给出修改建议。
## 样例文件
- `input/采购合同.md` —— 一份采购类合同全文样例。
- `expected/审查意见.md` —— (可选)期望的风险点与修改建议清单。
## 调用方式
- 接口:`POST /api/contract/review`(以 `input/采购合同.md` 为合同文本)。
## 期望产出
风险条款清单(付款、违约、交付标准、责任豁免等)+ 逐条修改建议。
> 说明:同名技能 `contract-review` 当前为「占位」实现,核心审查逻辑尚未落地;但平台已有独立契约审查接口可用于联调。
@@ -0,0 +1,14 @@
# 采购合同(样例全文)
甲方(采购方):博昇数字员工平台
乙方(供应商):上海某软件股份有限公司
## 条款
1. 采购内容:企业智能体开发平台 License 一套,含源码交付。
2. 金额:人民币 320 万元,含税。
3. 付款:预付款 50% 于合同生效后支付;验收后支付 45%;质保期(12 个月)结束后支付 5%。
4. 交付与验收:乙方收到预付款后 90 日内完成交付,甲方在 15 个工作日内验收。
5. 违约:乙方逾期交付,每逾期一日按合同金额 0.5% 支付违约金;甲方逾期付款同上。
6. 责任限制:在任何情况下,乙方对甲方的赔偿总额不超过合同金额。
7. 保密:乙方对甲方业务数据负保密义务,保密期 5 年。
8. 知识产权:交付源码的著作权归甲方。
@@ -0,0 +1,16 @@
# 文案校对(copy-proofreading)样例
## 用途
检查文案的错别字、语法、标点与合规表述,输出修改建议。
## 样例文件
- `input/待校对文案.md` —— 一段含常见错误的宣传/话术文案。
- `expected/校对结果.md` —— (可选)期望的纠错清单。
## 调用方式
- 接口:`POST /api/copy/proofread` 或 `GET /api/copy/quick`(快速校对)。
## 期望产出
定位并逐条列出错字、标点、重复、合规风险,给出替换建议。
> 说明:技能 `copy-proofreading` 当前为「占位」;平台有独立校对接口可用于联调。
@@ -0,0 +1,9 @@
# 待校对文案(样例,含刻意错误)
博昇数字员工平台,专注为企业提**供**「数字化经营增**长**」解决方案。我们提供高新企业认定辅助、专**精**特新培育、AI落地实施的一站式服务。
- 高新技术企业认定,享**受**所得税优惠;
- Ai 与人工结合,顾问式销售陪**办**交付;
- 提供企业级智能体平**台**,帮**主**提效。
如有**愿**,请联系我们:**4006-1234-5678**,期待与您共创未来!
@@ -0,0 +1,15 @@
# 文档翻译(document-translate)样例
## 用途
中英互译文档,保留结构与术语一致性。
## 样例文件
- `input/中文简介.md` —— 一段公司中英双语对照素材的中文版。
## 调用方式
- 接口:`POST /api/document/translate`(`content` 传入文本,`target_language` 指定目标语言)。
## 期望产出
对照翻译结果,术语(高企认定、智能体、顾问式销售等)应保持统一译法。
> 说明:技能 `document-translate` 当前为「占位」;平台有独立翻译接口可用于联调。
@@ -0,0 +1,3 @@
# 公司中文简介(供翻译)
博昇数字员工平台,聚焦资本咨询、资质认定辅导、AI 咨询与实施、企业级 AI 工具与平台建设。我们以顾问式销售方法论服务成长型企业,覆盖制造、科技与拟上市企业,提供从商业模式梳理到高企认定申报、再到 AI 落地交付的一站式陪伴服务。
@@ -0,0 +1,16 @@
# 面试纪要(interview-summary)样例
## 用途
把面试双方问答整理成纪要,提炼候选人能力评估、亮点与风险。
## 样例文件
- `input/面试记录.md` —— 一段 HR 与候选人对话速记。
- `expected/面试纪要.md` ——(可选)期望的纪要结构。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`interview-summary`,粘贴 `input/面试记录.md`)。
## 期望产出
候选人基本信息、能力评估、匹配度、亮点与风险、建议结论。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,11 @@
# 面试记录(样例速记)
候选人:陈先生,目标岗位「AI 解决方案顾问」
面试官:王助理(HR)+ 李董事长
- 陈先生有 6 年企业服务售前经验,服务过制造业与 SaaS 客户,主导过 3 个 AI 项目 POC。
- 熟悉高企认定流程并有 2 个成功申报案例。
- 沟通表达清晰,能用客户语言讲清「智能体 / 数字员工」的价值;对 FABE、SPIN 方法有基础认知。
- 期望薪资 2.2 万/月,可接受出差(含海外考察)。
- 风险点:此前公司产品偏 SaaS 标准化,独立方案设计经验略少;入职后需补充定制化方案训练。
- 面试评价:总体匹配度高,建议进入二面并安排一次现场方案演练。
@@ -0,0 +1,16 @@
# 长文写作(longform-writing)样例
## 用途
根据主题与要点生成结构化长文(公众号推文、深度文章)。
## 样例文件
- `input/写作主题.md` —— 主题与结构要求。
- `expected/文章样本.md` ——(可选)期望的开头与章节结构。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`longform-writing`,粘贴 `input/写作主题.md`)。
## 期望产出
一篇标题 + 引言 + 若干章节(含小标题)+ 结尾的长文,主题统一采用平台业务。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,14 @@
# 长文写作素材
标题方向:《企业搞 AI 落地,为什么需要「数字员工」而不是一堆工具?》
目标读者:制造与科技型企业的经营者。
结构要求:
1. 开场:抛出企业 AI 落地常见的误区(买工具 ≠ 有用)。
2. 第二段:什么是数字员工 / 智能体,与传统工具的区别。
3. 第三段:从「顾问式销售」到「陪伴式交付」的价值闭环。
4. 第四段:结合高企认定、AI 试点、流程智能化三个具体场景。
5. 结尾:给经营者的行动建议。
行文要求:口语化中带专业,少堆术语,多用具体例证。
@@ -0,0 +1,17 @@
# 会议纪要(meeting-minutes)样例
## 用途
把会议速录/要点整理成会议纪要:主题、结论、行动项。
## 样例文件
- `input/会议速录.md` —— 一段商务会议现场对话速记(3 位男性:两位董事长 + 一位助理,讨论 2026-10-18 美国考察议程)。
- `expected/会议纪要.md` —— 已人工整理的纪要参考(可直接对比产出)。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`meeting-minutes`,把 `input/会议速录.md` 作为输入)。
- 也可直接用画布技能触发。
## 期望产出
会议基本信息、参会人、议题讨论要点、决议、行动项(负责人+期限)。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,25 @@
# 会议速录(样例)—— 2026-10-18 美国企业考察议程讨论会
参会:张董事长(集团)、李董事长(海外业务)、王助理
时间:2026-09-18 14:00
**张董事长(开场):**
> 今天先把 10 月 18 日这批去美国的考察定下来,目标要清晰,别走马观花。李董先谈谈这次最想解决什么问题。
**李董事长:**
> 我的判断三件事:一是把北美代理和分销的意向摸清楚;二看两家对标企业在新品和市场打法上的差距;三我们有一个潜在技术合作方,想当面谈合作框架。考察不贪多,聚焦 3-4 家,行程 7 天左右。
**张董事长:**
> 同意聚焦。天数我建议 10 月 18 日出发、10 月 25 日返程,共 8 天。去掉飞行和时差,有效商务时间约 5 个工作日,安排紧凑些。
**王助理:**
> 补充落地信息:美国东岸适合先落纽约,再沿波士顿到芝加哥一线走,目标企业大多在东岸中段。我可以按这个排城市和对接顺序,控差旅成本。
**李董事长:**
> 关键是派谁带队、谁去谈。考察要有决策权的人在场。建议张董挂帅,我带市场团队随行,王助理统筹日程和签证。
**张董事长:**
> 可以,基调定了:目标=渠道对接+技术合作+竞品对标;规模=4-5 人小团队;周期=10 月 18 日-25 日;美国东岸三城。把每一项落到人和时间上。
**王助理(小结):**
> 我整理成行动项:名单与签证、企业走访预约、技术合作洽谈预案、预算审批、宣传复盘,每项挂责任人。
@@ -0,0 +1,16 @@
# 思维导图(mind-map)样例
## 用途
把一段文字整理成结构化思维导图(主题-分支-子项)。
## 样例文件
- `input/产品规划要点.md` —— 一段「客户成功产品规划」的描述,作为导图根节点素材。
- `expected/导图结构.md` ——(可选)期望的分支层级参考。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`mind-map`,粘贴 `input/产品规划要点.md`)。
## 期望产出
以「客户成功产品」为根的树形结构:核心价值 / 功能模块 / 落地阶段 / 度量指标。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,13 @@
# 客户成功产品规划要点
根节点:客户成功产品
主分支:
1. 核心价值:围绕高企认定、AI 落地、顾问式销售,让客户看得见「数字员工」的回报。
2. 功能模块:
- 知识库 / 规则库
- 专员与任务画布
- 技能市场(会议纪要、PPT、报告等)
- 审批与交付物流转
3. 落地阶段:导入期 → 试用期 → 正式付费 → 复购扩展。
4. 度量指标:激活率、任务完成率、续费率、NPS。
@@ -0,0 +1,16 @@
# OCR 图文理解(ocr-understanding)样例
## 用途
识别图片中的文字并结构化输出(OCR / 图文理解)。
## 样例文件
- `images/公司介绍_帧1.png` —— 从公司介绍视频抽取的一帧画面,作为图片输入样例。
## 调用方式
- 接口:`POST /api/skills/office/ocr`(multipart 上传图片 `file`,带 `task_id`;如需可带 `prompt`)。
- 把 `images/公司介绍_帧1.png` 作为上传图片。
## 期望产出
识别出的文本(text)+ 行级坐标(lines)+ 引擎与上传信息,便于下游进一步整理。
> 说明:技能为「已实现」,走 office 自定义 OCR(PaddleOCR 脚本)运行时。
@@ -0,0 +1,8 @@
# OCR 识别要求(样例)
图片:`../images/公司介绍_帧1.png`(公司介绍视频画面)
识别目标:提取画面中的公司名称、业务关键词、显著文案。
Prompt 建议:
> 请识别图中文字并整理为:公司名称、主营业务、关键卖点 三块。
@@ -0,0 +1,16 @@
# 政策解读改写(policy-rewrite)样例
## 用途
把政策/官方文本改写为通俗、可执行的企业解读。
## 样例文件
- `input/高企认定政策原文.md` —— 一段高新技术企业认定政策要点。
- `expected/通俗解读.md` ——(可选)期望的客户向解读。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`policy-rewrite`,粘贴 `input/高企认定政策原文.md`)。
## 期望产出
把「八大条件」改写为老板能听懂的话 + 企业自查清单口径的解释。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,12 @@
# 高新技术企业认定(政策原文要点样例)
依据《高新技术企业认定管理办法》,认定的硬性条件主要包括:
1. 企业须在中国境内注册成立一年以上(须正常经营)。
2. 对其主要产品(服务)的核心技术拥有自主知识产权(专利/软著等)。
3. 高新技术产品(服务)收入占总收入的比例不低于 60%。
4. 科技人员占当年职工总数的比例不低于 10%。
5. 近三个会计年度的研究开发费用总额占销售收入总额的比例须达到规定标准(销售收入 ≤ 5000 万:5%;5000 万-2 亿:4%;>2 亿:3%)。
6. 创新能力评价须达到相应要求(知识产权、科技成果转化、成长性等指标综合评分)。
7. 企业申请认定前一年内未发生重大安全、质量事故或严重环境违法行为。
8. 须符合《国家重点支持的高新技术领域》范围。
@@ -0,0 +1,16 @@
# PPT 生成(ppt-generation)样例
## 用途
按提纲把内容排成演示文稿(幻灯片结构 + 页面要点)。
## 样例文件
- `input/汇报提纲.md` —— 一段「赴美考察筹备汇报」的提纲。
- `expected/幻灯片结构.md` ——(可选)期望的页序与每页标题。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`ppt-generation`,粘贴 `input/汇报提纲.md`)。
## 期望产出
一份页序清晰的 PPT 框架:封面 / 背景 / 目的 / 行程 / 预算 / 分工 / 时间表 / 下一步。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,12 @@
# 赴美考察筹备汇报(PPT 提纲)
需要做一份向董事会汇报的 PPT,内容:
- 封面:2026 美国商务考察筹备方案
- 背景与目的:北美渠道对接、技术合作洽谈、竞品对标
- 考察概要:10 月 18 日-25 日,美国东岸(纽约-波士顿-芝加哥),4-5 人
- 行程安排:三城走访 3-4 家企业,按天排
- 预算概览:机票、酒店、交通、接待
- 分工表:张董带队 / 李董带市场 / 王助理统筹
- 关键时间节点:9 月 30 日签注、10 月 8 日企业预约、10 月 12 日洽谈预案
- 下一步与风险
@@ -0,0 +1,16 @@
# 周报 / 日报(progress-report)样例
## 用途
把零散的工作条目整理成结构化的周报/日报(进展、风险、下一步)。
## 样例文件
- `input/本周工作流水.md` —— 一周工作流水记录。
- `expected/周报.md` ——(可选)期望的周报结构。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`progress-report`,粘贴 `input/本周工作流水.md`)。
## 期望产出
本周进展 / 风险事项 / 下步计划 三段式周报。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,8 @@
# 本周工作流水(9-14 ~ 9-18)
- 周一:梳理云帆科技高新申报材料缺口清单,补齐研发费用账目;约见星海资本,谈随行考察事宜。
- 周二:更新《赴美考察企业走访清单》,确定 3 家候选;李董出差拜访 1 家对标企业。
- 周三:组织 AI 顾问面试 2 场,推进 1 名候选人到二面;拟写《技术合作洽谈预案》初稿。
- 周四:跟进客户新签 1 单(资质认定辅导),推动佣金结算;协调签证资料。
- 周五:内部周例会,复盘考察筹备进度;输出本周遗留事项:考察预算未最终确认、1 家候选企业预约待回复。
- 下周计划:锁定考察人数与预算、完成企业预约、推进新员工培训课表排期。
@@ -0,0 +1,18 @@
# 报告生成(report-generation)样例
## 用途
根据调研/数据/要点生成正式报告,并导出 PDF/DOCX/PPTX/XLSX。
## 样例文件
- `input/调研数据.md` —— 一份考察/调研的一手数据与要点。
- `expected/报告结构.md` ——(可选)期望的报告章节结构。
## 调用方式
- 生成:`POST /api/report/generate`(粘贴 `input/调研数据.md`)。
- 导出:`POST /api/report/export/pdf` / `.../docx` / `.../pptx` / `.../xlsx`。
- 预览:`POST /api/report/preview`。
## 期望产出
结构化报告(摘要 / 发现 / 分析 / 建议 / 附件)+ 可导出的文件。
> 说明:技能为「已实现」,有独立处理器并按所选格式导出文件。
@@ -0,0 +1,15 @@
# 赴美考察调研数据(样例输入)
背景:2026-10-18 至 25 日赴美国东岸(纽约-波士顿-芝加哥)商务考察。
调研要点:
- 对标企业 A:渠道以区域分销为主,年增长约 18%,重视本地化服务。
- 潜在技术合作方 B:在智能体/流程自动化上有成熟模块,愿以联合开发形式合作。
- 北美市场共性:售后与本地合规是客户核心关切;报价普遍高于国内。
拟结论方向:
1. 渠道策略建议采用「区域分销 + 本地服务伙伴」双轨。
2. 技术合作宜从联合开发 POC 切入,6 个月内出试用版。
3. 报价需含本地化实施与合规项,附后续服务包。
(该样例输入供 report/generate 生成正式考察报告)
@@ -0,0 +1,35 @@
# 公司背景(SampleData 共用素材)
> 供 sampledata 下所有技能样例复用,保持业务上下文一致。测试时可直接把本文件内容作为「知识来源」粘贴到任务上下文里。
## 公司简介
博昇是一家专注「企业数字化转型与经营增长」的专业服务机构,围绕资本运作、资质认定辅导、AI 落地实施三大主线,为成长型企业提供顾问式服务。
- 主营业务:资本咨询、资质认定辅导、AI 咨询与实施、企业级 AI 工具与平台建设
- 客户群体:制造业、科技型中小企业、拟上市 / 上新三板企业
- 服务模式:顾问式销售 + 陪伴式交付,顾问深扎行业,按里程碑推进
## 业务线
1. **资本咨询与股权融资**:商业模式梳理、估值、融资结构设计、尽调资料准备、路演材料与投资对接。
2. **资质认定辅导**:高新技术企业认定、专精特新梯度培育、各类政府补贴申报的合规辅导。
3. **AI 咨询与实施**:AI 落地可行性评估、POC 试点、数据治理、智能体(数字员工)建设。
4. **企业级 AI 工具与平台**:低代码 + 智能体平台搭建,覆盖销售、培训、审批、知识运营等场景。
## 销售方法论
- **FABE**:特征 → 优势 → 利益 → 证据,先讲客户听得懂的价值。
- **SPIN**:背景问题 → 难点问题 → 暗示问题 → 需求-效益问题。
- **LSCPA**:倾听 → 共担 → 澄清 → 提出方案 → 行动。
## 高频对象(样例里统一的人名 / 公司,便于对账)
| 对象 | 角色 |
| --- | --- |
| 张董事长 | 集团董事长 |
| 李董事长 | 海外业务板块董事长 |
| 王助理 | 总裁办助理 |
| 云帆科技 | 客户(制造企业,拟申报高企) |
| 星海资本 | 投资机构 |
| 2026-10-18 美国考察 | 集团海外商务考察项目 |
@@ -0,0 +1,15 @@
# 通用助手(smart-assistant)样例
## 用途
未指定专员的默认对话:答疑、查资料、推荐专员与拆任务。
## 样例文件
- `input/示例提问.md` —— 几类典型提问(答疑类 / 资料类 / 任务类)。
## 调用方式
- 接口:`POST /api/chat/message`(以 `input/示例提问.md` 中的提问为消息)。
## 期望产出
先判断类型再作答:能从知识库答则答;能推荐专员则点明「为什么是这个专员、需要你提供什么」。
> 说明:技能当前为「占位」(仅有 manifest),实际依赖通用 AI 对话,样例用于预置和口径设计。
@@ -0,0 +1,7 @@
# 通用助手示例提问
1. (答疑类)「高新技术企业认定对我们的所得税有什么好处?」
2. (答疑类)「我们公司能做 AI 落地吗?可以先做什么?」
3. (资料类)「平台里有没有介绍产品卖点的资料?」
4. (任务类)「我想把一段会议内容整理成纪要并在项目里留痕。」
5. (任务类)「下周要给董事会做汇报,帮我准备一份考察方案的 PPT。」
@@ -0,0 +1,15 @@
# 表格清理(table-cleanup)样例
## 用途
清洗脏表格:去空行、合并重复、纠正格式、补全字段名。
## 样例文件
- `input/脏表格.md` —— 一份带空行、错位、重复项的表格。
## 调用方式
- 接口:`POST /api/skills/office/execute`(skill_key=`table-cleanup`,粘贴表格文本)。
## 期望产出
规整后的表格(统一列名、补齐缺失、标注需人工确认项)。
> 说明:技能为「已实现」,走 office 运行时。
@@ -0,0 +1,15 @@
# 出差名单表(含脏数据样例)
第一行应为表头,但混入多余说明行,存在空行、重复与格式不一致:
`以下为赴美考察名单`
| 姓名 | 部门 | 职务 | 备注 |
| --- | --- | --- | --- |
| 张董 | 集团 | 董事长 | 带队 |
| 李董 | 海外 | 董事长 | 市场 |
| 王助理 | 总裁办 | 助理 | 签证 |
| 王助理 | 总裁办 | 助理 | 签证(重复) |
| (空) | | | |
| 张 董 | 集团 | 董事长 | 带队(与首行重复,空格差异) |
| 陈经理 | 市场 | 经理 | 待确认 |
@@ -0,0 +1,18 @@
# 文字转语音(text-to-speech)样例
## 用途
把文本合成语音(MP3),用于通知播报、培训内容朗读等。
## 样例文件
- `input/待合成文本.md` —— 一段可合成语音的文本(考察通知 + 一段产品介绍)。
- `audio/考察通知_男声.mp3` —— 已用本地 edge-tts 生成的一个参考输出(男声,可直接试听)。
## 调用方式
- 接口:`POST /api/skills/office/tts`(JSON:`{task_id, text, voice?, rate?}`)。
- 试听:`GET /api/tts/audio/<filename>`。
- 默认音色 `zh-CN-XiaoxiaoNeural`;示例参考输出使用男声 `zh-CN-YunxiNeural`。
## 期望产出
一段 MP3 音频产物 + 任务运行记录与交付物(artifact),音频 URL 可在线播放/下载。
> 说明:技能为「已实现」(本项目新增),调用本地 edge-tts。
@@ -0,0 +1,7 @@
# 待合成语音文本(样例)
文本 1(通知):
> 各位同事,我们定于十月十八日赴美国进行商务考察,为期八天,主要对接北美渠道与潜在技术合作方。请大家提前做好行程与签证准备。
文本 2(产品介绍,供培训朗读):
> 博昇数字员工平台,把知识库、专员与技能、审批和交付物流转整合在一起,让销售、培训和日常办公都能被 AI 接手。
@@ -37,7 +37,7 @@
│ ├── eai_agentplatform.db # SQLite(首启自动建)
│ ├── backups/ # 定期备份(服务自动维护,见第 7 节)
│ └── kb_data/ # 素材 + 提取缓存
└── (前端静态资源由 Nginx 托管,见 ../docs/deploy.md)
└── (前端静态资源由 Nginx 托管,见 ../docs/02_Architecture/部署文档.md)
```
---
@@ -12,7 +12,7 @@ import (
"eai_agentplatform/backend/internal/web"
)
// —— 积分规则(游戏化成长值,集中一处便于调整,见 docs/changelog.md 待确认项)——
// —— 积分规则(游戏化成长值,集中一处便于调整,见 docs/01_System_Overall/变更日志.md 待确认项)——
const (
ptFirstCompany = 10 // 首次浏览公司介绍
ptFirstProduct = 2 // 首次浏览单个产品
@@ -156,6 +156,8 @@ func RegisterRoutes(r *gin.Engine, cfg *config.Config) {
r.POST("/api/batch/files", middleware.Auth(cfg), ExtractFromFiles)
r.POST("/api/skills/office/execute", middleware.Auth(cfg), skillapi.ExecuteOfficeSkill)
r.POST("/api/skills/office/ocr", middleware.Auth(cfg), skillapi.ExecuteOfficeSkillOCR)
r.POST("/api/skills/office/tts", middleware.Auth(cfg), skillapi.ExecuteOfficeSkillTTS)
r.GET("/api/tts/audio/:filename", middleware.Auth(cfg), skillapi.ServeTTSAudio)
r.POST("/api/chat/message", middleware.Auth(cfg), HandleChatMessage)
// 语音工具
@@ -199,7 +199,7 @@ func ExecuteOfficeSkillOCR(c *gin.Context) {
TaskID: task.ID,
SpecialistKey: task.SpecialistKey,
ActionKey: "ocr-understanding",
ActionTitle: "OCR / 图文理解",
ActionTitle: "图片/扫描件智能识别",
ActionType: "ocr",
Status: "done",
InputJSON: string(inputJSON),
@@ -0,0 +1,192 @@
package skillapi
import (
"crypto/sha1"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"eai_agentplatform/backend/internal/config"
"eai_agentplatform/backend/internal/middleware"
"eai_agentplatform/backend/internal/model"
specialistruntime "eai_agentplatform/backend/internal/specialists/runtime"
"eai_agentplatform/backend/internal/store"
"eai_agentplatform/backend/internal/web"
)
// ttsDefaultVoice 默认中文女声(edge-tts 自带音色)。
const ttsDefaultVoice = "zh-CN-XiaoxiaoNeural"
// ttsAudioDir 存放合成 MP3 的目录,与公众号配图一致放在数据库同级的 tts_audio 下。
func ttsAudioDir() string {
cfg := config.Load()
return filepath.Join(filepath.Dir(cfg.DBPath), "tts_audio")
}
func defaultTTSText(text string) string {
text = strings.TrimSpace(text)
if text == "" {
return "这是一个文字转语音的示例。"
}
return text
}
// ExecuteOfficeSkillTTS POST /api/skills/office/tts —— 文字转语音。
// body: { "task_id": <任务ID>, "text": "要朗读的文字", "voice": "音色(可空)", "rate": "语速(可空, 如 +0% / -10%)" }
func ExecuteOfficeSkillTTS(c *gin.Context) {
user := middleware.CurrentUser(c)
if user == nil {
web.Fail(c, web.NewAuthError("未登录"))
return
}
var req struct {
TaskID uint `json:"task_id"`
Text string `json:"text"`
Voice string `json:"voice"`
Rate string `json:"rate"`
}
if err := c.ShouldBindJSON(&req); err != nil {
web.Fail(c, web.NewBadRequest("请求参数错误"))
return
}
if req.TaskID == 0 {
web.Fail(c, web.NewBadRequest("task_id 必填"))
return
}
text := defaultTTSText(req.Text)
voice := strings.TrimSpace(req.Voice)
if voice == "" {
voice = ttsDefaultVoice
}
rate := strings.TrimSpace(req.Rate)
task, ok := loadMyOwnedTask(c, user, req.TaskID)
if !ok {
return
}
now := time.Now()
dir := ttsAudioDir()
if err := os.MkdirAll(dir, 0o755); err != nil {
web.Fail(c, web.NewBadRequest("无法创建音频目录"))
return
}
sum := sha1.Sum([]byte(text + "|" + voice))
filename := fmt.Sprintf("task_%d_%s_%x.mp3", task.ID, now.Format("20060102-150405"), sum[:6])
audioPath := filepath.Join(dir, filename)
args := []string{"-m", "edge_tts", "--text", text, "--voice", voice, "--write-media", audioPath}
if rate != "" {
args = append(args, "--rate", rate)
}
cmd := exec.Command("python3", args...)
var stderr strings.Builder
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
web.Fail(c, web.NewBadRequest("语音合成失败:"+firstNonEmpty(strings.TrimSpace(stderr.String()), err.Error())))
return
}
if _, err := os.Stat(audioPath); err != nil {
web.Fail(c, web.NewBadRequest("语音合成失败:未生成音频文件"))
return
}
audioURL := "/api/tts/audio/" + filename
inputJSON, _ := json.Marshal(gin.H{"text": text, "voice": voice, "rate": rate})
outputJSON, _ := json.Marshal(gin.H{
"summary": "已将文本合成为语音,可在线播放或下载。",
"text": text,
"voice": voice,
"audio_url": audioURL,
})
logsJSON, _ := json.Marshal([]string{
"接收文字转语音请求",
fmt.Sprintf("调用本地 TTS 引擎(voice=%s)", voice),
"已生成 MP3 音频",
})
artifactPayloadJSON, _ := json.Marshal(gin.H{
"text": text,
"voice": voice,
"audio_url": audioURL,
"format": "mp3",
})
sourceRefsJSON, _ := json.Marshal([]string{"本地 edge-tts"})
var run model.TaskRun
var artifact model.TaskArtifact
err := store.DB.Transaction(func(tx *gorm.DB) error {
run = model.TaskRun{
TaskID: task.ID,
SpecialistKey: task.SpecialistKey,
ActionKey: "text-to-speech",
ActionTitle: "文字转语音",
ActionType: "audio",
Status: "done",
InputJSON: string(inputJSON),
OutputJSON: string(outputJSON),
LogsJSON: string(logsJSON),
StartedAt: now,
FinishedAt: &now,
}
if err := tx.Create(&run).Error; err != nil {
return err
}
artifact = model.TaskArtifact{
TaskID: task.ID,
SpecialistKey: task.SpecialistKey,
Title: fmt.Sprintf("%s - 语音合成结果", task.Title),
ArtifactType: "audio",
Status: specialistruntime.ArtifactStatusDraft,
ContentText: text,
ContentJSON: string(artifactPayloadJSON),
SourceRefsJSON: string(sourceRefsJSON),
CreatedByRunID: &run.ID,
}
if err := tx.Create(&artifact).Error; err != nil {
return err
}
task.CurrentRunID = &run.ID
task.CurrentResult = "已将文本合成为语音并生成 MP3。"
task.Status = specialistruntime.TaskStatusDraft
task.LastTriggeredAt = &now
return tx.Save(&task).Error
})
if err != nil {
web.Fail(c, web.NewBadRequest("保存结果失败:"+err.Error()))
return
}
freshTask, _ := reloadTask(task.ID)
web.OK(c, gin.H{
"audio_url": audioURL,
"text": text,
"voice": voice,
"rate": rate,
"run": run,
"artifact": artifact,
"task": freshTask,
})
}
// ServeTTSAudio GET /api/tts/audio/:filename —— 提供生成的 MP3 音频文件。
func ServeTTSAudio(c *gin.Context) {
filename := filepath.Base(strings.TrimSpace(c.Param("filename")))
if filename == "." || filename == "" {
web.Fail(c, web.NewNotFoundError("音频不存在"))
return
}
fullPath := filepath.Join(ttsAudioDir(), filename)
if _, err := os.Stat(fullPath); err != nil {
web.Fail(c, web.NewNotFoundError("音频不存在"))
return
}
c.File(fullPath)
}
@@ -7,7 +7,6 @@ import (
contractreview "eai_agentplatform/backend/internal/skills/packages/contract_review"
copyproofreading "eai_agentplatform/backend/internal/skills/packages/copy_proofreading"
documenttranslate "eai_agentplatform/backend/internal/skills/packages/document_translate"
emaildrafting "eai_agentplatform/backend/internal/skills/packages/email_drafting"
interviewsummary "eai_agentplatform/backend/internal/skills/packages/interview_summary"
longformwriting "eai_agentplatform/backend/internal/skills/packages/longform_writing"
meetingminutes "eai_agentplatform/backend/internal/skills/packages/meeting_minutes"
@@ -16,13 +15,10 @@ import (
policyrewrite "eai_agentplatform/backend/internal/skills/packages/policy_rewrite"
pptgeneration "eai_agentplatform/backend/internal/skills/packages/ppt_generation"
progressreport "eai_agentplatform/backend/internal/skills/packages/progress_report"
projectplanning "eai_agentplatform/backend/internal/skills/packages/project_planning"
proposalsummary "eai_agentplatform/backend/internal/skills/packages/proposal_summary"
reportgeneration "eai_agentplatform/backend/internal/skills/packages/report_generation"
smartassistant "eai_agentplatform/backend/internal/skills/packages/smart_assistant"
surveysummary "eai_agentplatform/backend/internal/skills/packages/survey_summary"
tablecleanup "eai_agentplatform/backend/internal/skills/packages/table_cleanup"
texttoolkit "eai_agentplatform/backend/internal/skills/packages/text_toolkit"
texttospeech "eai_agentplatform/backend/internal/skills/packages/text_to_speech"
)
var builtinRegistry = NewRegistry(
@@ -36,18 +32,14 @@ var builtinRegistry = NewRegistry(
pptgeneration.Manifest,
mindmap.Manifest,
longformwriting.Manifest,
texttoolkit.Manifest,
ocrunderstanding.Manifest,
meetingminutes.Manifest,
projectplanning.Manifest,
emaildrafting.Manifest,
tablecleanup.Manifest,
proposalsummary.Manifest,
progressreport.Manifest,
contractbrief.Manifest,
interviewsummary.Manifest,
policyrewrite.Manifest,
surveysummary.Manifest,
texttospeech.Manifest,
)
func BuiltinRegistry() *Registry {
@@ -11,8 +11,10 @@ type SkillDefinition struct {
EAILogicCode string `gorm:"column:eailogic_code;size:32;default:'';index" json:"eailogic_code"`
Description string `gorm:"type:text" json:"description"`
ObjectKind string `gorm:"column:object_kind;size:32;not null;default:skill;index" json:"object_kind"`
Source string `gorm:"size:32;not null;default:eai;index" json:"source"`
ObjectEntryRoute string `gorm:"column:object_entry_route;size:128;default:''" json:"object_entry_route"`
Source string `gorm:"size:32;not null;default:eai;index" json:"source"`
ObjectEntryRoute string `gorm:"column:object_entry_route;size:128;default:''" json:"object_entry_route"` // 业务对象进入入口(D26 口径)
Color string `gorm:"size:16;default:''" json:"color"` // 展示主色(面向用户展示层,唯一的真值在后端)
InteractionCardJSON string `gorm:"column:interaction_card_json;type:text" json:"interaction_card_json"` // 交互卡对象(JSON,snake_case 与专员一致)
// 这里**有意不写** `default:true`。带上它,GORM 在 Create 时会跳过布尔零值字段
// (false 被当成「没填」),改由库默认值 true 生效 —— 于是对象显式设的 false
// 被持久层改写成 true,创建接口永远设不出「不暴露给用户」的技能。
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "audio-transcribe",
Label: "语音转写",
Label: "会议音频分析(转写)",
OwnedDefinitionKeys: []string{"skill.audio-transcribe.definition"},
OwnedCatalogEntries: []string{"catalog.skill.audio-transcribe"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "batch-extract",
Label: "批量提取",
Label: "批量字段提取 → Excel",
OwnedDefinitionKeys: []string{"skill.batch-extract.definition"},
OwnedCatalogEntries: []string{"catalog.skill.batch-extract"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "contract-brief",
Label: "合同要点提炼",
Label: "合同批量审查与提取(提取)",
OwnedDefinitionKeys: []string{"skill.contract-brief.definition"},
OwnedCatalogEntries: []string{"catalog.skill.contract-brief"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "contract-brief",
Label: "合同要点提炼",
Label: "合同批量审查与提取(提取)",
PlanTitle: "合同要点提炼流程",
PlanSteps: []string{"识别合同结构", "提炼核心条款", "标记风险事项", "输出摘要版本"},
ResultTitle: "合同要点摘要",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "contract-review",
Label: "合同审查",
Label: "合同批量审查与提取(审查)",
OwnedDefinitionKeys: []string{"skill.contract-review.definition"},
OwnedCatalogEntries: []string{"catalog.skill.contract-review"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -1,11 +0,0 @@
package emaildrafting
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "email-drafting",
Label: "邮件起草",
OwnedDefinitionKeys: []string{"skill.email-drafting.definition"},
OwnedCatalogEntries: []string{"catalog.skill.email-drafting"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,14 +0,0 @@
package emaildrafting
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
var OfficeRuntime = officecontracts.Runtime{
Key: "email-drafting",
Label: "邮件起草",
PlanTitle: "邮件起草流程",
PlanSteps: []string{"识别沟通目的", "整理背景与重点", "生成正式邮件", "补充简短跟进版本"},
ResultTitle: "邮件草稿",
Summary: "已生成一版可直接发送的邮件正文,并补了简短跟进版本和要点摘要。",
Highlights: []string{"适合汇报、催办、确认和通知", "兼顾正式语气与清晰表达", "默认沉淀长邮件和短消息版本"},
ActionType: "communication",
}
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "interview-summary",
Label: "访谈整理",
Label: "招聘简历助手",
OwnedDefinitionKeys: []string{"skill.interview-summary.definition"},
OwnedCatalogEntries: []string{"catalog.skill.interview-summary"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "interview-summary",
Label: "访谈整理",
Label: "招聘简历助手",
PlanTitle: "访谈整理流程",
PlanSteps: []string{"归并访谈内容", "提炼主题观点", "总结关键洞察", "输出整理版本"},
ResultTitle: "访谈整理稿",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "longform-writing",
Label: "长文创作",
Label: "公文辅助写作(长文)",
OwnedDefinitionKeys: []string{"skill.longform-writing.definition"},
OwnedCatalogEntries: []string{"catalog.skill.longform-writing"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "longform-writing",
Label: "长文创作",
Label: "公文辅助写作(长文)",
PlanTitle: "长文创作流程",
PlanSteps: []string{"明确文体与受众", "规划章节大纲", "生成正文骨架", "整理摘要与交付稿"},
ResultTitle: "长文草稿",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "meeting-minutes",
Label: "会议纪要",
Label: "会议音频分析(纪要)",
OwnedDefinitionKeys: []string{"skill.meeting-minutes.definition"},
OwnedCatalogEntries: []string{"catalog.skill.meeting-minutes"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "meeting-minutes",
Label: "会议纪要",
Label: "会议音频分析(纪要)",
PlanTitle: "会议纪要整理流程",
PlanSteps: []string{"识别会议主题", "提炼关键结论", "整理行动项", "输出同步版本"},
ResultTitle: "会议纪要草稿",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "mind-map",
Label: "思维导图",
Label: "会议音频分析(思维导图)",
OwnedDefinitionKeys: []string{"skill.mind-map.definition"},
OwnedCatalogEntries: []string{"catalog.skill.mind-map"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "mind-map",
Label: "思维导图",
Label: "会议音频分析(思维导图)",
PlanTitle: "思维导图生成流程",
PlanSteps: []string{"识别主题主线", "拆分一级分支", "补齐关键节点", "整理导图源结构"},
ResultTitle: "导图结构草案",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "ocr-understanding",
Label: "OCR / 图文理解",
Label: "图片/扫描件智能识别",
OwnedDefinitionKeys: []string{"skill.ocr-understanding.definition"},
OwnedCatalogEntries: []string{"catalog.skill.ocr-understanding"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "ocr-understanding",
Label: "OCR / 图文理解",
Label: "图片/扫描件智能识别",
PlanTitle: "图文理解流程",
PlanSteps: []string{"识别图像内容", "抽取文字与字段", "整理结构摘要", "输出可复用结果"},
ResultTitle: "识别结果摘要",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "policy-rewrite",
Label: "制度改写",
Label: "公文辅助写作(制度)",
OwnedDefinitionKeys: []string{"skill.policy-rewrite.definition"},
OwnedCatalogEntries: []string{"catalog.skill.policy-rewrite"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "policy-rewrite",
Label: "制度改写",
Label: "公文辅助写作(制度)",
PlanTitle: "制度改写流程",
PlanSteps: []string{"识别制度目标", "统一结构口径", "重写正式正文", "补充修订说明"},
ResultTitle: "制度改写稿",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "ppt-generation",
Label: "PPT 生成",
Label: "一键生成 PPT",
OwnedDefinitionKeys: []string{"skill.ppt-generation.definition"},
OwnedCatalogEntries: []string{"catalog.skill.ppt-generation"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "ppt-generation",
Label: "PPT 生成",
Label: "一键生成 PPT",
PlanTitle: "PPT 生成流程",
PlanSteps: []string{"确认汇报目标", "规划页面结构", "提炼每页要点", "整理讲稿备注"},
ResultTitle: "演示文稿骨架",
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "progress-report",
Label: "周报 / 日报",
Label: "一键周报",
OwnedDefinitionKeys: []string{"skill.progress-report.definition"},
OwnedCatalogEntries: []string{"catalog.skill.progress-report"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "progress-report",
Label: "周报 / 日报",
Label: "一键周报",
PlanTitle: "进展汇报流程",
PlanSteps: []string{"归并本期工作", "提炼关键进展", "整理风险事项", "输出汇报版本"},
ResultTitle: "进展汇报草稿",
@@ -1,11 +0,0 @@
package projectplanning
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "project-planning",
Label: "项目规划",
OwnedDefinitionKeys: []string{"skill.project-planning.definition"},
OwnedCatalogEntries: []string{"catalog.skill.project-planning"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,14 +0,0 @@
package projectplanning
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
var OfficeRuntime = officecontracts.Runtime{
Key: "project-planning",
Label: "项目规划",
PlanTitle: "项目规划流程",
PlanSteps: []string{"明确目标边界", "拆解阶段路径", "整理里程碑", "补齐风险与依赖"},
ResultTitle: "项目规划草案",
Summary: "已把目标拆成阶段计划、里程碑和风险项,方便直接进入执行或评审。",
Highlights: []string{"适合启动、排期和推进对齐", "默认沉淀阶段计划与风险清单", "结果适合继续流转到任务治理"},
ActionType: "plan",
}
@@ -1,11 +0,0 @@
package proposalsummary
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "proposal-summary",
Label: "方案摘要",
OwnedDefinitionKeys: []string{"skill.proposal-summary.definition"},
OwnedCatalogEntries: []string{"catalog.skill.proposal-summary"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,14 +0,0 @@
package proposalsummary
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
var OfficeRuntime = officecontracts.Runtime{
Key: "proposal-summary",
Label: "方案摘要",
PlanTitle: "方案摘要流程",
PlanSteps: []string{"识别方案目标", "提炼核心亮点", "压缩实施路径", "输出摘要版本"},
ResultTitle: "方案摘要稿",
Summary: "已提炼出方案核心结论、价值亮点和实施建议,适合快速汇报或同步。",
Highlights: []string{"适合方案汇报和管理层预读", "自动压缩价值点与实施路径", "默认沉淀摘要正文和亮点清单"},
ActionType: "summary",
}
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "report-generation",
Label: "报告生成",
Label: "一键生成报告",
OwnedDefinitionKeys: []string{"skill.report-generation.definition"},
OwnedCatalogEntries: []string{"catalog.skill.report-generation"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "smart-assistant",
Label: "通用助手",
Label: "智能助手",
OwnedDefinitionKeys: []string{"skill.smart-assistant.definition"},
OwnedCatalogEntries: []string{"catalog.skill.smart-assistant"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -1,11 +0,0 @@
package surveysummary
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "survey-summary",
Label: "表单问卷汇总",
OwnedDefinitionKeys: []string{"skill.survey-summary.definition"},
OwnedCatalogEntries: []string{"catalog.skill.survey-summary"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,14 +0,0 @@
package surveysummary
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
var OfficeRuntime = officecontracts.Runtime{
Key: "survey-summary",
Label: "表单问卷汇总",
PlanTitle: "问卷汇总流程",
PlanSteps: []string{"归并表单结果", "提炼重点发现", "整理问题与建议", "输出汇总版本"},
ResultTitle: "问卷汇总稿",
Summary: "已整理出表单结果汇总、重点发现和改进建议,方便直接同步给负责人。",
Highlights: []string{"适合反馈表、报名表、调查问卷", "自动压缩重点发现和改进建议", "默认沉淀汇总报告和行动建议"},
ActionType: "report",
}
@@ -4,7 +4,7 @@ import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "table-cleanup",
Label: "表格整理",
Label: "知识库表格视图",
OwnedDefinitionKeys: []string{"skill.table-cleanup.definition"},
OwnedCatalogEntries: []string{"catalog.skill.table-cleanup"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
@@ -4,7 +4,7 @@ import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office
var OfficeRuntime = officecontracts.Runtime{
Key: "table-cleanup",
Label: "表格整理",
Label: "知识库表格视图",
PlanTitle: "表格整理流程",
PlanSteps: []string{"识别字段结构", "清洗原始数据", "整理表格内容", "补充字段说明"},
ResultTitle: "表格整理结果",
@@ -0,0 +1,11 @@
package texttospeech
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "text-to-speech",
Label: "文字转语音",
OwnedDefinitionKeys: []string{"skill.text-to-speech.definition"},
OwnedCatalogEntries: []string{"catalog.skill.text-to-speech"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,11 +0,0 @@
package texttoolkit
import skillcontracts "eai_agentplatform/backend/internal/skills/contracts"
var Manifest = skillcontracts.Manifest{
Key: "text-toolkit",
Label: "文本处理",
OwnedDefinitionKeys: []string{"skill.text-toolkit.definition"},
OwnedCatalogEntries: []string{"catalog.skill.text-toolkit"},
ReferencePolicy: skillcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,14 +0,0 @@
package texttoolkit
import officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
var OfficeRuntime = officecontracts.Runtime{
Key: "text-toolkit",
Label: "文本处理",
PlanTitle: "文本处理流程",
PlanSteps: []string{"识别清洗目标", "去除噪音符号", "统一格式与标点", "输出可复用文本"},
ResultTitle: "清洗后文本",
Summary: "已完成文本清洗、格式整理和统计,可直接复制或下载结果。",
Highlights: []string{"去 Markdown 噪音", "输出文本统计", "适合高频复制到 Word 和 IM"},
ActionType: "text",
}
@@ -98,112 +98,6 @@ func BuildMeetingMinutesArtifacts(inputText string) []gin.H {
}
}
func BuildEmailDraftingArtifacts(inputText string) []gin.H {
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
"recipient": {"收件人", "对象", "recipient", "to"},
"cc": {"抄送", "抄送人", "cc"},
"topic": {"主题", "标题", "topic", "subject"},
"purpose": {"目的", "意图", "purpose"},
"action": {"希望对方", "需要对方", "action"},
"deadline": {"时间", "截止时间", "deadline"},
"tone": {"语气", "风格", "tone", "style"},
})
topic := firstNonEmpty(fields["topic"], pickOfficeTopic(firstNonEmpty(bodyText, inputText), "邮件主题"))
recipient := firstNonEmpty(fields["recipient"], "各位")
ccList := splitSimpleList(fields["cc"])
purpose := firstNonEmpty(fields["purpose"], "同步背景和当前进展")
action := firstNonEmpty(fields["action"], "请协助确认并继续推进")
deadline := firstNonEmpty(fields["deadline"], "请尽快反馈")
tone := firstNonEmpty(fields["tone"], "正式、明确、礼貌")
points := extractOfficePoints(firstNonEmpty(bodyText, inputText), []string{"交代背景和当前情况", "说明希望对方配合或确认的事项", "给出时间点和下一步动作", "保持礼貌但结论清楚"})
subjectVariants := buildEmailSubjectVariants(topic, purpose)
subject := subjectVariants[0]
emailContent := strings.TrimSpace(strings.Join([]string{
"主题:" + subject,
"收件人:" + recipient,
"抄送:" + firstNonEmpty(strings.Join(ccList, "、"), "无"),
"",
recipient + "好,",
"",
purpose + "。" + firstNonEmpty(pointAt(points, 0), "这边同步一下当前事项的背景和进展。"),
action + "。" + firstNonEmpty(pointAt(points, 1), "目前需要大家协助确认相关事项。"),
deadline + "。" + firstNonEmpty(pointAt(points, 2), "如无问题,请按约定时间继续推进。"),
"",
"语气建议:" + tone + "。如有问题,请直接回复沟通。",
"",
"谢谢。",
}, "\n"))
shortContent := strings.TrimSpace(strings.Join([]string{
"【" + topic + "】",
firstNonEmpty(pointAt(points, 1), "请协助确认相关事项。"),
firstNonEmpty(pointAt(points, 2), "如无问题请按时推进。"),
}, "\n"))
briefContent := strings.TrimSpace(strings.Join([]string{
"# 邮件要点",
"",
"- 主题:" + subject,
"- " + firstNonEmpty(pointAt(points, 0), "交代背景和当前情况"),
"- " + firstNonEmpty(pointAt(points, 1), "说明希望对方配合或确认的事项"),
"- " + firstNonEmpty(pointAt(points, 2), "给出时间点和下一步动作"),
"- " + firstNonEmpty(pointAt(points, 3), "保持礼貌但结论清楚"),
}, "\n"))
subjectLines := []string{
"# 主题与抄送建议",
"",
"- 收件人:" + recipient,
"- 抄送建议:" + firstNonEmpty(strings.Join(ccList, "、"), "建议抄送直属负责人 / 相关协同方"),
"",
"## 可选主题",
}
for index, item := range subjectVariants {
subjectLines = append(subjectLines, fmt.Sprintf("%d. %s", index+1, item))
}
subjectContent := strings.TrimSpace(strings.Join(subjectLines, "\n"))
slug := officeSlug(topic, "email-drafting")
return []gin.H{
{
"key": "email",
"title": "正式邮件",
"description": "可直接复制到邮箱发送的完整版本。",
"kind": "text",
"fileFormat": "txt",
"downloadName": slug + ".txt",
"mimeType": "text/plain;charset=utf-8",
"content": emailContent,
},
{
"key": "short-followup",
"title": "简短跟进版",
"description": "适合发到 IM 或群里的短消息版本。",
"kind": "text",
"fileFormat": "txt",
"downloadName": slug + "-short.txt",
"mimeType": "text/plain;charset=utf-8",
"content": shortContent,
},
{
"key": "brief",
"title": "邮件要点",
"description": "方便审批或复核邮件口径的要点版。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-brief.md",
"mimeType": "text/markdown;charset=utf-8",
"content": briefContent,
},
{
"key": "subject-variants",
"title": "主题与抄送建议",
"description": "提供多版主题候选和抄送建议。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-subject.md",
"mimeType": "text/markdown;charset=utf-8",
"content": subjectContent,
},
}
}
func BuildProgressReportArtifacts(inputText string) []gin.H {
topic := pickOfficeTopic(inputText, "进展汇报")
points := extractOfficePoints(inputText, []string{"本期完成的关键工作", "当前风险和阻塞项", "需要协同支持的事项", "下一步计划"})
@@ -114,109 +114,6 @@ func BuildMindMapArtifacts(inputText string) []gin.H {
}
}
func BuildProjectPlanningArtifacts(inputText string) []gin.H {
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
"topic": {"项目", "项目名称", "主题", "topic"},
"deadline": {"时间要求", "截止时间", "deadline"},
"owner": {"负责人", "owner"},
"goal": {"目标", "goal"},
"start": {"开始时间", "启动时间", "start"},
})
topic := firstNonEmpty(fields["topic"], pickOfficeTopic(firstNonEmpty(bodyText, inputText), "项目规划"))
deadline := firstNonEmpty(fields["deadline"], "待确认")
owner := firstNonEmpty(fields["owner"], "待指定")
goal := firstNonEmpty(fields["goal"], "先明确目标、阶段、依赖和协同方式")
start := firstNonEmpty(fields["start"], "尽快启动")
points := extractOfficePoints(firstNonEmpty(bodyText, inputText), []string{"明确目标、范围和成功标准", "梳理关键里程碑与交付节点", "安排执行分工与协同节奏", "识别风险与外部依赖"})
stageRows := buildProjectStageRows(points, owner, deadline)
planContent := strings.TrimSpace(strings.Join([]string{
"# " + topic,
"",
"## 项目目标",
fmt.Sprintf("围绕“%s”整理一版可执行的项目规划,先确保目标、阶段和依赖都清楚。", topic),
"- 负责人:" + owner,
"- 启动时间:" + start,
"- 时间要求:" + deadline,
"- 总体目标:" + goal,
"",
"## 阶段安排",
"### 阶段 1:启动与对齐",
"- " + firstNonEmpty(pointAt(points, 0), "明确目标和边界"),
"### 阶段 2:执行与推进",
"- " + firstNonEmpty(pointAt(points, 1), "推进关键里程碑和核心交付"),
"### 阶段 3:验收与收口",
"- " + firstNonEmpty(pointAt(points, 2), "完成验收、复盘和沉淀"),
}, "\n"))
milestoneContent := strings.TrimSpace(strings.Join([]string{
"# 里程碑清单",
"",
"1. M1:" + firstNonEmpty(pointAt(points, 0), "明确目标和边界"),
"2. M2:" + firstNonEmpty(pointAt(points, 1), "推进关键里程碑和核心交付"),
"3. M3:" + firstNonEmpty(pointAt(points, 2), "完成验收、复盘和沉淀"),
"4. M4:" + firstNonEmpty(pointAt(points, 3), "确认依赖和外部配合事项"),
}, "\n"))
riskContent := strings.TrimSpace(strings.Join([]string{
"# 风险与依赖",
"",
"- 风险 1:" + firstNonEmpty(pointAt(points, 3), "关键依赖尚未完全明确"),
"- 风险 2:跨团队协同节奏可能影响排期",
"- 建议:将关键依赖提前前置到周会或启动会确认",
}, "\n"))
scheduleLines := []string{
"# 阶段排期表",
"",
"| 阶段 | 时间窗 | 负责人 | 目标 | 交付物 |",
"| --- | --- | --- | --- | --- |",
}
for _, item := range stageRows {
scheduleLines = append(scheduleLines, fmt.Sprintf("| %s | %s | %s | %s | %s |", asString(item["stage"]), asString(item["window"]), asString(item["owner"]), asString(item["goal"]), asString(item["output"])))
}
scheduleContent := strings.TrimSpace(strings.Join(scheduleLines, "\n"))
slug := officeSlug(topic, "project-planning")
return []gin.H{
{
"key": "project-plan",
"title": "项目计划",
"description": "适合直接评审和继续细化的主计划。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + ".md",
"mimeType": "text/markdown;charset=utf-8",
"content": planContent,
},
{
"key": "milestones",
"title": "里程碑清单",
"description": "关键节点和交付节奏的简洁版列表。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-milestones.md",
"mimeType": "text/markdown;charset=utf-8",
"content": milestoneContent,
},
{
"key": "risks",
"title": "风险清单",
"description": "项目推进前需要确认的风险与依赖。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-risks.md",
"mimeType": "text/markdown;charset=utf-8",
"content": riskContent,
},
{
"key": "schedule",
"title": "阶段排期表",
"description": "更接近甘特视角的阶段、时间窗和交付物表。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-schedule.md",
"mimeType": "text/markdown;charset=utf-8",
"content": scheduleContent,
},
}
}
func BuildTableCleanupArtifacts(inputText string) []gin.H {
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
"topic": {"主题", "标题", "topic", "title"},
@@ -58,115 +58,6 @@ func BuildLongformArtifacts(inputText string) []gin.H {
}
}
func BuildTextToolkitArtifacts(inputText string) []gin.H {
cleaned := stripMarkdownText(inputText)
stats := strings.Join([]string{
"# 文本统计",
"",
fmt.Sprintf("- 字符数:%d", len([]rune(cleaned))),
fmt.Sprintf("- 行数:%d", len(splitMeaningfulLines(cleaned))),
fmt.Sprintf("- 原始长度:%d", len([]rune(strings.TrimSpace(inputText)))),
"",
"## 处理说明",
"- 已移除常见 Markdown 标记",
"- 已压缩多余空行",
"- 已保留正文可读性",
}, "\n")
slug := officeSlug(pickOfficeTopic(inputText, "cleaned-text"), "text-toolkit")
return []gin.H{
{
"key": "cleaned",
"title": "清洗后文本",
"description": "适合直接粘贴到文档或聊天工具。",
"kind": "text",
"fileFormat": "txt",
"downloadName": slug + ".txt",
"mimeType": "text/plain;charset=utf-8",
"content": cleaned,
},
{
"key": "stats",
"title": "文本统计",
"description": "记录本次清洗和统计结果。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-stats.md",
"mimeType": "text/markdown;charset=utf-8",
"content": stats,
},
}
}
func BuildProposalSummaryArtifacts(inputText string) []gin.H {
topic := pickOfficeTopic(inputText, "方案摘要")
points := extractOfficePoints(inputText, []string{"明确方案目标和解决的问题", "提炼核心价值与收益", "压缩关键实施路径", "明确需要决策的事项"})
summaryContent := strings.TrimSpace(strings.Join([]string{
"# " + topic,
"",
"## 核心结论",
fmt.Sprintf("%s 已压缩为适合汇报和快速预读的摘要版本,重点保留目标、价值点和实施建议。", topic),
"",
"## 关键亮点",
"- " + firstNonEmpty(pointAt(points, 0), "明确方案目标和解决的问题"),
"- " + firstNonEmpty(pointAt(points, 1), "提炼核心价值与收益"),
"- " + firstNonEmpty(pointAt(points, 2), "压缩关键实施路径"),
"- " + firstNonEmpty(pointAt(points, 3), "明确需要决策的事项"),
"",
"## 实施建议",
"- 建议先确认资源与排期",
"- 建议围绕高优先级场景先落一版 MVP",
"- 建议同步关键负责人做进一步评审",
}, "\n"))
highlightsContent := strings.TrimSpace(strings.Join([]string{
"# 亮点清单",
"",
"1. " + firstNonEmpty(pointAt(points, 0), "明确方案目标和解决的问题"),
"2. " + firstNonEmpty(pointAt(points, 1), "提炼核心价值与收益"),
"3. " + firstNonEmpty(pointAt(points, 2), "压缩关键实施路径"),
"4. " + firstNonEmpty(pointAt(points, 3), "明确需要决策的事项"),
}, "\n"))
briefingContent := strings.TrimSpace(strings.Join([]string{
"【" + topic + " 摘要】",
"1. " + firstNonEmpty(pointAt(points, 0), "明确方案目标和解决的问题"),
"2. " + firstNonEmpty(pointAt(points, 1), "提炼核心价值与收益"),
"3. " + firstNonEmpty(pointAt(points, 2), "压缩关键实施路径"),
"建议按上述结论进入下一步决策或评审。",
}, "\n"))
slug := officeSlug(topic, "proposal-summary")
return []gin.H{
{
"key": "summary",
"title": "方案摘要",
"description": "适合直接汇报或继续细化的主摘要。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + ".md",
"mimeType": "text/markdown;charset=utf-8",
"content": summaryContent,
},
{
"key": "highlights",
"title": "亮点清单",
"description": "压缩提炼后的价值点列表。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-highlights.md",
"mimeType": "text/markdown;charset=utf-8",
"content": highlightsContent,
},
{
"key": "briefing",
"title": "汇报短版",
"description": "适合发群或口头汇报前快速同步的短摘要。",
"kind": "text",
"fileFormat": "txt",
"downloadName": slug + "-briefing.txt",
"mimeType": "text/plain;charset=utf-8",
"content": briefingContent,
},
}
}
func BuildContractBriefArtifacts(inputText string) []gin.H {
fields, bodyText := parseOfficeFields(inputText, map[string][]string{
"topic": {"合同名称", "主题", "topic"},
@@ -422,67 +313,3 @@ func BuildPolicyRewriteArtifacts(inputText string) []gin.H {
},
}
}
func BuildSurveySummaryArtifacts(inputText string) []gin.H {
topic := pickOfficeTopic(inputText, "问卷汇总")
points := extractOfficePoints(inputText, []string{"参与者的主要反馈方向", "高频问题或不满意点", "值得保留的积极反馈", "后续改进建议"})
reportContent := strings.TrimSpace(strings.Join([]string{
"# " + topic,
"",
"## 汇总结论",
"- " + firstNonEmpty(pointAt(points, 0), "参与者的主要反馈方向"),
"- " + firstNonEmpty(pointAt(points, 1), "高频问题或不满意点"),
"- " + firstNonEmpty(pointAt(points, 2), "值得保留的积极反馈"),
"- " + firstNonEmpty(pointAt(points, 3), "后续改进建议"),
"",
"## 汇总说明",
"已把表单和问卷结果压缩成便于阅读和决策的汇总结论。",
}, "\n"))
findingsContent := strings.TrimSpace(strings.Join([]string{
"# 重点发现",
"",
"- 发现 1:" + firstNonEmpty(pointAt(points, 0), "参与者主要关注体验和执行效果"),
"- 发现 2:" + firstNonEmpty(pointAt(points, 1), "部分问题集中在流程或内容安排上"),
"- 发现 3:" + firstNonEmpty(pointAt(points, 2), "已有若干积极反馈值得继续保留"),
}, "\n"))
actionsContent := strings.TrimSpace(strings.Join([]string{
"# 改进建议",
"",
"- [ ] " + firstNonEmpty(pointAt(points, 3), "根据汇总结果制定下一步改进动作"),
"- [ ] 对高频问题安排专项优化",
"- [ ] 向负责人同步汇总结论和优先级建议",
}, "\n"))
slug := officeSlug(topic, "survey-summary")
return []gin.H{
{
"key": "report",
"title": "汇总报告",
"description": "适合直接汇报或继续细化的主报告。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + ".md",
"mimeType": "text/markdown;charset=utf-8",
"content": reportContent,
},
{
"key": "findings",
"title": "重点发现",
"description": "从表单结果中提炼出的关键发现。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-findings.md",
"mimeType": "text/markdown;charset=utf-8",
"content": findingsContent,
},
{
"key": "actions",
"title": "改进建议",
"description": "建议后续继续推进的改进行动。",
"kind": "text",
"fileFormat": "md",
"downloadName": slug + "-actions.md",
"mimeType": "text/markdown;charset=utf-8",
"content": actionsContent,
},
}
}
@@ -2,7 +2,6 @@ package office
import (
contractbrief "eai_agentplatform/backend/internal/skills/packages/contract_brief"
emaildrafting "eai_agentplatform/backend/internal/skills/packages/email_drafting"
interviewsummary "eai_agentplatform/backend/internal/skills/packages/interview_summary"
longformwriting "eai_agentplatform/backend/internal/skills/packages/longform_writing"
meetingminutes "eai_agentplatform/backend/internal/skills/packages/meeting_minutes"
@@ -11,11 +10,7 @@ import (
policyrewrite "eai_agentplatform/backend/internal/skills/packages/policy_rewrite"
pptgeneration "eai_agentplatform/backend/internal/skills/packages/ppt_generation"
progressreport "eai_agentplatform/backend/internal/skills/packages/progress_report"
projectplanning "eai_agentplatform/backend/internal/skills/packages/project_planning"
proposalsummary "eai_agentplatform/backend/internal/skills/packages/proposal_summary"
surveysummary "eai_agentplatform/backend/internal/skills/packages/survey_summary"
tablecleanup "eai_agentplatform/backend/internal/skills/packages/table_cleanup"
texttoolkit "eai_agentplatform/backend/internal/skills/packages/text_toolkit"
officecontracts "eai_agentplatform/backend/internal/skills/runtime/office/contracts"
"github.com/gin-gonic/gin"
)
@@ -29,18 +24,13 @@ var builtinRegistry = NewRegistry(
withBuild(pptgeneration.OfficeRuntime, BuildPPTArtifacts),
withBuild(mindmap.OfficeRuntime, BuildMindMapArtifacts),
withBuild(longformwriting.OfficeRuntime, BuildLongformArtifacts),
withBuild(texttoolkit.OfficeRuntime, BuildTextToolkitArtifacts),
ocrunderstanding.OfficeRuntime,
withBuild(meetingminutes.OfficeRuntime, BuildMeetingMinutesArtifacts),
withBuild(projectplanning.OfficeRuntime, BuildProjectPlanningArtifacts),
withBuild(emaildrafting.OfficeRuntime, BuildEmailDraftingArtifacts),
withBuild(tablecleanup.OfficeRuntime, BuildTableCleanupArtifacts),
withBuild(proposalsummary.OfficeRuntime, BuildProposalSummaryArtifacts),
withBuild(progressreport.OfficeRuntime, BuildProgressReportArtifacts),
withBuild(contractbrief.OfficeRuntime, BuildContractBriefArtifacts),
withBuild(interviewsummary.OfficeRuntime, BuildInterviewSummaryArtifacts),
withBuild(policyrewrite.OfficeRuntime, BuildPolicyRewriteArtifacts),
withBuild(surveysummary.OfficeRuntime, BuildSurveySummaryArtifacts),
)
func BuiltinRegistry() *Registry {
@@ -71,26 +71,6 @@ func parseMeetingActions(text string, fallback []string) []gin.H {
return out
}
func buildEmailSubjectVariants(topic, purpose string) []string {
base := firstNonEmpty(topic, "事项")
context := strings.TrimSpace(purpose)
items := []string{
base + " - 请协助确认",
base + " - 需要回复",
base + " - 进展同步",
}
if context != "" {
runes := []rune(context)
if len(runes) > 12 {
context = string(runes[:12])
}
items = append(items, base+" - "+context)
} else {
items = append(items, base+" - 待处理提醒")
}
return items
}
func formatMeetingActionLine(actions []gin.H, index int) string {
if index < 0 || index >= len(actions) {
return fmt.Sprintf("%d. 待补充行动项", index+1)
@@ -149,29 +129,3 @@ func buildContractRedlineItems(points, focusKeywords []string) []gin.H {
}
return out
}
func stripMarkdownText(text string) string {
text = strings.ReplaceAll(text, "\r", "\n")
blockCode := regexp.MustCompile("```[\\s\\S]*?```")
text = blockCode.ReplaceAllStringFunc(text, func(value string) string {
return strings.TrimSpace(strings.ReplaceAll(value, "```", ""))
})
replacers := []struct {
pattern string
value string
}{
{"`([^`]+)`", "$1"},
{"^#{1,6}\\s+", ""},
{"^\\s*[-*+]\\s+", ""},
{"^\\s*\\d+[.)]\\s+", ""},
{"\\*\\*(.*?)\\*\\*", "$1"},
{"\\*(.*?)\\*", "$1"},
{"!\\[[^\\]]*\\]\\([^)]*\\)", ""},
{"\\[([^\\]]+)\\]\\(([^)]*)\\)", "$1"},
}
for _, item := range replacers {
text = regexp.MustCompile(item.pattern).ReplaceAllString(text, item.value)
}
text = regexp.MustCompile(`\n{3,}`).ReplaceAllString(text, "\n\n")
return strings.TrimSpace(text)
}
@@ -217,31 +217,6 @@ func splitSimpleList(value string) []string {
return out
}
func buildProjectStageRows(points []string, owner, deadline string) []gin.H {
labels := []string{"阶段 1", "阶段 2", "阶段 3", "阶段 4"}
windows := []string{"第 1 周", "第 2 周", "第 3 周", firstNonEmpty(deadline, "收口前")}
rows := make([]gin.H, 0, len(labels))
for index, label := range labels {
output := "收口结论"
switch index {
case 0:
output = "目标确认"
case 1:
output = "阶段交付"
case 2:
output = "验收材料"
}
rows = append(rows, gin.H{
"stage": label,
"window": windows[index],
"goal": firstNonEmpty(pointAt(points, index), "补充"+label+"目标"),
"owner": firstNonEmpty(owner, "待指定"),
"output": output,
})
}
return rows
}
func repeatString(value string, count int) []string {
items := make([]string, 0, count)
for index := 0; index < count; index++ {
@@ -2,31 +2,17 @@ package specialistcore
import (
contractreview "eai_agentplatform/backend/internal/specialists/packages/contract_review"
generalassistant "eai_agentplatform/backend/internal/specialists/packages/general_assistant"
hremailsorter "eai_agentplatform/backend/internal/specialists/packages/hr_email_sorter"
knowledgeoperations "eai_agentplatform/backend/internal/specialists/packages/knowledge_operations"
logisticsfulfillment "eai_agentplatform/backend/internal/specialists/packages/logistics_fulfillment"
presentationbriefing "eai_agentplatform/backend/internal/specialists/packages/presentation_briefing"
processcoordination "eai_agentplatform/backend/internal/specialists/packages/process_coordination"
reportgeneration "eai_agentplatform/backend/internal/specialists/packages/report_generation"
customerfollowup "eai_agentplatform/backend/internal/specialists/packages/customer_followup"
resumeprocessor "eai_agentplatform/backend/internal/specialists/packages/resume_processor"
solutionproposal "eai_agentplatform/backend/internal/specialists/packages/solution_proposal"
trainingdelivery "eai_agentplatform/backend/internal/specialists/packages/training_delivery"
wechatofficialaccount "eai_agentplatform/backend/internal/specialists/packages/wechat_official_account"
)
var builtinRegistry = NewRegistry(
generalassistant.Manifest,
trainingdelivery.Manifest,
knowledgeoperations.Manifest,
processcoordination.Manifest,
reportgeneration.Manifest,
wechatofficialaccount.Manifest,
contractreview.Manifest,
solutionproposal.Manifest,
presentationbriefing.Manifest,
logisticsfulfillment.Manifest,
hremailsorter.Manifest,
customerfollowup.Manifest,
resumeprocessor.Manifest,
)
@@ -0,0 +1,32 @@
package customerfollowup
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
var Manifest = specialistcontracts.Manifest{
Key: "customer-followup",
Label: "客户跟进专员",
RuleFileMarkdown: `# 客户跟进专员
## 你是谁
你负责客户资料整理到会议预约这一段的推进:资料归档、意向分级、联系建议、预约跟进、状态回写。
你面对的是销售、售前或客户成功同学,他们要的是「哪些客户该先跟、怎么跟、何时约」。
## 你怎么推进
1. 先给总览:客户一共多少个,分别处于新线索、已联系、待预约、已预约哪个阶段。
2. 逐个客户整理「客户名称 / 关键背景 / 当前意向 / 最近动作 / 下一步建议」。
3. 对高意向客户优先给出联系建议:推荐触达方式、首轮话术、会议目标和建议时间。
4. 跟进结果要回写,明确哪些客户已联系、哪些待补资料、哪些需要升级处理。
## 输出要求
- 客户资料要保留来源,标明来自 CRM、表格、邮件还是人工补录。
- 意向判断要写依据,不要只给一个高、中、低标签。
- 联系建议尽量可直接发出,避免只写空泛建议。
## 边界
- 不伪造客户承诺,不代替用户直接发送外部联系。
- 拿不到客户历史记录时如实说,不要按经验补全。`,
AllowedSkills: []string{"progress-report", "report-generation"},
OwnedDefinitionKeys: []string{"specialist.customer-followup.definition"},
OwnedCatalogEntries: []string{"catalog.specialist.customer-followup"},
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,31 +0,0 @@
package hremailsorter
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
var Manifest = specialistcontracts.Manifest{
Key: "hr-email-sorter",
Label: "HR 邮件整理专员",
RuleFileMarkdown: `# HR 邮件整理专员
## 你是谁
你负责把 HR 邮箱里的简历邮件理清楚:简历邮件识别、候选人信息抽取、去重归类。
你面对的是要快速筛出有效候选人的招聘同学。
## 你怎么推进
1. 先分类:简历投递 / 面试安排 / 其他(通知、广告、内部邮件)。
2. 简历邮件逐封抽字段:姓名、联系方式、应聘岗位、年限、学历、附件有没有。
3. 去重:同一候选人多次投递的合并,列出重复来源。
4. 输出归类清单,按岗位分组。
## 输出要求
- 字段缺失写「未提供」,不要用工整的占位内容填充。
- 附件解析失败的单列出来,标明原因。
## 边界
- 候选人个人信息只出现在整理结果里,不外传、不写入其他文档。
- 不做录用判断——那是简历处理专员和用人部门的事。`,
AllowedSkills: []string{"email-drafting", "batch-extract", "table-cleanup", "ocr-understanding"},
OwnedDefinitionKeys: []string{"specialist.hr-email-sorter.definition"},
OwnedCatalogEntries: []string{"catalog.specialist.hr-email-sorter"},
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
}
@@ -1,31 +0,0 @@
package logisticsfulfillment
import specialistcontracts "eai_agentplatform/backend/internal/specialists/contracts"
var Manifest = specialistcontracts.Manifest{
Key: "logistics-fulfillment",
Label: "履约跟单专员",
RuleFileMarkdown: `# 履约跟单专员
## 你是谁
你负责订单履约的过程跟踪:节点跟踪、异常识别、催办升级、状态回写。
你面对的是盯着一批单子的人,他要的是「哪几单要出事了」。
## 你怎么推进
1. 先给总览:在途多少单、正常多少、异常多少。
2. 异常单逐条给出「单号 / 卡在哪个节点 / 卡了多久 / 原因 / 建议动作」。
3. 按节点时效判断该催谁,给出可直接发送的催办话术。
4. 收尾确认状态已回写,没回写的列出来。
## 输出要求
- 时间口径统一(统一时区、标明统计截止时点)。
- 异常分级:影响交付日期的算高优先级,只影响体感的往下降。
## 边界
- 只读订单与物流数据,不代替用户改单、取消单、承诺新的交期。
- 拿不到物流节点信息时如实说,不要按经验推测位置。`,
AllowedSkills: []string{"progress-report", "table-cleanup", "email-drafting"},
OwnedDefinitionKeys: []string{"specialist.logistics-fulfillment.definition"},
OwnedCatalogEntries: []string{"catalog.specialist.logistics-fulfillment"},
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
}
@@ -26,7 +26,7 @@ var Manifest = specialistcontracts.Manifest{
- 不编造数据、案例、客户反馈。
- 不把未确认方案写成既定事实。
- 视觉美化可以建议,但当前重点是结构与表达,不承诺设计成品。`,
AllowedSkills: []string{"ppt-generation", "proposal-summary", "mind-map", "progress-report"},
AllowedSkills: []string{"ppt-generation", "mind-map", "progress-report"},
OwnedDefinitionKeys: []string{"specialist.presentation-briefing.definition"},
OwnedCatalogEntries: []string{"catalog.specialist.presentation-briefing"},
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
@@ -23,7 +23,7 @@ var Manifest = specialistcontracts.Manifest{
## 边界
- 只起草催办与升级建议,不代替用户对外发送。
- 不评价同事的工作态度,只陈述事项状态与时间事实。`,
AllowedSkills: []string{"progress-report", "project-planning", "email-drafting"},
AllowedSkills: []string{"progress-report"},
OwnedDefinitionKeys: []string{"specialist.process-coordination.definition"},
OwnedCatalogEntries: []string{"catalog.specialist.process-coordination"},
ReferencePolicy: specialistcontracts.SharedReferenceReadonlyHistory,
@@ -4,20 +4,22 @@ import specialistcontracts "eai_agentplatform/backend/internal/specialists/contr
var Manifest = specialistcontracts.Manifest{
Key: "resume-processor",
Label: "简历处理专员",
RuleFileMarkdown: `# 简历处理专员
Label: "招聘筛选专员",
RuleFileMarkdown: `# 招聘筛选专员
## 你是谁
你负责简历筛选到面试安排:筛选、评分排序、跟进标记、面试安排。
你面对的是用人部门,他们要的是一份能直接拿去约面试的名单。
你负责从招聘入口整理到候选人筛选的闭环:邮件归档、候选人抽取、评分排序、跟进标记、面试安排。
你面对的是招聘同学和用人部门,他们要的是一份能直接拿去推进的候选人清单。
## 你怎么推进
1. 先确认岗位要求与硬性门槛(学历、年限、必备技能),门槛项单独标。
2. 逐份评分:按岗位要求逐项对照,给出总分与排序,并写明「为什么排这个位置」。
3. 标出不确定项:信息缺失、表述含糊、需要电话确认的点。
4. 给面试安排建议:分批、每批人选、建议面试重点。
1. 先整理招聘入口:把招聘邮件、附件和候选人资料归到统一清单,重复投递先合并。
2. 再确认岗位要求与硬性门槛(学历、年限、必备技能),门槛项单独标。
3. 逐份评分:按岗位要求逐项对照,给出总分与排序,并写明「为什么排这个位置」。
4. 标出不确定项:信息缺失、表述含糊、需要电话确认的点。
5. 给面试安排建议:分批、每批人选、建议面试重点。
## 输出要求
- 候选人入口整理要保留来源,标明来自哪封邮件、哪个附件或哪次投递。
- 评分要能追溯到岗位要求的具体条目,不要只给一个分数。
- 排序理由写事实(做过什么、做了多久),不写「感觉不错」。

Some files were not shown because too many files have changed in this diff Show More