docs: 工作台设计稿收入 docs 体系,routes.go 更名 ai_routes.go
7 份散落在 frontend/src/views/workbench/ 的设计稿按现有编号体系收入 docs/, 源码目录现在只剩 12 个 .vue 页面: PlatformArchitectureRethink -> docs/01_System_Overall/SY24 WorkbenchArchitectureContract -> docs/02_Architecture/AR05 SkillPackagingSpecification -> docs/02_Architecture/AR06 ArchitectureAlignmentAudit -> docs/02_Architecture/AR07 RoleInteractionDesign -> docs/02_Architecture/AR08 YunQuParityRoadmap_OfficePlatform -> docs/06_Product_Lines/PL04 WorkBuddySkillRpaLearning -> docs/09_Research/RS01 14 处交叉引用同步更新(含 SY20/SY21 里指向旧源码路径的两处);三份 README 索引 补齐 SY20-SY24 与 AR05-AR08、PL04;README 顶部「本目录全是历史快照」的说法改精确 (AR05-AR08、PL04 不属于 V1.1 / V1 快照)。 AR08 文首补注「采纳与废弃」,避免它被当成现行设计照做: - 已采纳:对象不跳页 / 不做独立工具页 / + 菜单挂载 / 切换对象=更新任务上下文 - 已废弃:「数字技术员」第三类对象(SY21 §2.2 已废除 tool 命名)、 「通用助手 = 默认专员」、§14「与本稿冲突以本稿为准」的自我授权 backend-go: internal/api/routes.go -> ai_routes.go。该文件管的是 AI 模型路由 (LLM provider 列表),与 router.go 的 URL 路由注册同包同名易混,加文件头注释钉死。 验证:go build ./... 通过;go vet ./internal/api/ 无告警;npm run build 通过。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
|
||||
> **命名规则:** `SY{NN}_{描述}.md`
|
||||
> **用途:** 系统概述、架构愿景、设计原则
|
||||
>
|
||||
> **当前统一口径:** 术语与一级导航请以 `SY21`、`SY22` 为准。
|
||||
> 当前产品一级导航目标态为:`新建任务 / 项目 / 专员·技能·APP·连接器 / 长程APP / 知识库 / 后台管理 / 我的`
|
||||
|
||||
## 文件清单
|
||||
|
||||
@@ -24,9 +27,14 @@
|
||||
| `SY14_Industry_Derived_Connector_And_Application_Requirement_Matrix.md` | 从六个行业反推连接器与应用方向矩阵 |
|
||||
| `SY15_Terminology_Benchmark_Ontology_Semantic_Layer_Object_Layer.md` | 本体层 / 语义层 / 对象层命名基准研究(含星邺汇捷 / Palantir / Microsoft / Salesforce 对照) |
|
||||
| `SY16_Ontology_Generalizes_Data_Actions_And_Workflows.md` | 本体如何让数据、动作、工作流一般化 |
|
||||
| `SY17_Workbench_UI_Wireframes.md` | 数字员工平台 UI 线框图(知识库固定 + 专员动态生长) |
|
||||
| `SY17_Workbench_UI_Wireframes.md` | 数字员工平台 UI 线框图(早期线框推演,当前命名与导航以 SY22 为准) |
|
||||
| `SY18_DWP_DW_ADW_Formal_Design_Contract.md` | DWP / DW / ADW 正式设计合同(供人和 AI 共用的对象基准) |
|
||||
| `SY19_Universal_Digital_Worker_Product_Planning.md` | 通用数字员工平台 V1.0 产品规划(先通用、后定制的产品打法收口) |
|
||||
| `SY20_Role_Card_And_Lightweight_Ontology_Architecture.md` | 角色卡与轻量本体对象架构(专家对象交互属性的历史收敛稿) |
|
||||
| `SY21_Unified_Role_Skill_Action_Architecture.md` | 统一 Expert / Skill / Action 总架构确认稿(六层架构与命名收口) |
|
||||
| `SY22_Role_Skill_App_Unified_Task_Architecture.md` | Expert / Skill / App 统一任务架构(把 App 升级为一级对象、补齐完整一级导航、并将知识库确认为默认内建 App,产品名收口为“长程APP”) |
|
||||
| `SY23_Specialist_Rule_File_And_Skill_Binding_Plan.md` | 专员「岗位说明书 + 技能绑定」改造方案(诊断运行时同质化根因 + 三步打通链路 + AionUi 规则文件改写清单) |
|
||||
| `SY24_Platform_Architecture_Rethink.md` | 数字员工平台整体架构重思考(Workbench 收敛与对象化迁移**历史稿**,其结论已并入 SY21 / SY22) |
|
||||
|
||||
## 当前主线关系
|
||||
|
||||
@@ -44,3 +52,8 @@
|
||||
12. `SY17`:把六层架构落成数字员工平台工作台线框,明确平台不再是单一导航后台
|
||||
13. `SY18`:正式定义 DWP / DW / ADW 的结构合同、字段规范和 AI 生成规则
|
||||
14. `SY19`:把当前阶段产品路线正式收口为「先通用数字员工、后行业包与企业定制」
|
||||
15. `SY20`:把角色卡从 UI 文案提升为角色对象内建属性,并确认轻量本体的落地边界
|
||||
16. `SY21`:正式收口六层架构与 `expert / skill / action / connector / policy` 总命名
|
||||
17. `SY22`:在 `SY21` 基础上补齐第三类一级对象 `app`,补全完整一级导航视图,并将知识库确认为默认内建 App,把平台升级为 Expert / Skill / App 三对象统一任务系统,产品名收口为“长程APP”
|
||||
18. `SY23`:定位到「专员与技能之间缺绑定边、专员说明未进 prompt」是专员的运行时空洞根因,给出三步打通方案与 AionUi 规则文件改写清单
|
||||
19. `SY24`:Workbench 收敛与对象化迁移的历史重思考稿,结论已并入 `SY21` / `SY22`;本文只作背景追溯,命名一律以 `SY21` 为准
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
# SY20 — 角色卡与轻量本体对象架构
|
||||
|
||||
> 状态:架构建议稿
|
||||
> 日期:2026-09-16
|
||||
> 关联文档:
|
||||
> - `SY03_Knowledge_Centric_Agent_Platform_Strategy.md`
|
||||
> - `docs/01_System_Overall/SY24_Platform_Architecture_Rethink.md`
|
||||
|
||||
> 2026-09-16 术语同步:
|
||||
> 本文档继续成立,但请以 `SY21_Unified_Role_Skill_Action_Architecture.md`、`SY22_Role_Skill_App_Unified_Task_Architecture.md` 为总架构收口版本。
|
||||
> 其中最关键的口径更新是:
|
||||
> - 角色卡属于专家对象属性,不再单列为独立架构层
|
||||
> - 对外当前统一采用 `专家 / 技能 / 长程APP / 知识库`
|
||||
> - 对内正式收敛为 `expert / skill / app / action / connector / policy`
|
||||
> - 当前一级导航目标态为 `新建任务 / 项目 / 专员·技能·APP·连接器 / 长程APP / 知识库 / 后台管理 / 我的`
|
||||
> - 本文中原先出现的“角色 / Role / 工具”概念,应理解为历史过渡词,未来命名统一转向 `专家 / 技能 / action`
|
||||
|
||||
---
|
||||
|
||||
## 1. 这份文档要回答什么
|
||||
|
||||
在当前工作台架构下,我们已经确认:
|
||||
|
||||
- 专员和技能都不应该再是独立页面
|
||||
- 它们都应该作为可挂载对象进入 `/home`
|
||||
- 当前最大问题已经不是“怎么跳转”,而是“对象本身怎么定义”
|
||||
|
||||
这份文档要回答 3 个关键问题:
|
||||
|
||||
1. 专员和技能型角色是否应该统一为同一种对象
|
||||
2. 是否应该引入类似 character.ai 的“角色卡”
|
||||
3. 是否应该在当前阶段引入“本体 / ontology”
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心结论
|
||||
|
||||
### 2.1 专员和工具应统一为同一种对象
|
||||
|
||||
建议统一收敛为:
|
||||
|
||||
**角色对象(Role Object)**
|
||||
|
||||
两者底层结构基本一致,差异只在能力边界:
|
||||
|
||||
- 工具:单能力、单任务域、通常不再继续调用别的工具
|
||||
- 专员:多步骤、可编排、允许调用工具完成子任务
|
||||
|
||||
也就是说:
|
||||
|
||||
**工具不是“低一层的页面”,而是“能力范围更窄的角色”。**
|
||||
|
||||
### 2.2 应该加入角色卡,而且要作为对象内建属性
|
||||
|
||||
建议明确加入:
|
||||
|
||||
**Role Card = 角色对象的可定义交互外壳**
|
||||
|
||||
它不只是欢迎语,而是对象如何被用户感知、如何开场、如何引导用户进入任务的第一层契约。
|
||||
|
||||
欢迎语应从硬编码 UI 文案,升级为:
|
||||
|
||||
**对象属性驱动的开场定义**
|
||||
|
||||
### 2.3 应该加入本体,但当前只做轻量本体
|
||||
|
||||
建议加入:
|
||||
|
||||
**轻量运营本体(Lightweight Operational Ontology)**
|
||||
|
||||
但不建议现在就上完整 RDF / OWL / SHACL 那套重语义工程。
|
||||
|
||||
当前阶段更合适的是:
|
||||
|
||||
- 先定义平台自己的对象类型、动作类型、产物类型、关系类型
|
||||
- 先服务工作台挂载、执行链、权限、结果展示
|
||||
- 先把“平台语义层”立起来
|
||||
|
||||
而不是一开始就追求语义网级别的正式本体工程。
|
||||
|
||||
---
|
||||
|
||||
## 3. 为什么要引入角色卡
|
||||
|
||||
### 3.1 当前问题
|
||||
|
||||
现在工作台的问题不是“没有欢迎语”这么简单,而是:
|
||||
|
||||
- 选了专员后,页面不知道该如何以这个对象的身份开场
|
||||
- 选了工具后,只是多了一个 chip,但没有人格化 / 职责化表达
|
||||
- 当前欢迎态仍然是“通用助手门厅”,不是“当前对象门厅”
|
||||
|
||||
这说明我们缺的不是一句文案,而是:
|
||||
|
||||
**对象自我介绍能力**
|
||||
|
||||
### 3.2 角色卡的价值
|
||||
|
||||
角色卡负责定义:
|
||||
|
||||
1. 这个对象是谁
|
||||
2. 它擅长什么
|
||||
3. 它怎么和用户说话
|
||||
4. 它建议用户怎么开始
|
||||
5. 它不做什么
|
||||
|
||||
所以角色卡不是装饰,而是对象定义的一部分。
|
||||
|
||||
### 3.3 角色卡应该覆盖的内容
|
||||
|
||||
建议 `role_card` 最少包含:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "合同审查专员",
|
||||
"tagline": "把合同风险、红线和交付意见整理清楚",
|
||||
"greeting": "我是合同审查专员,已经准备好帮你定位条款风险、整理红线建议,并输出可交付的审查结果。",
|
||||
"relationship_to_user": "你的法务协作搭档",
|
||||
"tone": "专业、直接、可追溯",
|
||||
"opening_prompt": "把合同发给我,或者直接告诉我这次要重点盯哪些条款。",
|
||||
"starter_prompts": [
|
||||
"审查这份采购合同的风险点",
|
||||
"帮我整理一版 redline 建议",
|
||||
"重点看赔偿责任和终止条款"
|
||||
],
|
||||
"boundaries": [
|
||||
"我会指出风险,但不替代人工法律意见",
|
||||
"高风险条款会明确标出待人工确认"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 为什么要引入轻量本体
|
||||
|
||||
### 4.1 我们真正需要的不是“知识图谱名词”,而是平台统一语义
|
||||
|
||||
如果没有本体层,平台会继续出现这些问题:
|
||||
|
||||
- 专员和工具只是 UI 名字,没有统一语义身份
|
||||
- 任务挂的是 `specialist_key`,但系统不知道对象之间是什么关系
|
||||
- 工作流、产物、动作、知识对象各自分散,难以统一编排
|
||||
- 后面做多对象协作时,平台不知道谁能调用谁、产出什么、依赖什么
|
||||
|
||||
### 4.2 当前阶段不适合直接上重本体
|
||||
|
||||
完整本体工程的问题不在“对不对”,而在“此刻成本太高”:
|
||||
|
||||
- 建模成本高
|
||||
- 治理成本高
|
||||
- 版本演进成本高
|
||||
- 需要更成熟的数据治理和知识工程流程
|
||||
|
||||
对我们当前阶段来说,最重要的是先统一平台对象语义,而不是先做语义网工程。
|
||||
|
||||
### 4.3 当前阶段建议的本体范围
|
||||
|
||||
建议只定义 5 类核心语义:
|
||||
|
||||
1. **角色类型**
|
||||
- specialist
|
||||
- tool
|
||||
|
||||
2. **对象类型**
|
||||
- contract
|
||||
- customer
|
||||
- report
|
||||
- resume
|
||||
- knowledge_item
|
||||
|
||||
3. **动作类型**
|
||||
- analyze
|
||||
- extract
|
||||
- review
|
||||
- draft
|
||||
- translate
|
||||
- escalate
|
||||
|
||||
4. **产物类型**
|
||||
- summary
|
||||
- report
|
||||
- redline
|
||||
- checklist
|
||||
- spreadsheet
|
||||
|
||||
5. **关系类型**
|
||||
- can_use_tool
|
||||
- produces_artifact
|
||||
- acts_on_object
|
||||
- depends_on
|
||||
- cites_knowledge
|
||||
|
||||
这就足以支撑我们当前的工作台对象化。
|
||||
|
||||
---
|
||||
|
||||
## 5. 建议采用的统一对象架构
|
||||
|
||||
### 5.1 根对象:`object_definition`
|
||||
|
||||
不建议再把“专员定义”和“工具定义”拆成两套根结构。
|
||||
|
||||
建议统一使用已有方向里的:
|
||||
|
||||
**`object_definition`**
|
||||
|
||||
然后在里面用 `role_kind` 区分:
|
||||
|
||||
- `specialist`
|
||||
- `tool`
|
||||
|
||||
### 5.2 建议结构
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "obj.contract-review",
|
||||
"code": "EAI-R-001",
|
||||
"key": "contract-review",
|
||||
"label": "合同审查专员",
|
||||
"object_class": "role",
|
||||
"role_kind": "specialist",
|
||||
"source": "eai",
|
||||
"status": "active",
|
||||
"role_card": {
|
||||
"tagline": "把合同风险、红线和交付意见整理清楚",
|
||||
"greeting": "我是合同审查专员,已经准备好帮你定位条款风险并输出审查建议。",
|
||||
"relationship_to_user": "你的法务协作搭档",
|
||||
"tone": "专业、直接、可追溯",
|
||||
"opening_prompt": "把合同发给我,或者告诉我这次重点审哪些条款。",
|
||||
"starter_prompts": [
|
||||
"审查这份采购合同的风险点",
|
||||
"帮我整理一版 redline 建议"
|
||||
],
|
||||
"boundaries": [
|
||||
"我会标出高风险项",
|
||||
"最终法律意见仍需人工确认"
|
||||
]
|
||||
},
|
||||
"capability_profile": {
|
||||
"summary": "条款识别、风险分析、红线建议、交付摘要",
|
||||
"input_types": ["document", "text"],
|
||||
"artifact_types": ["summary", "redline", "checklist"],
|
||||
"can_chat": true,
|
||||
"can_execute": true
|
||||
},
|
||||
"collaboration_profile": {
|
||||
"callable_tool_keys": ["document-translate", "batch-extract"],
|
||||
"can_be_called_by": [],
|
||||
"orchestration_mode": "supervisor"
|
||||
},
|
||||
"ontology_binding": {
|
||||
"acts_on_object_types": ["contract"],
|
||||
"action_types": ["review", "analyze", "draft"],
|
||||
"produces_artifact_types": ["summary", "redline", "checklist"],
|
||||
"knowledge_domains": ["legal", "compliance"]
|
||||
},
|
||||
"execution_profile": {
|
||||
"settings_schema": [],
|
||||
"executor_key": "contract-review",
|
||||
"result_card_key": "contract-review"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 工具对象也用同一结构
|
||||
|
||||
工具只是把 `role_kind` 改为 `tool`:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "document-translate",
|
||||
"label": "文档翻译",
|
||||
"object_class": "role",
|
||||
"role_kind": "tool",
|
||||
"role_card": {
|
||||
"tagline": "把内容准确翻译成目标语言并输出指定格式",
|
||||
"greeting": "我是文档翻译工具,可以把文本、文档整理成目标语言输出。",
|
||||
"relationship_to_user": "你的翻译执行角色"
|
||||
},
|
||||
"collaboration_profile": {
|
||||
"callable_tool_keys": [],
|
||||
"orchestration_mode": "none"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
也就是说:
|
||||
|
||||
**工具和专员不是两套模型,而是一套模型上的两个角色种类。**
|
||||
|
||||
---
|
||||
|
||||
## 6. 专员与工具的真正差异
|
||||
|
||||
建议只保留这一个核心差异:
|
||||
|
||||
### 6.1 工具
|
||||
|
||||
- 聚焦单能力
|
||||
- 输入输出边界更明确
|
||||
- 通常不再调别的工具
|
||||
- 更像“执行角色”
|
||||
|
||||
### 6.2 专员
|
||||
|
||||
- 聚焦任务闭环
|
||||
- 可以调用多个工具
|
||||
- 会管理步骤、产物、待确认点
|
||||
- 更像“编排角色”
|
||||
|
||||
所以:
|
||||
|
||||
**专员 = 能调用工具的角色对象**
|
||||
|
||||
而不是:
|
||||
|
||||
**专员 = 页面,工具 = 页面里的功能按钮**
|
||||
|
||||
---
|
||||
|
||||
## 7. 对工作台交互的直接影响
|
||||
|
||||
### 7.1 欢迎态改成对象驱动
|
||||
|
||||
当前 `/home` 的欢迎态不应再写死成通用助手。
|
||||
|
||||
应该改为:
|
||||
|
||||
1. 如果当前挂的是对象,就优先显示该对象的 `role_card.greeting`
|
||||
2. `starter_prompts` 作为欢迎态快捷入口
|
||||
3. `tagline / opening_prompt / boundaries` 作为辅助说明
|
||||
4. 如果没有挂对象,再退回通用助手默认欢迎态
|
||||
|
||||
### 7.2 输入框左侧对象 chip 不再只是标签
|
||||
|
||||
它应表达:
|
||||
|
||||
- 当前对象是谁
|
||||
- 当前对象属于 `specialist` 还是 `tool`
|
||||
- 当前对象的 `tagline`
|
||||
|
||||
### 7.3 右栏不应再叫“专员面板”
|
||||
|
||||
因为工具也是角色对象。
|
||||
|
||||
建议后续改成更中性的:
|
||||
|
||||
- `ObjectPanel`
|
||||
- `RolePanel`
|
||||
|
||||
只是当对象是 `specialist` 时,展示更完整的工作流与产物;
|
||||
当对象是 `tool` 时,展示它的输入边界、执行结果、相关产物。
|
||||
|
||||
---
|
||||
|
||||
## 8. 对数据层的建议
|
||||
|
||||
### 8.1 先别引入新根对象名,先复用 `object_definition`
|
||||
|
||||
当前项目已经在往:
|
||||
|
||||
- `object_definition`
|
||||
- `task_object_instance`
|
||||
- `object_run`
|
||||
- `task_message`
|
||||
|
||||
这条路上走。
|
||||
|
||||
因此不建议再新起一套:
|
||||
|
||||
- `specialist_definition`
|
||||
- `tool_definition`
|
||||
- `role_definition`
|
||||
|
||||
而是:
|
||||
|
||||
**在 `object_definition` 里加角色属性分组。**
|
||||
|
||||
### 8.2 建议新增的对象属性分组
|
||||
|
||||
建议统一加这几组:
|
||||
|
||||
- `role_kind`
|
||||
- `role_card_json`
|
||||
- `capability_profile_json`
|
||||
- `collaboration_profile_json`
|
||||
- `ontology_binding_json`
|
||||
|
||||
### 8.3 后端可以分阶段兼容
|
||||
|
||||
第一阶段不必立刻改完后端表。
|
||||
|
||||
可以先在前端 registry 和 specialist adapter 里形成统一结构:
|
||||
|
||||
- 内置工具走前端静态定义
|
||||
- 专员走后端字段 + 前端适配
|
||||
- 统一映射成 `object_definition` 视图模型
|
||||
|
||||
等结构稳定后,再把后端持久化模型补齐。
|
||||
|
||||
---
|
||||
|
||||
## 9. 当前阶段的实施建议
|
||||
|
||||
### Phase 1:先把角色卡引入前端对象视图层
|
||||
|
||||
先做:
|
||||
|
||||
- `role_card` 统一适配层
|
||||
- `/home` 欢迎态改为对象驱动
|
||||
- 专员 / 工具都能显示自己的 greeting 与 starter prompts
|
||||
|
||||
这一步不要求后端表结构大改。
|
||||
|
||||
### Phase 2:把 Studio / Market 的专员编辑升级为对象编辑
|
||||
|
||||
新增:
|
||||
|
||||
- 欢迎语
|
||||
- tagline
|
||||
- opening prompt
|
||||
- starter prompts
|
||||
- boundaries
|
||||
|
||||
让专员卡真正可定义。
|
||||
|
||||
工具也开始逐步以同样结构注册。
|
||||
|
||||
### Phase 3:补轻量本体层
|
||||
|
||||
建立平台统一字典:
|
||||
|
||||
- object types
|
||||
- action types
|
||||
- artifact types
|
||||
- relation types
|
||||
|
||||
先服务工作台、运行链和知识引用,不追求重语义工程。
|
||||
|
||||
---
|
||||
|
||||
## 10. 最终建议
|
||||
|
||||
这次不建议二选一,而是建议同时引入两层:
|
||||
|
||||
### 必须现在就做
|
||||
|
||||
1. **角色卡**
|
||||
- 必须加
|
||||
- 而且要作为对象属性
|
||||
- 欢迎语、引导语、starter prompts 都应从这里来
|
||||
|
||||
2. **统一对象模型**
|
||||
- 专员和工具统一为 `object_definition`
|
||||
- 用 `role_kind` 区分
|
||||
- 专员只是“可调用工具的角色”
|
||||
|
||||
### 应该现在开始,但先做轻量版
|
||||
|
||||
3. **轻量本体**
|
||||
- 必须做
|
||||
- 但只做平台运营本体
|
||||
- 不要一开始就上重 RDF / OWL 工程
|
||||
|
||||
### 暂时不要做的事
|
||||
|
||||
4. 不要再继续把“欢迎语”写成页面模板文案
|
||||
5. 不要再继续把“工具”当页面,而不是角色
|
||||
6. 不要现在就把本体做成知识工程大项目
|
||||
|
||||
---
|
||||
|
||||
## 11. 一句话收口
|
||||
|
||||
建议把平台对象统一定义为:
|
||||
|
||||
**“带角色卡的角色对象”**
|
||||
|
||||
其中:
|
||||
|
||||
- 工具 = 单能力角色
|
||||
- 专员 = 可调用工具的编排角色
|
||||
- 本体 = 这些角色、动作、对象、产物之间的轻量语义骨架
|
||||
@@ -0,0 +1,691 @@
|
||||
# SY21 — 统一 Expert / Skill / Action 总架构确认稿
|
||||
|
||||
> 状态:总架构确认稿
|
||||
> 日期:2026-09-16
|
||||
> 关联文档:
|
||||
> - `SY03_Knowledge_Centric_Agent_Platform_Strategy.md`
|
||||
> - `SY15_Terminology_Benchmark_Ontology_Semantic_Layer_Object_Layer.md`
|
||||
> - `SY20_Role_Card_And_Lightweight_Ontology_Architecture.md`
|
||||
> - `docs/01_System_Overall/SY24_Platform_Architecture_Rethink.md`
|
||||
|
||||
> 2026-09-16 术语同步:
|
||||
> 本文原先使用 `Role / role / role_card` 作为主术语。
|
||||
> 现已确认 `Role` 不再作为推荐命名,统一改口为:
|
||||
> - 对外:`专家(Expert) / 技能 / 连接器`
|
||||
> - 对内:`expert / skill / action / connector / policy`
|
||||
> 文中尚未完全迁移的 `role`、`role_card`、`角色对象层`,后续均应分别理解为 `expert`、`expert_card`、`专家对象层`。
|
||||
|
||||
---
|
||||
|
||||
## 1. 这份文档要确认什么
|
||||
|
||||
在前面几轮讨论后,当前项目已经不再缺“局部页面方案”,真正缺的是一份统一总架构结论,用来回答以下问题:
|
||||
|
||||
1. 平台到底按几层架构来收敛
|
||||
2. 本体、角色卡、对象、技能、Action、连接器分别处于什么位置
|
||||
3. 对外到底暴露什么,对内到底运行什么
|
||||
4. 是否还要继续使用 `tool` 这个词
|
||||
5. 当前代码和文档后续应该往哪个方向迁移
|
||||
|
||||
这份文档的目标不是给出某个局部功能设计,而是把平台的总语言、总结构、总对象模型先定下来。
|
||||
|
||||
---
|
||||
|
||||
## 2. 最终结论
|
||||
|
||||
## 2.1 平台采用六层总架构
|
||||
|
||||
建议正式统一为六层:
|
||||
|
||||
1. 外部连接层
|
||||
2. 本体与语义上下文层
|
||||
3. 总线与编排层
|
||||
4. 能力层
|
||||
5. 专家对象层
|
||||
6. 工作台与运行治理层
|
||||
|
||||
这六层已经足以覆盖:
|
||||
|
||||
- 通用数字员工
|
||||
- 文档类、知识类、分析类能力
|
||||
- 工业设备监测、安防、巡检、告警、工单等强外部接口场景
|
||||
|
||||
## 2.2 不再把 `tool` 作为正式命名
|
||||
|
||||
命名上正式收敛为:
|
||||
|
||||
- 对外:`专家 / 技能 / 连接器`
|
||||
- 对内:`expert / skill / action / connector / policy`
|
||||
|
||||
结论:
|
||||
|
||||
**以后不再新增正式架构概念 `tool`。**
|
||||
|
||||
`tool` 只作为历史迁移词存在,用于兼容旧文档、旧字段、旧目录,不再作为未来架构的主词。
|
||||
|
||||
## 2.3 对外默认暴露 `专家 + 技能`
|
||||
|
||||
外部用户看到的应该是:
|
||||
|
||||
- 专家
|
||||
- 技能
|
||||
- 欢迎语
|
||||
- starter prompts
|
||||
- 可完成的任务
|
||||
|
||||
而不是:
|
||||
|
||||
- tool 列表
|
||||
- 底层调用动作
|
||||
- 技术执行接口
|
||||
|
||||
所以:
|
||||
|
||||
**用户入口层默认暴露 skill,不暴露 action。**
|
||||
|
||||
## 2.4 对内统一使用 `action`
|
||||
|
||||
内部最小执行单元统一叫:
|
||||
|
||||
**Action**
|
||||
|
||||
它用于承接:
|
||||
|
||||
- 一次原子能力执行
|
||||
- 一次外部系统调用
|
||||
- 一次标准化输入输出动作
|
||||
- 一次可授权、可审计、可编排的执行操作
|
||||
|
||||
也就是说:
|
||||
|
||||
- `skill` 是任务化能力包
|
||||
- `action` 是原子执行单元
|
||||
|
||||
## 2.5 要引入本体层,而且是必需的
|
||||
|
||||
如果平台后续要扩展到:
|
||||
|
||||
- 工业设备运行监测员
|
||||
- 安防管理员
|
||||
- 巡检专员
|
||||
- 告警分析专员
|
||||
- 工单协调专员
|
||||
|
||||
那么本体层不是可选项,而是必要项。
|
||||
|
||||
原因很简单:
|
||||
|
||||
没有本体层,上层对象和工作台体验很快就会被行业对象、事件、状态、规则的差异撕裂。
|
||||
|
||||
## 2.6 专家卡不是独立层,而是专家对象属性
|
||||
|
||||
角色卡仍然要保留,但它不是一层单独架构层。
|
||||
|
||||
更准确的定义是:
|
||||
|
||||
**专家卡 = 专家对象的交互属性集**
|
||||
|
||||
它负责:
|
||||
|
||||
- 角色是谁
|
||||
- 角色如何开场
|
||||
- 角色如何和用户说话
|
||||
- 角色建议用户如何开始
|
||||
- 角色承诺做什么、不做什么
|
||||
|
||||
---
|
||||
|
||||
## 3. 六层总架构定义
|
||||
|
||||
## 3.1 第一层:外部连接层
|
||||
|
||||
这一层负责连接真实世界和外部系统。
|
||||
|
||||
包括:
|
||||
|
||||
- PLC
|
||||
- SCADA
|
||||
- MES
|
||||
- ERP
|
||||
- CRM
|
||||
- CMMS / 工单系统
|
||||
- IoT 平台
|
||||
- 视频平台
|
||||
- 文档系统
|
||||
- 数据库
|
||||
- API / Webhook / MQ
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**数据从哪里来,动作往哪里去。**
|
||||
|
||||
在本项目里,这一层的标准对象是:
|
||||
|
||||
- `connector_definition`
|
||||
- `connector_binding`
|
||||
|
||||
## 3.2 第二层:本体与语义上下文层
|
||||
|
||||
这一层负责定义平台语义。
|
||||
|
||||
它不是简单的表结构,而是平台统一语义底座。
|
||||
|
||||
当前阶段建议采用轻量本体,先定义:
|
||||
|
||||
1. 对象类型
|
||||
- device
|
||||
- alarm
|
||||
- work_order
|
||||
- report
|
||||
- contract
|
||||
- knowledge_item
|
||||
- person
|
||||
- site
|
||||
|
||||
2. 动作类型
|
||||
- monitor
|
||||
- inspect
|
||||
- diagnose
|
||||
- review
|
||||
- extract
|
||||
- translate
|
||||
- escalate
|
||||
- dispatch
|
||||
|
||||
3. 状态类型
|
||||
- running
|
||||
- warning
|
||||
- critical
|
||||
- pending
|
||||
- approved
|
||||
- closed
|
||||
|
||||
4. 关系类型
|
||||
- belongs_to
|
||||
- depends_on
|
||||
- triggers
|
||||
- resolves
|
||||
- cites
|
||||
- produces
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**系统里到底有什么对象,它们如何关联,允许哪些动作。**
|
||||
|
||||
## 3.3 第三层:总线与编排层
|
||||
|
||||
这一层负责流转,不负责人格,不负责 UI。
|
||||
|
||||
它至少应包含三类总线:
|
||||
|
||||
1. 上下文总线
|
||||
2. 事件总线
|
||||
3. 能力编排总线
|
||||
|
||||
职责包括:
|
||||
|
||||
- 角色之间的协作
|
||||
- skill 对 action 的编排
|
||||
- action 对 connector 的调用
|
||||
- 事件进入任务上下文
|
||||
- 审批和安全边界控制
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**对象怎么流动,能力怎么协作,任务怎么推进。**
|
||||
|
||||
## 3.4 第四层:能力层
|
||||
|
||||
这一层正式拆成三类对象:
|
||||
|
||||
1. `skill`
|
||||
2. `action`
|
||||
3. `policy`
|
||||
|
||||
### 3.4.1 skill
|
||||
|
||||
`skill` 是面向任务的能力包。
|
||||
|
||||
它通常由以下部分组成:
|
||||
|
||||
- intent
|
||||
- prompt template
|
||||
- action chain
|
||||
- input schema
|
||||
- output schema
|
||||
- artifact schema
|
||||
- guardrails
|
||||
|
||||
可以理解为:
|
||||
|
||||
**skill = 用户任务入口 + 规则 + 执行编排模板**
|
||||
|
||||
### 3.4.2 action
|
||||
|
||||
`action` 是内部原子执行单元。
|
||||
|
||||
例如:
|
||||
|
||||
- `read_device_status`
|
||||
- `query_alarm_history`
|
||||
- `create_work_order`
|
||||
- `extract_contract_terms`
|
||||
- `translate_document`
|
||||
- `generate_shift_report`
|
||||
|
||||
它必须具备:
|
||||
|
||||
- 标准输入
|
||||
- 标准输出
|
||||
- 权限边界
|
||||
- 风险级别
|
||||
- 审计记录
|
||||
|
||||
### 3.4.3 policy
|
||||
|
||||
`policy` 负责定义约束和治理条件,例如:
|
||||
|
||||
- 某 action 是否允许自动执行
|
||||
- 是否需要人工确认
|
||||
- 哪些角色可以调用哪些 skill
|
||||
- 哪些 connector 只能读不能写
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**系统能做哪些事,这些事如何以任务化和原子化两种粒度存在。**
|
||||
|
||||
## 3.5 第五层:专家对象层
|
||||
|
||||
这是用户真正感知到的执行主体层。
|
||||
|
||||
专家对象统一采用一个根模型,例如:
|
||||
|
||||
- `object_definition`
|
||||
|
||||
专家对象不再分裂成多套根结构。
|
||||
|
||||
建议至少包含两类专家:
|
||||
|
||||
1. `assistant`
|
||||
2. `specialist`
|
||||
|
||||
如果后续需要更强的“执行人格化对象”,可补充:
|
||||
|
||||
3. `executor`
|
||||
|
||||
其中:
|
||||
|
||||
- `assistant`:默认兜底编排专家
|
||||
- `specialist`:面向领域任务的主专家
|
||||
- `executor`:必要时暴露给用户的窄能力执行专家
|
||||
|
||||
这里最关键的变化是:
|
||||
|
||||
**专家对象不直接等于 action。**
|
||||
|
||||
专家对象负责承接用户、暴露 skill、组织交互体验;
|
||||
真正执行时,仍然落到 `skill -> action -> connector`。
|
||||
|
||||
### 3.5.1 专家卡属于这一层
|
||||
|
||||
`expert_card` 是专家对象属性,不再单列成架构层。
|
||||
|
||||
建议最少包含:
|
||||
|
||||
- name
|
||||
- tagline
|
||||
- greeting
|
||||
- tone
|
||||
- opening_prompt
|
||||
- starter_prompts
|
||||
- boundaries
|
||||
- relationship_to_user
|
||||
|
||||
### 3.5.2 专家对象与能力层的关系
|
||||
|
||||
专家对象不直接暴露所有 action。
|
||||
|
||||
更合适的关系是:
|
||||
|
||||
- 专家对象暴露 `skill`
|
||||
- `skill` 编排多个 `action`
|
||||
- `action` 调用 `connector`
|
||||
|
||||
所以:
|
||||
|
||||
**专家承接用户,skill 组织任务,action 执行动作。**
|
||||
|
||||
## 3.6 第六层:工作台与运行治理层
|
||||
|
||||
这一层是最终运行现场。
|
||||
|
||||
包括:
|
||||
|
||||
- `/home` Workbench
|
||||
- task
|
||||
- task_message
|
||||
- task_object_instance
|
||||
- object_run
|
||||
- artifact
|
||||
- workflow panel
|
||||
- audit / observe / approval
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**一条具体任务如何挂载角色、发送消息、运行 skill、触发 action、沉淀产物。**
|
||||
|
||||
---
|
||||
|
||||
## 4. 最终对象关系
|
||||
|
||||
建议以后统一采用下面这条主链路:
|
||||
|
||||
`user -> expert -> skill -> action -> connector`
|
||||
|
||||
再叠加本体层:
|
||||
|
||||
`ontology -> expert / skill / action / connector`
|
||||
|
||||
也就是说:
|
||||
|
||||
1. 用户不是直接找 action
|
||||
2. 用户是进入某个专家
|
||||
3. 专家向用户暴露 skill
|
||||
4. skill 编排 action
|
||||
5. action 调用 connector
|
||||
6. 全程受 ontology 和 policy 约束
|
||||
|
||||
---
|
||||
|
||||
## 5. 对外暴露模型
|
||||
|
||||
## 5.1 对终端用户
|
||||
|
||||
默认暴露:
|
||||
|
||||
- 专员
|
||||
- 技能
|
||||
- 欢迎语
|
||||
- 任务入口
|
||||
- 产物结果
|
||||
|
||||
默认不暴露:
|
||||
|
||||
- action
|
||||
- connector 技术细节
|
||||
- 编排细节
|
||||
- 底层风险策略
|
||||
|
||||
## 5.2 对管理员 / 搭建者
|
||||
|
||||
可以暴露:
|
||||
|
||||
- skill 绑定了哪些 action
|
||||
- action 绑定了哪些 connector
|
||||
- 权限和审批条件
|
||||
- 输出 schema
|
||||
- 审计与日志
|
||||
|
||||
## 5.3 对运行时
|
||||
|
||||
直接处理:
|
||||
|
||||
- action call
|
||||
- connector call
|
||||
- context binding
|
||||
- event routing
|
||||
- approval gate
|
||||
- audit log
|
||||
|
||||
---
|
||||
|
||||
## 6. 为什么不再使用 `tool`
|
||||
|
||||
## 6.1 对外不合适
|
||||
|
||||
`tool` 太像功能按钮集合,不像任务语言,也不像角色语言。
|
||||
|
||||
尤其在数字员工和工业智能体场景里,它会把产品体验拉回“工具页”心智。
|
||||
|
||||
## 6.2 对内也不够精确
|
||||
|
||||
内部真正需要区分的是:
|
||||
|
||||
- 任务级能力包:`skill`
|
||||
- 原子执行动作:`action`
|
||||
- 外部系统入口:`connector`
|
||||
|
||||
`tool` 夹在中间,语义反而模糊。
|
||||
|
||||
## 6.3 正式命名替换
|
||||
|
||||
后续正式命名建议统一为:
|
||||
|
||||
- 用户可见的 `tool` -> `skill`
|
||||
- 内部原子执行的 `tool` -> `action`
|
||||
- `chatTools` -> `availableSkills`
|
||||
- `currentToolKey` -> `currentSkillKey`
|
||||
- `tool_keys` -> `skill_keys`
|
||||
- 顶部设置条组件 -> `SkillStrip` 或 `ActionStrip`
|
||||
- 前端技能定义目录 -> `src/skills/*`
|
||||
- 后端原子动作定义 -> `action_definition / action_refs / action_records`
|
||||
|
||||
说明:
|
||||
|
||||
当前仓库已有大量 `tool` 历史字段,不建议在总架构确认稿阶段立刻全量重命名;
|
||||
但从现在开始,**不再新增新的正式 `tool` 命名。**
|
||||
|
||||
---
|
||||
|
||||
## 7. 角色、技能、Action 的清晰边界
|
||||
|
||||
## 7.1 角色
|
||||
|
||||
回答的是:
|
||||
|
||||
**谁来承接这次任务。**
|
||||
|
||||
角色包含:
|
||||
|
||||
- 身份
|
||||
- 角色卡
|
||||
- 协作边界
|
||||
- 可暴露 skills
|
||||
- 权限范围
|
||||
|
||||
## 7.2 技能
|
||||
|
||||
回答的是:
|
||||
|
||||
**用户想完成什么任务。**
|
||||
|
||||
技能包含:
|
||||
|
||||
- 任务意图
|
||||
- 开始条件
|
||||
- 输入输出约束
|
||||
- 产物定义
|
||||
- 对 action 的编排模板
|
||||
|
||||
## 7.3 Action
|
||||
|
||||
回答的是:
|
||||
|
||||
**系统这一步到底执行了什么动作。**
|
||||
|
||||
Action 包含:
|
||||
|
||||
- 原子能力定义
|
||||
- 风险级别
|
||||
- 调用协议
|
||||
- connector 绑定
|
||||
- 审计信息
|
||||
|
||||
---
|
||||
|
||||
## 8. 角色卡和本体是否重叠
|
||||
|
||||
不重叠。
|
||||
|
||||
它们都可能写到“能力”相关内容,但目标完全不同。
|
||||
|
||||
## 8.1 本体
|
||||
|
||||
服务机器一致性,定义:
|
||||
|
||||
- 对象
|
||||
- 动作
|
||||
- 状态
|
||||
- 关系
|
||||
- 规则
|
||||
|
||||
## 8.2 角色卡
|
||||
|
||||
服务人机交互一致性,定义:
|
||||
|
||||
- 开场方式
|
||||
- 角色语气
|
||||
- 任务入口提示
|
||||
- 用户对该角色的体验预期
|
||||
|
||||
一句话:
|
||||
|
||||
**本体定义世界,角色卡定义人格。**
|
||||
|
||||
---
|
||||
|
||||
## 9. 对当前 Workbench 的直接要求
|
||||
|
||||
## 9.1 欢迎语必须对象属性驱动
|
||||
|
||||
当用户挂载某个角色后,Workbench 不应继续显示通用助手欢迎语。
|
||||
|
||||
应改为:
|
||||
|
||||
1. 优先显示当前专家的 `expert_card.greeting`
|
||||
2. 下方展示 `starter_prompts`
|
||||
3. 辅助展示 `tagline / opening_prompt / boundaries`
|
||||
4. 无挂载角色时,再退回默认助手欢迎态
|
||||
|
||||
## 9.2 输入区顶部应体现当前对象
|
||||
|
||||
输入区顶部不应只显示一个孤立 chip。
|
||||
|
||||
应明确表达:
|
||||
|
||||
- 当前对象是谁
|
||||
- 当前这次输入会触发什么任务语义
|
||||
- 当前对象是否存在可调设置
|
||||
|
||||
并冻结以下交互规则:
|
||||
|
||||
1. `+` 右边一次只显示一个当前对象
|
||||
2. 当前对象要么是专员,要么是技能,要么是默认助手
|
||||
3. 专员内部调用技能时,下游技能只进入执行链与右侧面板,不在输入区显性双挂
|
||||
|
||||
## 9.3 右侧面板应是对象面板,不再是旧“工具面板”
|
||||
|
||||
建议中性命名:
|
||||
|
||||
- `ObjectPanel`
|
||||
- `ExpertPanel`
|
||||
|
||||
其内容由当前角色和当前运行态决定,而不是由旧页面类型决定。
|
||||
|
||||
---
|
||||
|
||||
## 10. 目标数据结构建议
|
||||
|
||||
## 10.1 角色定义 `object_definition`
|
||||
|
||||
建议继续作为统一根对象,至少补充:
|
||||
|
||||
- `object_kind`
|
||||
- `expert_card_json`
|
||||
- `capability_profile_json`
|
||||
- `collaboration_profile_json`
|
||||
- `ontology_binding_json`
|
||||
|
||||
## 10.2 技能定义 `skill_definition`
|
||||
|
||||
建议新增独立定义层,至少包含:
|
||||
|
||||
- `id`
|
||||
- `key`
|
||||
- `label`
|
||||
- `description`
|
||||
- `exposed_to_user`
|
||||
- `input_schema`
|
||||
- `output_schema`
|
||||
- `artifact_schema`
|
||||
- `action_refs`
|
||||
- `policy_refs`
|
||||
- `ontology_binding`
|
||||
|
||||
## 10.3 Action 定义 `action_definition`
|
||||
|
||||
建议新增,至少包含:
|
||||
|
||||
- `id`
|
||||
- `key`
|
||||
- `label`
|
||||
- `action_type`
|
||||
- `connector_ref`
|
||||
- `input_schema`
|
||||
- `output_schema`
|
||||
- `risk_level`
|
||||
- `approval_mode`
|
||||
- `audit_level`
|
||||
|
||||
## 10.4 运行态
|
||||
|
||||
建议继续沿用并收敛为:
|
||||
|
||||
- `task`
|
||||
- `task_object_instance`
|
||||
- `task_message`
|
||||
- `object_run`
|
||||
- `artifact`
|
||||
|
||||
其中:
|
||||
|
||||
- `task_object_instance` 负责挂载当前角色
|
||||
- `task_message` 负责持久化会话
|
||||
- `object_run` 负责记录 skill 和 action 的执行链
|
||||
|
||||
---
|
||||
|
||||
## 11. 对当前项目的迁移原则
|
||||
|
||||
## 11.1 总原则
|
||||
|
||||
先定语言,再改代码。
|
||||
|
||||
当前阶段最重要的是把架构口径统一为:
|
||||
|
||||
- 六层总架构
|
||||
- 对外 `角色 + 技能`
|
||||
- 对内 `skill + action + connector`
|
||||
- `tool` 正式退出未来命名
|
||||
|
||||
## 11.2 当前阶段不要做的事
|
||||
|
||||
1. 不要继续新增 `tool` 概念
|
||||
2. 不要再把 action 做成独立页面
|
||||
3. 不要再让路由承担能力身份
|
||||
4. 不要让欢迎语继续写死在页面里
|
||||
|
||||
## 11.3 下一阶段最值得做的事
|
||||
|
||||
1. 先把当前架构文档同步到这一套口径
|
||||
2. 再把前端欢迎态改为 `expert_card.greeting` 驱动
|
||||
3. 再把 `tool` 相关变量和目录逐步迁移到 `skill / action`
|
||||
4. 后续再进入数据库与运行时的对象化升级
|
||||
|
||||
---
|
||||
|
||||
## 12. 一句话总收口
|
||||
|
||||
平台以后应统一理解为:
|
||||
|
||||
**一个以本体为语义底座、以角色为用户承接体、以技能为任务入口、以 Action 为原子执行单元、以 Workbench 为统一运行现场的数字员工与工业智能体平台。**
|
||||
@@ -0,0 +1,755 @@
|
||||
# SY22 — Expert / Skill / App 统一任务架构
|
||||
|
||||
> 状态:总架构扩展确认稿
|
||||
> 日期:2026-09-16
|
||||
> 关联文档:
|
||||
> - `SY17_Workbench_UI_Wireframes.md`
|
||||
> - `SY20_Role_Card_And_Lightweight_Ontology_Architecture.md`
|
||||
> - `SY21_Unified_Role_Skill_Action_Architecture.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. 这份文档要解决什么问题
|
||||
|
||||
在 `SY21` 中,平台已经正式收敛为六层架构,并明确了:
|
||||
|
||||
- 对外暴露 `专家 / 技能 / 连接器`
|
||||
- 对内运行 `expert / skill / action / connector / policy`
|
||||
- 不再继续扩张 `tool` 概念
|
||||
|
||||
但随着工作台进一步向 WorkBuddy 类产品演进,出现了一个新问题:
|
||||
|
||||
**系统里需要一种既不是专家、也不是技能的新一级对象。**
|
||||
|
||||
它具备以下特征:
|
||||
|
||||
- 不是以对话为主交互
|
||||
- 有自己长期存在的主界面
|
||||
- 有结构化状态、表单、题卡、看板、画布等交互
|
||||
- 启动后应成为一个长程任务实例
|
||||
- 可挂载右栏 AI、可调用技能、可沉淀业务产物
|
||||
|
||||
这类对象不适合继续塞进 `expert`,也不适合伪装成“大 skill”。
|
||||
|
||||
因此,这份文档正式确认:
|
||||
|
||||
> **平台需要第三类一级对象:App。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 最终结论
|
||||
|
||||
## 2.1 六层总架构继续成立,但第五层升级
|
||||
|
||||
`SY21` 的六层架构继续有效:
|
||||
|
||||
1. 外部连接层
|
||||
2. 本体与语义上下文层
|
||||
3. 总线与编排层
|
||||
4. 能力层
|
||||
5. 对象层
|
||||
6. 工作台与运行治理层
|
||||
|
||||
本次变化不是推翻六层,而是把第五层从偏“专家对象层”正式升级为:
|
||||
|
||||
> **对象层(Expert / Skill / App)**
|
||||
|
||||
## 2.2 App 是一级对象,不是页面,也不是大技能
|
||||
|
||||
App 的准确定义是:
|
||||
|
||||
> **面向某类长程任务的状态化运行壳。**
|
||||
|
||||
它与 Skill 的区别在于:
|
||||
|
||||
- `skill` 解决“做什么”
|
||||
- `app` 解决“这类工作如何持续运行、展示、交互、留痕”
|
||||
|
||||
它与 Expert 的区别在于:
|
||||
|
||||
- `expert` 解决“谁在与你协作”
|
||||
- `app` 解决“这项工作在什么界面和状态机里被推进”
|
||||
|
||||
## 2.3 任务不再等于对话
|
||||
|
||||
平台后续的统一定义应为:
|
||||
|
||||
> **任务 = 一个工作实例容器**
|
||||
|
||||
这个容器里可以挂载:
|
||||
|
||||
- 一个主 `app`
|
||||
- 一个右栏 `expert`
|
||||
- 多个后台 `skill`
|
||||
- 若干 `connector`
|
||||
|
||||
因此:
|
||||
|
||||
- 对话是任务中的一种交互轨迹
|
||||
- 不是所有任务都必须以消息流作为主界面
|
||||
|
||||
## 2.4 长程APP是一级导航,但一级导航必须完整描述
|
||||
|
||||
`app` 升格后,不能只补一句“新增长程APP”,否则会把整个一级导航重新说乱。
|
||||
|
||||
一级导航不再是同质栏目,而应明确分成四类:
|
||||
|
||||
1. 工作入口
|
||||
2. 对象目录
|
||||
3. 组织知识入口
|
||||
4. 治理与个人入口
|
||||
|
||||
推荐的一级导航全景应为:
|
||||
|
||||
1. `新建任务`
|
||||
- 对话驱动任务的默认入口
|
||||
- 负责创建以 `expert` 为主对象的任务
|
||||
2. `项目`
|
||||
- 任务容器与聚合视图
|
||||
- 用于组织多个长程任务与对话任务
|
||||
3. `专家 · 技能 · 连接器`
|
||||
- 对象目录与配置浏览入口
|
||||
- 这里看的是定义,不是运行时
|
||||
4. `长程APP`
|
||||
- `app` 定义卡片入口
|
||||
- 这里展示的是可启动的长程 App,不是历史任务
|
||||
5. `知识库`
|
||||
- 组织级默认内建 App 的直达入口
|
||||
- 承载组织专有知识、素材、题库、结果记录等核心资产
|
||||
- 是 Expert 与 App 共同消费的知识底座
|
||||
6. `后台管理`
|
||||
- 工坊、系统配置、对象治理、权限治理
|
||||
- 是平台治理入口,不是业务运行入口
|
||||
7. `我的`
|
||||
- 个人总览、我的资料、个人偏好与个人工作视角
|
||||
|
||||
这里最重要的边界是:
|
||||
|
||||
- `专家 · 技能 · 连接器` 看的是对象定义与配置
|
||||
- `长程APP` 看的是可运行的 `app`
|
||||
- `项目` 看的是任务集合
|
||||
- `知识库` 看的是组织级知识底座与其内建 App 运行面
|
||||
|
||||
这里需要明确一个特例:
|
||||
|
||||
> **知识库本身也是 `app`,但它不是普通可选 App,而是组织级默认必须存在的内建 App。**
|
||||
|
||||
原因是:
|
||||
|
||||
- 平台服务的是单一组织而不是开放公域
|
||||
- 没有组织专有知识,很多 Expert 与 App 无法稳定运行
|
||||
- 知识库不仅提供资料查看,还承担沉淀、审批、引用、题库与知识资产治理
|
||||
|
||||
因此在产品层,知识库同时具有两种身份:
|
||||
|
||||
1. 在对象模型里,它属于 `app.knowledge_hub`
|
||||
2. 在一级导航里,它拥有保留的直达入口,不必埋进“长程APP”卡片列表
|
||||
|
||||
点击 `长程APP` 里的卡片后,标准动作应为:
|
||||
|
||||
1. 创建任务实例
|
||||
2. 挂载主 `app`
|
||||
3. 进入该 `app` 的运行界面
|
||||
4. 同时进入统一任务列表
|
||||
|
||||
当前像 `AI考试` 这种已经长出独立业务界面的主导航,在架构上应理解为**过渡态专题入口**。
|
||||
后续应逐步收敛为:
|
||||
|
||||
- `长程APP -> app.training_exam`
|
||||
|
||||
而不是继续长期作为与 `专家 / 技能 / 项目 / 知识库` 并列的专题型一级主栏目。
|
||||
|
||||
---
|
||||
|
||||
## 3. 三类一级对象的边界
|
||||
|
||||
## 3.1 Expert
|
||||
|
||||
`expert` 是面向用户协作的交互外壳。
|
||||
|
||||
核心职责:
|
||||
|
||||
- 理解意图
|
||||
- 引导开场
|
||||
- 陪伴推进
|
||||
- 解释状态
|
||||
- 调度技能
|
||||
|
||||
典型交互:
|
||||
|
||||
- 对话主导
|
||||
- 欢迎语
|
||||
- starter prompts
|
||||
- 右栏 AI 助手
|
||||
|
||||
## 3.2 Skill
|
||||
|
||||
`skill` 是面向任务复用的能力包。
|
||||
|
||||
核心职责:
|
||||
|
||||
- 封装某类能力
|
||||
- 编排 `action`
|
||||
- 规范输入输出
|
||||
- 生成产物
|
||||
|
||||
典型交互:
|
||||
|
||||
- 被角色调用
|
||||
- 被 App 调用
|
||||
- 被工作流调用
|
||||
|
||||
## 3.3 App
|
||||
|
||||
`app` 是面向场景化长程任务或组织级运行面的运行壳。
|
||||
|
||||
核心职责:
|
||||
|
||||
- 承载主界面
|
||||
- 驱动状态机
|
||||
- 管理结构化数据
|
||||
- 组织多步骤交互
|
||||
- 沉淀长程产物
|
||||
|
||||
典型交互:
|
||||
|
||||
- 菜单
|
||||
- 表单
|
||||
- 按钮
|
||||
- 题卡
|
||||
- 看板
|
||||
- 画布
|
||||
|
||||
其中应区分两类 App:
|
||||
|
||||
1. **任务型 App**
|
||||
- 进入后通常创建 `app_task`
|
||||
- 例如培训考试、审批、数据分析、流程编排
|
||||
2. **底座型 App**
|
||||
- 组织级长期存在,默认安装
|
||||
- 例如知识库
|
||||
- 它既提供独立运行面,也为其他任务提供知识支撑
|
||||
|
||||
AI 在 App 中通常位于:
|
||||
|
||||
- 右栏副驾驶位
|
||||
- 辅助填表
|
||||
- 规则解释
|
||||
- 状态总结
|
||||
- 自然语言触发复杂动作
|
||||
|
||||
---
|
||||
|
||||
## 4. 六层架构回溯后的新定义
|
||||
|
||||
## 4.1 第一层:外部连接层
|
||||
|
||||
这一层继续负责连接真实世界与外部系统。
|
||||
|
||||
包括:
|
||||
|
||||
- 本地文件系统
|
||||
- 企业业务系统
|
||||
- 工业系统
|
||||
- 培训 / 考试 / OA / ERP / MES / CRM / LMS
|
||||
- 模型服务
|
||||
- API / Webhook / MQ
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**数据从哪里来,动作往哪里去。**
|
||||
|
||||
## 4.2 第二层:本体与语义上下文层
|
||||
|
||||
这一层需要从行业对象语义继续扩展到工作对象语义。
|
||||
|
||||
除了原有:
|
||||
|
||||
- device
|
||||
- alarm
|
||||
- work_order
|
||||
- report
|
||||
|
||||
还应补充:
|
||||
|
||||
- task
|
||||
- stage
|
||||
- expert
|
||||
- skill
|
||||
- app
|
||||
- artifact
|
||||
- form
|
||||
- workflow
|
||||
- record
|
||||
|
||||
对于 `app`,这一层必须支持:
|
||||
|
||||
- App 处理的业务对象类型
|
||||
- App 允许的阶段类型
|
||||
- App 产物类型
|
||||
- App 与 Expert / Skill 的可挂载关系
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**平台到底在处理哪些业务对象、工作对象和它们之间的关系。**
|
||||
|
||||
## 4.3 第三层:总线与编排层
|
||||
|
||||
这一层继续承担流转职责,但要正式接纳 `app` 作为任务主对象。
|
||||
|
||||
至少应包含:
|
||||
|
||||
1. 任务总线
|
||||
2. 事件总线
|
||||
3. 对象挂载总线
|
||||
4. 能力编排总线
|
||||
|
||||
新职责包括:
|
||||
|
||||
- 任务创建后挂载主 `app`
|
||||
- 根据 `app` 状态切换工作台界面
|
||||
- 允许右栏 `expert` 感知当前 `app` 上下文
|
||||
- 允许 `app` 调度 `skill`
|
||||
- 允许人工接管与审批节点插入
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**任务如何创建,对象如何挂载,状态如何推进,能力如何协作。**
|
||||
|
||||
## 4.4 第四层:能力层
|
||||
|
||||
这一层继续保持:
|
||||
|
||||
- `skill`
|
||||
- `action`
|
||||
- `policy`
|
||||
|
||||
但要明确一个边界:
|
||||
|
||||
> **App 不进入能力层。**
|
||||
|
||||
原因是:
|
||||
|
||||
- `skill` 是能力包
|
||||
- `action` 是原子动作
|
||||
- `app` 是运行壳
|
||||
|
||||
App 可以调用 Skill,但不替代 Skill。
|
||||
|
||||
## 4.5 第五层:对象层
|
||||
|
||||
这一层正式收敛为:
|
||||
|
||||
- `expert`
|
||||
- `skill`
|
||||
- `app`
|
||||
|
||||
并且三者都应该具备:
|
||||
|
||||
- 对象定义
|
||||
- 版本信息
|
||||
- 生命周期状态
|
||||
- 权限边界
|
||||
- 可挂载关系
|
||||
|
||||
这一层回答的是:
|
||||
|
||||
**平台有哪些可被用户使用、可被任务挂载、可被版本化治理的一等对象。**
|
||||
|
||||
## 4.6 第六层:工作台与运行治理层
|
||||
|
||||
这一层不再只有单一对话工作台,而应明确分成两类运行现场:
|
||||
|
||||
### A. 对话工作台
|
||||
|
||||
- 以专家为主
|
||||
- 适合模糊任务、探索任务、咨询任务
|
||||
- 中央区域以消息流为主
|
||||
|
||||
### B. 长程APP
|
||||
|
||||
- 以 App 为主
|
||||
- 适合强状态、强结构、长周期任务
|
||||
- 中央区域以业务界面为主
|
||||
- AI 位于右栏
|
||||
|
||||
两者统一纳入:
|
||||
|
||||
- 同一任务列表
|
||||
- 同一运行治理体系
|
||||
- 同一审计和产物体系
|
||||
|
||||
---
|
||||
|
||||
## 5. 统一任务模型
|
||||
|
||||
## 5.1 任务是工作实例容器
|
||||
|
||||
新的任务定义应为:
|
||||
|
||||
> **task = 一次完整工作实例**
|
||||
|
||||
它负责统一承载:
|
||||
|
||||
- 当前主对象
|
||||
- 当前阶段
|
||||
- 当前参与对象
|
||||
- 当前运行状态
|
||||
- 当前产物集合
|
||||
|
||||
## 5.2 一个任务可挂多个对象实例
|
||||
|
||||
建议使用如下运行模型:
|
||||
|
||||
- 主挂载:`app` 或 `expert`
|
||||
- 右栏挂载:`expert`
|
||||
- 后台挂载:`skill`
|
||||
|
||||
例如一个培训考试任务可以是:
|
||||
|
||||
- 主对象:`app.training_exam`
|
||||
- 右栏对象:`expert.learning_coach`
|
||||
- 后台能力:`skill.auto_grading`
|
||||
- 后台能力:`skill.study_plan_generation`
|
||||
|
||||
## 5.3 会话只是任务的一部分
|
||||
|
||||
以后应避免继续把任务状态写死在消息流里。
|
||||
|
||||
更准确的关系是:
|
||||
|
||||
- `task`:工作容器
|
||||
- `task_message`:对话轨迹
|
||||
- `app_state`:App 主状态
|
||||
- `artifact`:产物
|
||||
- `event`:运行轨迹
|
||||
|
||||
---
|
||||
|
||||
## 6. 存储架构建议
|
||||
|
||||
## 6.1 对象定义层
|
||||
|
||||
建议继续使用统一根定义:
|
||||
|
||||
- `object_definition`
|
||||
- `object_version`
|
||||
|
||||
关键字段建议:
|
||||
|
||||
- `object_id`
|
||||
- `object_type`:`expert | skill | app`
|
||||
- `code`
|
||||
- `key`
|
||||
- `label`
|
||||
- `status`
|
||||
- `manifest`
|
||||
- `schema_version`
|
||||
|
||||
其中 `app.manifest` 至少应包含:
|
||||
|
||||
- `object_entry_route`
|
||||
- `layout_type`
|
||||
- `supported_views`
|
||||
- `default_sidebar_expert`
|
||||
- `allowed_skills`
|
||||
- `state_schema`
|
||||
- `artifact_schema`
|
||||
- `permission_model`
|
||||
|
||||
为避免与 AI 路由和普通页面导航混同,当前项目统一采用三类命名:
|
||||
|
||||
- `ai_route_*`:AI 模型路由
|
||||
- `object_entry_route`:专家 / 技能 / APP 这类业务对象的进入入口
|
||||
- `page_route`:普通页面导航路径
|
||||
|
||||
## 6.2 任务与挂载层
|
||||
|
||||
建议新增或统一为:
|
||||
|
||||
- `task`
|
||||
- `task_object_instance`
|
||||
|
||||
`task` 核心字段建议:
|
||||
|
||||
- `task_id`
|
||||
- `task_type`:`conversation_task | app_task`
|
||||
- `title`
|
||||
- `status`
|
||||
- `source_object_type`
|
||||
- `source_object_id`
|
||||
- `current_stage`
|
||||
- `started_at`
|
||||
- `completed_at`
|
||||
|
||||
`task_object_instance` 核心字段建议:
|
||||
|
||||
- `task_object_instance_id`
|
||||
- `task_id`
|
||||
- `object_id`
|
||||
- `object_version_id`
|
||||
- `object_type`
|
||||
- `mount_slot`:`main | right_sidebar | background`
|
||||
- `instance_role`:`primary | assistant | worker`
|
||||
|
||||
## 6.3 运行轨迹层
|
||||
|
||||
建议使用:
|
||||
|
||||
- `object_run`
|
||||
- `task_message`
|
||||
|
||||
其中:
|
||||
|
||||
- `object_run` 记录对象执行、阶段推进、技能调用、人工确认
|
||||
- `task_message` 仅记录对话内容和消息元数据
|
||||
|
||||
需要明确:
|
||||
|
||||
> **`task_message` 不再承担 App 主状态存储责任。**
|
||||
|
||||
## 6.4 App 状态层
|
||||
|
||||
建议为 `app` 单独引入运行时状态存储:
|
||||
|
||||
- `app_instance_state`
|
||||
- `app_event`
|
||||
- `app_artifact`
|
||||
|
||||
`app_instance_state` 建议存:
|
||||
|
||||
- `task_id`
|
||||
- `task_object_instance_id`
|
||||
- `workflow_state`
|
||||
- `ui_state`
|
||||
- `form_state`
|
||||
- `selected_record_id`
|
||||
- `snapshot_version`
|
||||
|
||||
`app_event` 建议存:
|
||||
|
||||
- `event_type`
|
||||
- `payload`
|
||||
- `operator`
|
||||
- `created_at`
|
||||
|
||||
`app_artifact` 建议存:
|
||||
|
||||
- `artifact_type`
|
||||
- `artifact_uri`
|
||||
- `artifact_meta`
|
||||
- `produced_by`
|
||||
- `created_at`
|
||||
|
||||
## 6.5 领域数据层
|
||||
|
||||
对于复杂 App,不应把所有业务数据都塞进 `app_instance_state.payload_json`。
|
||||
|
||||
必须允许按领域建模。
|
||||
|
||||
例如培训考试 App 可拥有独立领域表:
|
||||
|
||||
- `training_plan`
|
||||
- `course_module`
|
||||
- `exam_paper`
|
||||
- `exam_question`
|
||||
- `exam_attempt`
|
||||
- `exam_answer`
|
||||
- `exam_score`
|
||||
|
||||
因此存储应分为:
|
||||
|
||||
- 通用运行表:承载平台运行
|
||||
- 领域业务表:承载业务事实
|
||||
|
||||
---
|
||||
|
||||
## 7. 前端与交互层含义
|
||||
|
||||
## 7.1 一级导航升级
|
||||
|
||||
前端一级导航不能只补“长程APP”这一项,而应整体升级为完整的信息架构。
|
||||
|
||||
建议目标态如下:
|
||||
|
||||
1. `新建任务`
|
||||
- 默认进入对话工作台
|
||||
- 主对象通常为 `expert`
|
||||
2. `项目`
|
||||
- 承载项目列表与项目详情
|
||||
- 用于聚合任务、产物与阶段
|
||||
3. `专家 · 技能 · 连接器`
|
||||
- 展示 `expert / skill / connector` 的定义目录
|
||||
- 负责浏览、筛选、配置、安装态查看
|
||||
4. `长程APP`
|
||||
- 展示 `app` 定义卡片
|
||||
- 负责启动 `app_task`
|
||||
5. `知识库`
|
||||
- 作为默认必须存在的内建 App 直接出现在一级导航
|
||||
- 承载组织知识、素材、题库、记录与知识治理
|
||||
- 是任务运行的公共知识面
|
||||
6. `后台管理`
|
||||
- 承载工坊、系统配置、组织与治理能力
|
||||
7. `我的`
|
||||
- 承载个人总览、个人资料与个人入口
|
||||
|
||||
因此,一级导航里实际并存四种不同语义:
|
||||
|
||||
- 工作启动入口:`新建任务`
|
||||
- 工作组织入口:`项目`
|
||||
- 对象目录入口:`专家 · 技能 · 连接器`、`长程APP`
|
||||
- 组织知识与治理入口:`知识库`、`后台管理`、`我的`
|
||||
|
||||
### 7.1.1 为什么必须这样写全
|
||||
|
||||
如果只写:
|
||||
|
||||
- 专家
|
||||
- 技能
|
||||
- 长程APP
|
||||
|
||||
会遗漏三件事:
|
||||
|
||||
1. `项目` 其实是统一任务系统的重要容器,不是普通页面
|
||||
2. `知识库` 是组织级默认内建 App,也是 Expert 和 App 的共用知识底座,不是边角内容
|
||||
3. `后台管理 / 我的` 分别承担治理与个人视角,不应被误解为附属页
|
||||
|
||||
### 7.1.2 当前专题主导航的收敛原则
|
||||
|
||||
凡是已经长成“非对话式、强结构、强状态”的专题栏目,例如:
|
||||
|
||||
- 培训考试
|
||||
- 审批中心
|
||||
- 数据分析台
|
||||
- 流程编排台
|
||||
|
||||
在目标架构中都应优先判断为 `app`,最终收敛进:
|
||||
|
||||
- `长程APP`
|
||||
|
||||
而不是继续无限增长新的专题型一级导航。
|
||||
|
||||
唯一应保留一级直达入口的 App,是像 `知识库` 这种**组织级默认必装底座 App**。
|
||||
|
||||
## 7.2 进入 App 的动作不是“打开页面”,而是“创建任务”
|
||||
|
||||
点击 App 卡片后的标准动作应为:
|
||||
|
||||
1. 创建 `task`
|
||||
2. 创建主 `task_object_instance(app)`
|
||||
3. 自动挂载右栏 `expert`
|
||||
4. 进入 `app runtime`
|
||||
|
||||
## 7.3 App 运行界面不再强制对话居中
|
||||
|
||||
App 主界面应由业务形态决定,例如:
|
||||
|
||||
- 培训考试:课程目录、题卡、成绩面板
|
||||
- 审批:表单、节点、操作栏
|
||||
- 数据分析:图表、筛选器、表格
|
||||
- 流程编排:画布、节点、日志
|
||||
|
||||
AI 对话框在 App 中退居右栏能力区。
|
||||
|
||||
---
|
||||
|
||||
## 8. 样板场景:培训考试 App
|
||||
|
||||
## 8.1 对象组合
|
||||
|
||||
- 主对象:`app.training_exam`
|
||||
- 右栏对象:`expert.learning_coach`
|
||||
- 调用技能:`skill.generate_study_plan`
|
||||
- 调用技能:`skill.auto_grade_exam`
|
||||
|
||||
## 8.2 任务阶段
|
||||
|
||||
建议阶段至少包括:
|
||||
|
||||
1. 待建档
|
||||
2. 培训中
|
||||
3. 练习中
|
||||
4. 待模拟考
|
||||
5. 模拟考完成
|
||||
6. 待正式考试
|
||||
7. 正式考试中
|
||||
8. 待复盘
|
||||
9. 待补训
|
||||
10. 已结业
|
||||
|
||||
## 8.3 交互形态
|
||||
|
||||
- 培训中:课程目录 + 内容区 + 右栏 AI 教练
|
||||
- 练习中:题目区 + 即时讲解
|
||||
- 正式考试中:题卡 + 倒计时 + 受控作答区
|
||||
- 复盘中:错题分析 + 补训计划 + 证书面板
|
||||
|
||||
这个样板说明:
|
||||
|
||||
> **同一个任务实例中,对话、结构化界面、技能执行、产物沉淀可以长期共存。**
|
||||
|
||||
---
|
||||
|
||||
## 9. 迁移指导
|
||||
|
||||
## 9.1 术语迁移
|
||||
|
||||
对外:
|
||||
|
||||
- 专家
|
||||
- 技能
|
||||
- 长程APP
|
||||
|
||||
一级导航目标态:
|
||||
|
||||
- 新建任务
|
||||
- 项目
|
||||
- 专家 · 技能 · 连接器
|
||||
- 长程APP
|
||||
- 知识库
|
||||
- 后台管理
|
||||
- 我的
|
||||
|
||||
对内:
|
||||
|
||||
- `expert`
|
||||
- `skill`
|
||||
- `app`
|
||||
- `action`
|
||||
- `connector`
|
||||
- `policy`
|
||||
|
||||
## 9.2 后端迁移重点
|
||||
|
||||
1. 从“任务 = 对话”迁移到“任务 = 工作实例”
|
||||
2. 新增 `app` 对象定义与版本机制
|
||||
3. 新增 `task_object_instance`
|
||||
4. 新增 `app_state / app_event / app_artifact`
|
||||
5. 把消息表从主状态中心降级为对话轨迹层
|
||||
|
||||
## 9.3 前端迁移重点
|
||||
|
||||
1. 把一级导航整理为“新建任务 / 项目 / 专家 · 技能 · 连接器 / 长程APP / 知识库 / 后台管理 / 我的”
|
||||
2. 新增“长程APP”并以对象定义驱动 App 卡片列表与详情页
|
||||
3. 将现有专题型一级导航逐步收敛为 `app`,避免继续平铺新的业务主栏目;`知识库` 作为默认必装底座 App 保留一级直达入口
|
||||
4. 统一任务列表兼容 `conversation_task` 和 `app_task`
|
||||
5. App Runtime 布局支持“主业务区 + 右栏 AI”
|
||||
|
||||
---
|
||||
|
||||
## 10. 最终定义
|
||||
|
||||
这次架构升级后的平台可以正式定义为:
|
||||
|
||||
> **一个以统一任务系统为核心、同时承载 Expert / Skill / App 三类一级对象的工业智能体操作平台。**
|
||||
|
||||
其中:
|
||||
|
||||
- `Expert` 负责协作
|
||||
- `Skill` 负责能力
|
||||
- `App` 负责长程任务运行壳
|
||||
- `Task` 负责统一承载工作实例
|
||||
|
||||
这意味着平台已经不再是单一对话驱动系统,而是:
|
||||
|
||||
> **对话工作台与长程APP并存,但统一运行、统一治理、统一沉淀。**
|
||||
@@ -0,0 +1,381 @@
|
||||
# SY23 — 专员「岗位说明书 + 技能绑定」改造方案
|
||||
|
||||
> 状态:实施建议稿
|
||||
> 日期:2026-09-17
|
||||
> 关联文档:`SY18_Specialist_Minimal_Definition_Model.md`、`SY20_Role_Card_And_Lightweight_Ontology_Architecture.md`、`SY21_Unified_Role_Skill_Action_Architecture.md`、`SY22_Role_Skill_App_Unified_Task_Architecture.md`
|
||||
> 外部参照:AionUi / AionCore 内置助手与技能(已下载至 `codebase/AionCore-assets/`)
|
||||
|
||||
---
|
||||
|
||||
## 0. 一句话诊断
|
||||
|
||||
**我们现在的 10 个专员,在运行时是同一个助手换了 10 个名字。**
|
||||
|
||||
工作台主对话走 `POST /api/assistant/chat`(前端 `api/assistant.js` → `chatWithAssistant`),而这个接口:
|
||||
|
||||
| 环节 | 现状 | 位置 |
|
||||
|------|------|------|
|
||||
| 前端发送的字段 | 只有 `message` / `mode` / `ai_route_id` | `views/workbench/SmartAssistantPage.vue:471` |
|
||||
| 后端请求体 | **已有** `task_id` / `context` 字段,但前端一个都没发 | `internal/api/smart_assistant.go:17-25` |
|
||||
| 后端 System Prompt | **两条写死的字符串**,与专员无关 | `internal/api/smart_assistant.go:136-140` |
|
||||
| 后端是否查过 specialist 表 | **从未** | `callAssistantAI` 全文 26 行 |
|
||||
| 「专家模式」任务拆解 | **三条写死的假步骤**(准备/执行/完成阶段) | `internal/api/smart_assistant.go:161-174` |
|
||||
| 知识检索 | 这条链路完全不检索知识库 | 对比 `worker_task.go:707` |
|
||||
|
||||
也就是说:**不管用户选了「合同审查专员」还是「物流履约专员」,后端收到的请求完全一样,产出的 System Prompt 完全一样。** 专员是在前端画出来的差异,不是后端跑出来的差异。
|
||||
|
||||
这与 SY21 §3.5.2 已经拍板的关系式直接冲突:
|
||||
|
||||
> 专家承接用户,skill 组织任务,action 执行动作。
|
||||
|
||||
我们目前**只做了「专家承接用户」(前端 UI),缺了「专家暴露 skill」和「skill 编排 action」两条边**。
|
||||
|
||||
---
|
||||
|
||||
## 1. AionUi 做对了什么(三件事)
|
||||
|
||||
AionCore 的 `builtin-assistants/assistants.json` 里,每个助手就三个关键字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "word-creator",
|
||||
"rule_file": "word-creator.{locale}.md",
|
||||
"enabled_skills": ["officecli-docx"]
|
||||
}
|
||||
```
|
||||
|
||||
拆开看:
|
||||
|
||||
**① 每个助手有一份「岗位说明书」(rule file)**
|
||||
- 就是这个助手的 System Prompt 主体,会话创建时注入
|
||||
- 简体中文版共 21 份,长度分布很说明问题:
|
||||
- 办公类 9 份在 **433–650 字**(如 `word-creator.zh-CN.md` 517 字)
|
||||
- 编排类 9 份在 **2470–9007 字**(如 `cowork.zh-CN.md` 6705 字)
|
||||
- **短的那批不是偷懒,是分工**:它们把「怎么做」全部委托给技能,说明书本身只负责「我是谁 / 什么时候说什么 / 什么时候用哪个技能」
|
||||
|
||||
`word-creator.zh-CN.md` 全文的结构(517 字):
|
||||
|
||||
```markdown
|
||||
# Word 文档助手
|
||||
你是 **Word Creator** —— 一个专门使用 officecli 创建、编辑和分析专业 Word 文档的 AI 助手。
|
||||
## 当用户打招呼或询问你能做什么时
|
||||
简短介绍自己:[一段自我介绍的原文]
|
||||
然后等待用户请求。
|
||||
## 当用户想要创建或编辑文档时
|
||||
严格按照 `officecli-docx` 技能执行。……不要偏离或简化技能中的指令。
|
||||
在开始工作前,主动提醒用户一次:[一段提醒原文]
|
||||
在生成完成后,明确告诉用户:[一段收尾原文]
|
||||
```
|
||||
|
||||
**② 每个助手声明它能用哪些技能(`enabled_skills`)**
|
||||
- 技能以目录形式链接进工作区,底层 CLI 通过 `native_skills_dirs` 发现
|
||||
- 21 个助手里 13 个只绑 1 个技能,`cowork` 绑 5 个,`game-3d` / `ui-ux-pro-max` / `planning-with-files` / `human-3-coach` 绑 0 个
|
||||
- **绑 0 个技能但有 4000+ 字说明书的,恰恰是最像「专员」的那几个**(纯靠说明书驱动行为,不靠工具)
|
||||
|
||||
**③ 说明书负责「调度」,技能负责「执行」**
|
||||
- 长说明书(`cowork` 6705 字)的核心内容就是「什么场景下按哪个技能走」——这正是 SY20 说的「专员 = 可调用工具的角色」
|
||||
- `cowork` 是 21 个助手里唯一的多技能编排样板,**也是我们最该先抄的一份**
|
||||
|
||||
### 结论
|
||||
|
||||
SY18 + SY20 + AionUi 三边指向同一件缺失的事:
|
||||
|
||||
```
|
||||
SY18 说:专员有「动作」 ─┐
|
||||
SY20 说:专员 = 可调用工具的角色 ─┼─→ 专员和技能之间没有绑定边
|
||||
SY21 说:专家对象暴露 skill ─┤ 专员没有一份进 prompt 的说明书
|
||||
AionUi 说:rule_file + enabled_skills ─┘
|
||||
```
|
||||
|
||||
**我们已经有的(没用的)**:`specialist.role_card_json` 字段建了、值也写了,但从未进过任何 prompt。
|
||||
**我们缺的**:不是字段,是**把字段送进 prompt 的那条线**,和**专员↔技能的绑定边**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 改造方案
|
||||
|
||||
三步,从「运行时能看出差异」倒推,不铺新架构。
|
||||
|
||||
### 步骤 1:给专员两样东西(数据层,改动最小)
|
||||
|
||||
在 `internal/model/specialist.go` 加两个字段:
|
||||
|
||||
```go
|
||||
// RuleFileMarkdown 岗位说明书正文(Markdown 全文)。
|
||||
// 会话创建时注入 System Prompt,决定这个专员怎么说话、怎么推进、什么时候调用哪个技能。
|
||||
RuleFileMarkdown string `gorm:"type:text" json:"rule_file_markdown"`
|
||||
|
||||
// AllowedSkills 绑定技能 key 列表,JSON 数组,顺序即优先级(首个为主技能)。
|
||||
// 元素取值对齐前端 availableSkills[].key,见 §2.4 校验清单。
|
||||
AllowedSkills string `gorm:"type:text" json:"allowed_skills"`
|
||||
```
|
||||
|
||||
**为什么是两个字段而不是两张表**
|
||||
|
||||
| 选择 | 理由 |
|
||||
|------|------|
|
||||
| 说明书用单字段 | AionUi 也是「一个助手一份 rule file」,不引入版本表 |
|
||||
| 技能绑定用 JSON 数组 | SY22 §6.1 已把 `allowed_skills` 定为对象 `manifest` 的字段。现在用同名字段落地,**将来迁到 `object_definition` 时只是把列搬进 manifest,没有语义返工** |
|
||||
| 不新建 `specialist_skill` 表 | 10 个专员 × 3–5 个技能 ≈ 40 行。表能提供的索引和 FK,在这里都不成立——15 个前端技能在后端根本没有行,FK 建不起来。数组顺序天然表达优先级,无需 `sort_order` 列 |
|
||||
|
||||
> 升级路径(不在本轮):若将来技能绑定要挂**属性**(按技能配参数默认值、按技能配权限档位),再拆成关联表;那时 `allowed_skills` 里的元素从字符串升级为对象,字段名不变。
|
||||
|
||||
**迁移**:GORM `AutoMigrate` 会自动 `ADD COLUMN`,**不需要**手写迁移函数。
|
||||
(`internal/store/db.go:83` 的 `migrateObjectEntryRouteColumns` 是为 `DROP COLUMN` 写的——SQLite 的 AutoMigrate 删不掉列,加列不在此列。)
|
||||
|
||||
**播种**:在 `internal/store/seed.go` 的 `seedSpecialists()` 之后加 `seedSpecialistRules()`,遵守现有「存在则只补空字段」约定——**说明书非空就不覆盖**,保护人工编辑。
|
||||
|
||||
### 步骤 2:让对话带上专员(打通链路)
|
||||
|
||||
这是**当前最大的断点**,也是投入产出比最高的一处。改动共 4 个文件、约 30 行。
|
||||
|
||||
**前端(3 处)**
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `frontend/src/api/assistant.js` | `chatWithAssistant(data)` 已透传整个 data,无需改 |
|
||||
| `frontend/src/store/workerRuntime.js` | 已有 `currentSpecialistKey` computed(185-192 行),直接用 |
|
||||
| `frontend/src/views/workbench/SmartAssistantPage.vue:471` | 请求体补上 `task_id` 与 `specialist_key` |
|
||||
|
||||
```js
|
||||
const res = await chatWithAssistant({
|
||||
message: text,
|
||||
mode: mode.value,
|
||||
ai_route_id: selectedAiChatRouteId.value,
|
||||
task_id: currentTaskId.value || 0,
|
||||
specialist_key: workerRuntime.currentSpecialistKey || '',
|
||||
})
|
||||
```
|
||||
|
||||
> 两个都发是刻意的:**有任务时以 `task_id` 为准**(服务端从 `worker_task.specialist_key` 反查,不信任客户端);**任务尚未创建时**(刚进 `/home` 还没发第一句话)前端手上只有 `pendingSpecialistKey`,此时用 `specialist_key` 兜底。
|
||||
|
||||
**后端(1 处)**
|
||||
|
||||
`internal/api/smart_assistant.go` 的 `callAssistantAI` 增加专员解析:
|
||||
|
||||
```go
|
||||
// 解析当前专员:优先按 task_id 反查(服务端权威),其次用请求里的 specialist_key
|
||||
func resolveSpecialist(userID uint, req SmartAssistantRequest) *model.Specialist {
|
||||
if req.TaskID > 0 {
|
||||
var task model.WorkerTask
|
||||
if err := store.DB.Where("id = ? AND user_id = ?", req.TaskID, userID).
|
||||
First(&task).Error; err == nil && task.SpecialistKey != "" {
|
||||
var s model.Specialist
|
||||
if err := store.DB.Where("key = ?", task.SpecialistKey).First(&s).Error; err == nil {
|
||||
return &s
|
||||
}
|
||||
}
|
||||
}
|
||||
if req.SpecialistKey != "" {
|
||||
var s model.Specialist
|
||||
if err := store.DB.Where("key = ?", req.SpecialistKey).First(&s).Error; err == nil {
|
||||
return &s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
> 现成的反查先例:`internal/api/worker_task.go:364` 就是同一套 `store.DB.Where("key = ?", task.SpecialistKey).First(&specialist)`。
|
||||
|
||||
`SmartAssistantRequest` 需补一个字段(`TaskID` 已存在,只差 `SpecialistKey`):
|
||||
|
||||
```go
|
||||
SpecialistKey string `json:"specialist_key"`
|
||||
```
|
||||
|
||||
### 步骤 3:让说明书进 prompt(注入)
|
||||
|
||||
改造 `callAssistantAI` 的 System Prompt 拼装,从「二选一写死」变成「通用底座 + 专员说明书」:
|
||||
|
||||
```go
|
||||
func buildAssistantSystemPrompt(userID uint, req SmartAssistantRequest, enableThinking bool) string {
|
||||
base := "你是一位专业的AI通用助手,回答简洁直接,不展开思考过程,快速响应用户问题。"
|
||||
if enableThinking {
|
||||
base = "你是一位专家级AI数字员工,使用 thinking 模式。……"
|
||||
}
|
||||
|
||||
s := resolveSpecialist(userID, req)
|
||||
if s == nil {
|
||||
return base // 未挂专员 → 通用助手兜底,行为与今天一致
|
||||
}
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString(base)
|
||||
b.WriteString("\n\n【当前专员】")
|
||||
b.WriteString(s.Label)
|
||||
|
||||
if skills := parseAllowedSkills(s.AllowedSkills); len(skills) > 0 {
|
||||
b.WriteString("\n【可用技能】")
|
||||
b.WriteString(strings.Join(skills, "、"))
|
||||
}
|
||||
|
||||
// 说明书是主体,放最后,避免被前面的短句稀释
|
||||
if strings.TrimSpace(s.RuleFileMarkdown) != "" {
|
||||
b.WriteString("\n\n")
|
||||
b.WriteString(s.RuleFileMarkdown)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
```
|
||||
|
||||
**同时接上第二条链路**:`internal/api/worker_task.go:708` 已经在拼 System Prompt 且**手上就有 specialist 对象**,把说明书一起拼进去即可——这条链路是免费的,因为它本来就认识专员。
|
||||
|
||||
```go
|
||||
systemPrompt := buildSystemPrompt(contextJSON, knowledge) +
|
||||
specialistPromptSection(specialist) + // ← 新增
|
||||
"\n\n当前任务:" + buildWorkerAITaskPrompt(task, specialist, req)
|
||||
```
|
||||
|
||||
> `specialistPromptSection(s)` 抽成一个共用小函数,`smart_assistant.go` 和 `worker_task.go` 都调它,避免两处 prompt 拼法各写一遍。
|
||||
|
||||
### §2.4 技能 key 校验清单
|
||||
|
||||
绑定的是裸字符串,所以需要一个校验来源。**新增单个 Go 常量文件**即可(22 条,从 `frontend/src/config/workbench.js` 的 `availableSkills` 一次性抄出):
|
||||
|
||||
```go
|
||||
// internal/model/skill_keys.go
|
||||
// 前端 availableSkills 的 key 全集。绑定校验以此为准。
|
||||
// 注意:这里只列 key,不含技能实现——技能实现仍在前端。
|
||||
var ValidSkillKeys = map[string]bool{
|
||||
"smart-assistant": true, "document-translate": true, "copy-proofreading": true,
|
||||
"audio-transcribe": true, "batch-extract": true, "contract-review": true,
|
||||
"report-generation": true, "ppt-generation": true, "mind-map": true,
|
||||
"longform-writing": true, "text-toolkit": true, "ocr-understanding": true,
|
||||
"meeting-minutes": true, "project-planning": true, "email-drafting": true,
|
||||
"table-cleanup": true, "proposal-summary": true, "progress-report": true,
|
||||
"contract-brief": true, "interview-summary": true, "policy-rewrite": true,
|
||||
"survey-summary": true,
|
||||
}
|
||||
```
|
||||
|
||||
写入时校验,非法 key 直接 400 —— 这样至少在录入侧挡住拼写错误。
|
||||
|
||||
> **命名冲突提醒**:`contract-review` 和 `report-generation` **既是专员 key 又是技能 key**。
|
||||
> 这是对的、也是刻意的(合同审查专员绑定合同审查技能),但读日志和调代码时极易混淆。建议**日志与报错文案一律写成 `专员:contract-review` / `技能:contract-review`** 带类型前缀。
|
||||
|
||||
---
|
||||
|
||||
## 3. 21 份规则文件,先改写哪几份
|
||||
|
||||
全部 21 份已下载在 `codebase/AionCore-assets/crates/aionui-app/assets/builtin-assistants/rules/`。
|
||||
|
||||
### 第一梯队:直接改写就能用(建议本轮做)
|
||||
|
||||
| # | AionUi 来源 | 字数 | 对应我们的专员 | 为什么先做 |
|
||||
|---|-------------|------|----------------|------------|
|
||||
| 1 | `cowork` + 5 技能 | 6705 | `general-assistant`、`process-coordination` | **21 份里唯一的多技能编排样板**。它的说明书通篇在写「什么场景按哪个技能走」——这正是 SY20「专员 = 可调用工具的角色」要的东西。我们的「通用助手 / 流程协调」现在完全是空壳 |
|
||||
| 2 | `word-creator` + `officecli-docx` | 517 | `report-generation`、`solution-proposal` | 说明书只有 517 字,是**最简模板**,改造成本最低;`officecli-docx` 是文档产出的通用底座,一份技能喂两个专员 |
|
||||
| 3 | `morph-ppt` + `officecli-pptx` | 554 | `training-delivery` | 培训交付要出课件,morph-ppt 专做「文档转 PPT」,另有 3D 变体。我们「培训交付」目前零后端实现,接上就是真能力 |
|
||||
|
||||
### 第二梯队:要改业务语义(本轮之后)
|
||||
|
||||
| # | AionUi 来源 | 字数 | 对应我们的专员 | 改造要点 |
|
||||
|---|-------------|------|----------------|----------|
|
||||
| 4 | `social-job-publisher` | 2470 | `hr-email-sorter`、`resume-processor` | 招聘发布场景接近,但从「发帖到社媒」改成「读邮箱 → 写简历表」,需按 SY18 的信源/结果模型重写 |
|
||||
| 5 | `planning-with-files` | 5500 | `process-coordination` | 纯说明书(绑 0 技能),讲「用文件做长期规划」,接近流程协调 |
|
||||
| 6 | `beautiful-mermaid` | 433 | `report-generation` | 图表产出,可作报告生成的第二个技能 |
|
||||
| 7 | `excel-creator` + `officecli-xlsx` | 562 | `report-generation` | 表格产出 |
|
||||
| 8 | `dashboard-creator`、`financial-model-creator`、`pitch-deck-creator`、`academic-paper` | 567–614 | `solution-proposal` | 方案建议的几种形态,按客户行业挑 |
|
||||
|
||||
### 不要碰
|
||||
|
||||
| 来源 | 原因 |
|
||||
|------|------|
|
||||
| **`builtin-skills/pdf/`** | **© 2025 Anthropic, PBC,附加条款明文禁止创建衍生作品、禁止在服务外保留副本、禁止再分发。必须删除,不得移植进产品。** |
|
||||
| `openclaw-setup`、`aionui-assistant`、`aionui-*` 技能 | AionUi 自身的安装运维助手,与业务无关 |
|
||||
| `moltbook` | 面向其自有平台的发布助手 |
|
||||
| `game-3d`、`story-roleplay`、`human-3-coach`、`ui-ux-pro-max` | 游戏 / 角色扮演 / 个人成长 / 设计工具,与企业办公无关 |
|
||||
| `weixin-file-send` | 是「把文件发到微信」的客户端脚本,依赖其本地 Electron 环境,不可移植(公众号专员要的是发文,不是发文件) |
|
||||
|
||||
### 前置依赖:OfficeCLI 未下载
|
||||
|
||||
7 个 `officecli-*` 技能全部依赖 **OfficeCLI**(AionUi 用它免装 Office 操作 docx/xlsx/pptx)。**我们目前没有这份资产**,第一梯队第 2、3 项开工前必须先搞定它,否则说明书改完也没东西可调。
|
||||
|
||||
---
|
||||
|
||||
## 4. 前端要动的地方(最小集)
|
||||
|
||||
**前提原则(沿用已拍板方向):专员是任务的字段,不是页面。** 本方案不新增任何专员页面。
|
||||
|
||||
### 必改
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `views/workbench/SmartAssistantPage.vue:471` | 请求体补 `task_id` / `specialist_key`(步骤 2) |
|
||||
| `views/workbench/CapabilityCatalogDetailPage.vue:257` | 专员详情页 `extraSections: []` 是空的,**正好是挂「绑定技能」「岗位说明书」两个 section 的位置**(技能详情页 160-183 行有现成写法可抄) |
|
||||
| `store/workerRuntime.js:425-441` | `attachSpecialistToCurrentTask` 目前**强制**把技能清成 `DEFAULT_SKILL_KEY`(438 行)。这正是「选了专员反而更空」的根因——应改为写入该专员的**主技能**(`allowed_skills[0]`) |
|
||||
|
||||
### 建议改
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `views/workbench/StudioPage.vue:1505-1545`、`MarketPage.vue:660-740` | 管理员/市场的专员表单,是录入说明书与绑定技能的两个编辑入口(`api/specialist.go` 与表单 payload 需同步透传新字段) |
|
||||
| `components/chat/SpecialistChip.vue:41-54` | 胶囊提示补「已绑定 N 个技能」 |
|
||||
| `views/workbench/CapabilityCatalogPage.vue:385-404` | 专员卡片增加技能徽章 |
|
||||
|
||||
### 明确不改
|
||||
|
||||
- `config/workbench.js` 的 `availableSkills`(22 条)—— 技能仍归前端,本方案不把技能搬到后端
|
||||
- `config/skillSettings.js` 的既有 7 条技能定义
|
||||
- `skills/registry/*` 技能实现本体
|
||||
|
||||
> **双份真相问题记录在案**:前端 22 个技能 vs 后端 `skill_definition` 7 行,今天无同步机制。本方案用 §2.4 的 `ValidSkillKeys` 常量做**单向校验**兜底,不解决同步问题。彻底解决要等 SY22 的 `object_definition` 落地,**不在本轮**。
|
||||
|
||||
---
|
||||
|
||||
## 5. 顺带发现的线上缺陷(独立于本方案,建议立即修)
|
||||
|
||||
`internal/api/batch_extract.go:62` 与 `internal/api/contract_review.go:359` 调用:
|
||||
|
||||
```go
|
||||
ai.GenerateWithFallback(nil, messages)
|
||||
```
|
||||
|
||||
而 `internal/ai/llm.go:302` 的实现第一行就是:
|
||||
|
||||
```go
|
||||
fallbacks, err := config.GetFallbackRoutes(primary.RouteID) // primary == nil → 空指针
|
||||
```
|
||||
|
||||
**验证结论**:
|
||||
- `internal/api/router.go:146` / `:152` 确认两条路由都是活路径(`POST /api/contract/review`、`POST /api/batch/extract`,均挂 `middleware.Auth`)
|
||||
- `cmd/server/main.go:47` 用的是 `gin.Default()`,自带 Recovery —— 所以表现为 **HTTP 500**,不会打挂进程,但**这两个功能 100% 不可用**
|
||||
- 前端 `api/contract.js:3`、`api/batch.js:3` 确实在调这两个接口
|
||||
|
||||
**修复**:两处改为传入真实路由(`config.GetRoute(...)`,可参照 `smart_assistant.go:146`),或在 `GenerateWithFallback` 入口对 `primary == nil` 显式返回错误而非 panic。**建议两者都做**——前者修功能,后者防复发。
|
||||
|
||||
---
|
||||
|
||||
## 6. 不建议现在做的事
|
||||
|
||||
| 事项 | 原因 |
|
||||
|------|------|
|
||||
| 迁到统一的 `object_definition` 根表 | SY22 §6.1 是终态,但当前前端专员/技能展示**大量读本地硬编码**(`businessApps` 10 个、`availableSkills` 22 个)。先迁表等于先付迁移成本、后拿收益。本方案的字段命名已与 SY22 对齐,将来搬迁无返工 |
|
||||
| 把 22 个前端技能搬到后端 | 无运行时收益,且会立刻暴露「技能没有真实实现」的更大缺口 |
|
||||
| 给专员做独立页面 | 违背已拍板方向(专员是任务的字段)。AionUi 同样把助手配置放在设置里,不放主界面 |
|
||||
| 移植 `builtin-skills/pdf/` | 许可证禁止(见 §3) |
|
||||
| 补 `specialist_skill` 关联表 | 见 §2 步骤 1 的取舍说明 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 工作量与推进顺序
|
||||
|
||||
| 阶段 | 内容 | 估时 |
|
||||
|------|------|------|
|
||||
| **P0** | 修 §5 的空指针缺陷 | 0.5 天 |
|
||||
| **P1** | 步骤 1 数据层(2 字段 + 播种 + `ValidSkillKeys` 校验) | 0.5 天 |
|
||||
| **P2** | 步骤 2 打通链路(前端 2 处 + 后端 `resolveSpecialist`) | 0.5 天 |
|
||||
| **P3** | 步骤 3 注入 prompt(`buildAssistantSystemPrompt` + `worker_task.go:708` 同步) | 0.5 天 |
|
||||
| **P4** | 前端最小集(详情页两个 section + `attachSpecialistToCurrentTask` 改主技能) | 1 天 |
|
||||
| **P5** | 第一梯队 3 份说明书改写(需先拿到 OfficeCLI) | 每份 0.5–1 天 |
|
||||
|
||||
**P1–P3 合计约 1.5 天,做完即可看到「同一个助手在不同专员下说话方式不同」**——这是整个方案能否立住的最小验证点。**建议 P1–P3 做完先停下来验证一次,再决定要不要投 P5。**
|
||||
|
||||
### 验收标准(沿用 SY18 §8)
|
||||
|
||||
> 如果一个专员无法用三行(信源 / 动作 / 结果)说清、且权限说不出「能读什么 / 能写什么 / 谁能用」,说明设计过重了。
|
||||
|
||||
再加一条本方案的:
|
||||
|
||||
> **选中两个不同的专员、问同一句话,后端发出的 System Prompt 必须不同。** 只要这一条不成立,专员就还只是装饰。
|
||||
@@ -0,0 +1,941 @@
|
||||
# 数字员工平台整体架构重思考
|
||||
|
||||
> 落盘日期:2026-09-16
|
||||
> 状态:架构重思考稿,作为后续产品与数据结构重构的总纲
|
||||
> 关联文档:
|
||||
> - `../02_Architecture/AR05_Workbench_Architecture_Contract.md`
|
||||
> - `../02_Architecture/AR06_Skill_Packaging_Specification.md`
|
||||
> - `../02_Architecture/AR08_Role_Interaction_Design.md`
|
||||
|
||||
> 2026-09-16 架构同步说明:
|
||||
> 本文档保留 Workbench 收敛和对象化迁移结论,但总命名以
|
||||
> `docs/01_System_Overall/SY21_Unified_Role_Skill_Action_Architecture.md` 为准。
|
||||
> 当前统一口径为:
|
||||
> - 对外:`角色 / 技能 / 连接器`
|
||||
> - 对内:`role / skill / action / connector / policy`
|
||||
> - `tool` 在本稿中主要代表历史命名和过渡字段,不再作为未来正式概念
|
||||
> - 欢迎语、starter prompts、对象开场方式,应由角色对象属性驱动,而不是页面硬编码
|
||||
|
||||
---
|
||||
|
||||
## 1. 最终判断
|
||||
|
||||
现在这个系统最核心的问题,不是页面太多,也不是导航太乱,而是:
|
||||
|
||||
**产品架构、前端架构、后端数据结构三层没有使用同一个对象模型。**
|
||||
|
||||
当前系统里同时混着以下几种模型:
|
||||
|
||||
1. `任务挂专员`
|
||||
2. `工具等于页面`
|
||||
3. `项目保存一组 skill_keys / specialist_keys`
|
||||
4. `运行记录只知道 specialist_key,不知道真正执行的是谁`
|
||||
|
||||
这四套模型不能长期并存。
|
||||
|
||||
所以新的总架构必须统一成一句话:
|
||||
|
||||
`一个 Workbench + 一个任务会话 + 多个可挂载对象 + 一条可追踪执行链`
|
||||
|
||||
---
|
||||
|
||||
## 2. 产品架构重定义
|
||||
|
||||
平台以后不是“很多能力页面”,而是一个真正的数字员工平台,分成两大面:
|
||||
|
||||
### 2.1 执行面
|
||||
|
||||
执行面只保留一个:
|
||||
|
||||
- `Workbench`
|
||||
|
||||
它承载:
|
||||
|
||||
- 当前任务
|
||||
- 当前对象
|
||||
- 消息流
|
||||
- 工作流
|
||||
- 产物
|
||||
- 附件
|
||||
- 启动对象 / 切换对象 / 关闭对象
|
||||
|
||||
### 2.2 管理面
|
||||
|
||||
管理面负责:
|
||||
|
||||
- 目录浏览
|
||||
- 配置
|
||||
- 安装
|
||||
- 权限
|
||||
- 连接器
|
||||
- 运营
|
||||
- 观测
|
||||
|
||||
它不承担任务执行。
|
||||
|
||||
一句话:
|
||||
|
||||
- `Workbench` 负责使用
|
||||
- `Catalog / Studio / Console` 负责管理
|
||||
|
||||
---
|
||||
|
||||
## 3. 统一对象模型
|
||||
|
||||
未来系统里所有“可被用户启动、配置、关闭、调用”的东西,都统一叫:
|
||||
|
||||
`对象`
|
||||
|
||||
对象分三类:
|
||||
|
||||
### 3.1 默认助手
|
||||
|
||||
定义:
|
||||
|
||||
- 默认兜底对象
|
||||
- 没选专员、没选技术员时的默认入口
|
||||
|
||||
本质:
|
||||
|
||||
- 一种特殊的编排对象
|
||||
|
||||
### 3.2 数字专员
|
||||
|
||||
定义:
|
||||
|
||||
- 负责任务拆解、编排、协调、汇总的对象
|
||||
|
||||
本质:
|
||||
|
||||
- 编排型对象
|
||||
|
||||
### 3.3 数字技术员
|
||||
|
||||
定义:
|
||||
|
||||
- 负责某一个能力动作的对象
|
||||
|
||||
本质:
|
||||
|
||||
- 执行型对象
|
||||
|
||||
### 3.4 关键结论
|
||||
|
||||
工具不再是页面,也不再是一个特殊技术概念。
|
||||
|
||||
工具只是:
|
||||
|
||||
`数字技术员的产品展示名称`
|
||||
|
||||
所以未来建模必须统一为:
|
||||
|
||||
- 对象定义
|
||||
- 对象安装
|
||||
- 对象实例
|
||||
- 对象运行
|
||||
|
||||
而不是:
|
||||
|
||||
- 专员一套表
|
||||
- 工具一套路由
|
||||
- 页面里再塞一套局部状态
|
||||
|
||||
---
|
||||
|
||||
## 4. 新的领域分层
|
||||
|
||||
系统应该拆成 4 层:
|
||||
|
||||
### 4.1 定义层
|
||||
|
||||
定义“这个对象是谁”。
|
||||
|
||||
例如:
|
||||
|
||||
- 文档翻译技术员
|
||||
- 合同审查专员
|
||||
- 通用助手
|
||||
|
||||
这一层存:
|
||||
|
||||
- 身份
|
||||
- 来源
|
||||
- 版本
|
||||
- 设置 schema
|
||||
- 能力 schema
|
||||
- 展示配置
|
||||
|
||||
### 4.2 安装层
|
||||
|
||||
定义“这个对象在当前租户 / 工作区里是否可用”。
|
||||
|
||||
这一层存:
|
||||
|
||||
- 是否启用
|
||||
- 是否安装
|
||||
- 版本锁定
|
||||
- 权限范围
|
||||
- 默认配置
|
||||
|
||||
### 4.3 实例层
|
||||
|
||||
定义“这条任务当前挂了谁”。
|
||||
|
||||
这一层存:
|
||||
|
||||
- 当前任务里挂载了哪些对象
|
||||
- 当前焦点是谁
|
||||
- 各对象的本次任务配置快照
|
||||
- 对象是否打开 / 关闭
|
||||
|
||||
### 4.4 运行层
|
||||
|
||||
定义“这次实际跑了什么”。
|
||||
|
||||
这一层存:
|
||||
|
||||
- 消息
|
||||
- 调用链
|
||||
- 步骤
|
||||
- 产物
|
||||
- 日志
|
||||
- 状态变化
|
||||
|
||||
---
|
||||
|
||||
## 5. 最重要的结构纠偏
|
||||
|
||||
### 5.1 Task 不能只挂一个 specialist_key
|
||||
|
||||
当前 `worker_task` 的核心绑定是:
|
||||
|
||||
- `specialist_key`
|
||||
|
||||
这不够。
|
||||
|
||||
因为未来一条任务里可能同时存在:
|
||||
|
||||
- 一个主专员
|
||||
- 多个技术员
|
||||
- 动态切换的当前焦点对象
|
||||
|
||||
但对用户可见的输入区交互,必须坚持一条规则:
|
||||
|
||||
- `+` 右边一次只显示一个当前对象
|
||||
- 当前对象要么是专员,要么是技能,要么是默认助手
|
||||
- 专员内部调用技能,只进入执行链和右侧面板,不在输入区显性双挂
|
||||
|
||||
所以真正的任务结构不应是:
|
||||
|
||||
`task -> specialist_key`
|
||||
|
||||
而应是:
|
||||
|
||||
`task -> mounted objects`
|
||||
|
||||
### 5.2 Run 不能只知道 specialist_key
|
||||
|
||||
当前 `worker_run` 也只知道:
|
||||
|
||||
- `specialist_key`
|
||||
- `action_key`
|
||||
|
||||
这会导致系统分不清:
|
||||
|
||||
- 是哪个对象发起的
|
||||
- 是哪个对象实际执行的
|
||||
- 是专员步骤,还是技术员步骤
|
||||
- 是人工确认,还是自动调用
|
||||
|
||||
所以运行记录必须升级为:
|
||||
|
||||
- 谁发起
|
||||
- 谁执行
|
||||
- 父子运行关系
|
||||
- 对应对象实例
|
||||
|
||||
### 5.3 Project 不能只存 skill_keys 与 object_entry_route 语义
|
||||
|
||||
当前项目里保存:
|
||||
|
||||
- `specialist_keys`
|
||||
- `skill_keys`
|
||||
- `connector_keys`
|
||||
|
||||
方向是对的,但语义还不够硬。
|
||||
|
||||
以后项目应该保存的是:
|
||||
|
||||
- 默认对象绑定
|
||||
- 默认配置快照
|
||||
- 默认连接器绑定
|
||||
- 默认知识域
|
||||
|
||||
而不是仅仅一串“key 列表”。
|
||||
|
||||
### 5.4 消息必须成为一等数据
|
||||
|
||||
当前系统最大缺口之一,是消息没有成为正式持久化对象。
|
||||
|
||||
没有消息层,Workbench 永远只是半成品,因为:
|
||||
|
||||
- 任务无法真正恢复
|
||||
- 对象切换没有上下文历史
|
||||
- 运行记录无法和用户意图精确对齐
|
||||
- 后续审计、回放、总结都不完整
|
||||
|
||||
所以必须新增:
|
||||
|
||||
- `task_message`
|
||||
|
||||
---
|
||||
|
||||
## 6. 推荐的核心数据结构
|
||||
|
||||
以下是建议采用的目标数据模型。
|
||||
|
||||
## 6.1 对象定义表 `object_definition`
|
||||
|
||||
作用:
|
||||
|
||||
- 统一描述默认助手 / 专员 / 技术员
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type ObjectDefinition = {
|
||||
id: string
|
||||
code: string
|
||||
source: 'eai' | 'custom'
|
||||
kind: 'assistant' | 'specialist' | 'tool'
|
||||
key: string
|
||||
label: string
|
||||
description: string
|
||||
version: string
|
||||
state: 'active' | 'inactive'
|
||||
icon: string
|
||||
color: string
|
||||
capabilitySchema: object
|
||||
settingsSchema: object[]
|
||||
workflowSchema: object[]
|
||||
artifactSchema: object[]
|
||||
uiSchema: object
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. `specialist` 和 `tool` 都是对象定义,不再属于两套异构模型
|
||||
2. EAI 与 custom 由 `source` 区分
|
||||
3. 旧的 `specialist` 表最终应演进成这一层
|
||||
|
||||
## 6.2 对象安装表 `object_installation`
|
||||
|
||||
作用:
|
||||
|
||||
- 记录某个对象在某个租户 / 工作区 / 组织里是否可用
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type ObjectInstallation = {
|
||||
id: string
|
||||
objectDefinitionId: string
|
||||
tenantId: string
|
||||
workspaceId: string
|
||||
state: 'installed' | 'disabled' | 'trial'
|
||||
pinned: boolean
|
||||
permissionScope: object
|
||||
connectorBindings: object[]
|
||||
knowledgeBindings: object[]
|
||||
defaultSettings: object
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 这层解决“平台有,但当前租户能不能用”
|
||||
2. 这层负责安装态,而不是任务态
|
||||
|
||||
## 6.3 项目表 `project`
|
||||
|
||||
作用:
|
||||
|
||||
- 作为任务的长期上下文容器
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type Project = {
|
||||
id: string
|
||||
code: string
|
||||
name: string
|
||||
ownerId: string
|
||||
instruction: string
|
||||
templateKey: string
|
||||
defaultObjectBindings: object[]
|
||||
defaultConnectorBindings: object[]
|
||||
defaultKnowledgeBindings: object[]
|
||||
state: 'active' | 'archived'
|
||||
pinned: boolean
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 项目不是对象目录
|
||||
2. 项目是任务上下文模板
|
||||
3. 项目里应该保存默认挂载关系,而不是只保存裸 key 列表
|
||||
|
||||
## 6.4 任务会话表 `task_session`
|
||||
|
||||
作用:
|
||||
|
||||
- 表示用户正在处理的一条真实任务
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type TaskSession = {
|
||||
id: string
|
||||
title: string
|
||||
summary: string
|
||||
ownerId: string
|
||||
projectId?: string
|
||||
state: 'draft' | 'running' | 'waiting' | 'done' | 'archived'
|
||||
priority: 'P1' | 'P2' | 'P3'
|
||||
currentObjectInstanceId?: string
|
||||
defaultSpecialistInstanceId?: string
|
||||
latestRunId?: string
|
||||
latestArtifactId?: string
|
||||
pinned: boolean
|
||||
dueAt?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 任务只记录“当前主会话”
|
||||
2. 任务不直接存 `tool object_entry_route`
|
||||
3. 任务不直接把工具建模成页面
|
||||
|
||||
## 6.5 任务挂载对象表 `task_object_instance`
|
||||
|
||||
作用:
|
||||
|
||||
- 这是整个系统最关键的新表
|
||||
- 记录某条任务当前挂载了哪些对象
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type TaskObjectInstance = {
|
||||
id: string
|
||||
taskId: string
|
||||
objectDefinitionId: string
|
||||
objectKind: 'assistant' | 'specialist' | 'skill'
|
||||
role: 'default' | 'primary' | 'secondary'
|
||||
state: 'mounted' | 'focused' | 'closed'
|
||||
settingsSnapshot: object
|
||||
source: 'manual' | 'auto'
|
||||
mountedAt: string
|
||||
closedAt?: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 当前专员、当前技能都应该从这里来
|
||||
2. `currentSkillKey` 只是这张表的前端运行态字段
|
||||
3. 关闭对象时,不是跳页面,而是把实例 state 改成 `closed`
|
||||
|
||||
## 6.6 消息表 `task_message`
|
||||
|
||||
作用:
|
||||
|
||||
- 持久化消息流
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type TaskMessage = {
|
||||
id: string
|
||||
taskId: string
|
||||
objectInstanceId?: string
|
||||
role: 'user' | 'assistant' | 'system'
|
||||
messageType: 'text' | 'tool_call' | 'status' | 'summary'
|
||||
contentText: string
|
||||
contentJSON?: object
|
||||
replyToMessageId?: string
|
||||
createdAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 每条消息可以挂到某个对象实例上
|
||||
2. 这样才能知道“这句话是对谁说的”
|
||||
3. 回放、总结、继续追问都依赖这层
|
||||
|
||||
## 6.7 执行表 `object_run`
|
||||
|
||||
作用:
|
||||
|
||||
- 记录对象实际执行的过程
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type ObjectRun = {
|
||||
id: string
|
||||
taskId: string
|
||||
objectInstanceId: string
|
||||
initiatedByRunId?: string
|
||||
initiatedByObjectInstanceId?: string
|
||||
parentRunId?: string
|
||||
runType: 'chat' | 'workflow' | 'skill' | 'approval'
|
||||
actionKey: string
|
||||
actionTitle: string
|
||||
state: 'queued' | 'running' | 'waiting' | 'done' | 'failed' | 'cancelled'
|
||||
inputJSON: object
|
||||
outputJSON?: object
|
||||
logsJSON?: object[]
|
||||
startedAt?: string
|
||||
finishedAt?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 必须显式有 `running / waiting / failed`
|
||||
2. 当前 `worker_run.status` 默认 `done` 的模型是不够的
|
||||
3. `parentRunId` 解决专员调用技术员的问题
|
||||
|
||||
## 6.8 产物表 `artifact`
|
||||
|
||||
作用:
|
||||
|
||||
- 统一管理任务产出
|
||||
|
||||
建议字段:
|
||||
|
||||
```ts
|
||||
type Artifact = {
|
||||
id: string
|
||||
taskId: string
|
||||
objectInstanceId?: string
|
||||
createdByRunId?: string
|
||||
artifactType: string
|
||||
title: string
|
||||
state: 'draft' | 'review' | 'approved' | 'published'
|
||||
contentText?: string
|
||||
contentJSON?: object
|
||||
sourceRefsJSON?: object[]
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 产物不属于页面
|
||||
2. 产物属于任务和执行链
|
||||
3. 右栏展示只是视图,不是数据来源
|
||||
|
||||
---
|
||||
|
||||
## 7. 前端运行时结构重定义
|
||||
|
||||
前端 store 应该从“按页面凑状态”改成“按任务会话管理状态”。
|
||||
|
||||
推荐结构:
|
||||
|
||||
```ts
|
||||
type WorkbenchRuntime = {
|
||||
activeTaskId: string
|
||||
draftSelection: {
|
||||
specialistKey?: string
|
||||
toolKey?: string
|
||||
mode?: string
|
||||
}
|
||||
tasksById: Record<string, TaskSession>
|
||||
mountedObjectsByTaskId: Record<string, TaskObjectInstance[]>
|
||||
messagesByTaskId: Record<string, TaskMessage[]>
|
||||
runsByTaskId: Record<string, ObjectRun[]>
|
||||
artifactsByTaskId: Record<string, Artifact[]>
|
||||
focusedObjectInstanceIdByTaskId: Record<string, string>
|
||||
panelStateByTaskId: Record<string, { activeTab: 'workflow' | 'artifacts' }>
|
||||
}
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. 当前对象应该由 `focusedObjectInstanceId` 决定
|
||||
2. `currentSkillKey` 和 `currentSpecialistKey` 最终都只是计算值
|
||||
3. 页面不应该自己猜当前对象是谁
|
||||
|
||||
---
|
||||
|
||||
## 8. 前端目录结构重定义
|
||||
|
||||
建议未来前端结构分成 5 块:
|
||||
|
||||
```text
|
||||
src/
|
||||
workbench/
|
||||
pages/
|
||||
components/
|
||||
stores/
|
||||
runtime/
|
||||
tools/
|
||||
eai/
|
||||
custom/
|
||||
registry/
|
||||
shared/
|
||||
specialists/
|
||||
eai/
|
||||
custom/
|
||||
registry/
|
||||
shared/
|
||||
connectors/
|
||||
catalog/
|
||||
```
|
||||
|
||||
关键说明:
|
||||
|
||||
1. `workbench/` 只承载执行工作面
|
||||
2. `tools/` 只放技术员定义与局部组件
|
||||
3. `specialists/` 只放专员定义与局部组件
|
||||
4. 不再允许 `views/tools/*.vue` 承担执行职责
|
||||
|
||||
---
|
||||
|
||||
## 9. 路由模型重定义
|
||||
|
||||
未来路由应该只分三类:
|
||||
|
||||
### 9.1 执行路由
|
||||
|
||||
- `/home`
|
||||
|
||||
### 9.2 目录路由
|
||||
|
||||
- `/catalog/specialists`
|
||||
- `/catalog/skills`
|
||||
- `/catalog/connectors`
|
||||
|
||||
### 9.3 配置 / 管理路由
|
||||
|
||||
- `/studio`
|
||||
- `/console`
|
||||
- `/projects`
|
||||
|
||||
强结论:
|
||||
|
||||
- `apps/*` 退出执行入口
|
||||
- `tools/*` 退出执行入口
|
||||
|
||||
---
|
||||
|
||||
## 10. 对当前表结构的明确评价
|
||||
|
||||
### 10.1 当前 `specialist` 表
|
||||
|
||||
优点:
|
||||
|
||||
- 已经积累了足够多的对象定义字段
|
||||
|
||||
问题:
|
||||
|
||||
- 同时承载了目录字段、展示字段、流程字段、配置字段
|
||||
- 仍然以“专员”命名,无法统一承载默认助手和技术员
|
||||
|
||||
判断:
|
||||
|
||||
- 可以作为 `object_definition` 的迁移来源
|
||||
- 不建议长期继续维持原表语义
|
||||
|
||||
### 10.2 当前 `worker_task` 表
|
||||
|
||||
优点:
|
||||
|
||||
- 已经有任务的基础壳
|
||||
|
||||
问题:
|
||||
|
||||
- 核心绑定仍然是 `specialist_key`
|
||||
- 还没有对象实例层
|
||||
- 还没有消息层
|
||||
|
||||
判断:
|
||||
|
||||
- 适合作为 `task_session` 的迁移来源
|
||||
- 不适合作为最终任务模型
|
||||
|
||||
### 10.3 当前 `worker_run` 表
|
||||
|
||||
优点:
|
||||
|
||||
- 已经有动作记录
|
||||
|
||||
问题:
|
||||
|
||||
- 缺少对象实例 id
|
||||
- 缺少父子调用链
|
||||
- 缺少真实运行状态
|
||||
|
||||
判断:
|
||||
|
||||
- 适合作为 `object_run` 的迁移来源
|
||||
- 必须升级
|
||||
|
||||
### 10.4 当前 `worker_artifact` 表
|
||||
|
||||
优点:
|
||||
|
||||
- 基本方向正确
|
||||
|
||||
问题:
|
||||
|
||||
- 仍然绑定 `specialist_key`
|
||||
- 没有明确对象实例来源
|
||||
|
||||
判断:
|
||||
|
||||
- 可以直接演进成新 `artifact` 模型
|
||||
|
||||
---
|
||||
|
||||
## 11. 最关键的产品决策
|
||||
|
||||
下面这些必须作为平台级决策固定下来:
|
||||
|
||||
### 11.1 任务中心化
|
||||
|
||||
所有运行时行为都围绕任务展开。
|
||||
|
||||
### 11.2 对象实例化
|
||||
|
||||
对象不是页面,不是 tab,不是配置项。
|
||||
|
||||
对象在任务里必须有实例。
|
||||
|
||||
### 11.3 消息持久化
|
||||
|
||||
没有消息层,就没有真正的 Workbench。
|
||||
|
||||
### 11.4 运行链可追踪
|
||||
|
||||
专员调技术员,必须可追踪为父子执行链。
|
||||
|
||||
### 11.5 管理与使用分离
|
||||
|
||||
Catalog / Studio / Console 不参与执行面。
|
||||
|
||||
---
|
||||
|
||||
## 12. 推荐迁移顺序
|
||||
|
||||
### Phase 1:冻结对象模型
|
||||
|
||||
确定:
|
||||
|
||||
- assistant / specialist / tool 三类对象
|
||||
- source / code / key / label 规范
|
||||
|
||||
### Phase 2:补对象实例层
|
||||
|
||||
新增:
|
||||
|
||||
- `task_object_instance`
|
||||
|
||||
前端先用 runtime 影子模型兼容。
|
||||
|
||||
### Phase 3:补消息层
|
||||
|
||||
新增:
|
||||
|
||||
- `task_message`
|
||||
|
||||
让任务真正可恢复。
|
||||
|
||||
### Phase 4:升级运行链
|
||||
|
||||
把 `worker_run` 升级为带父子关系的 `object_run`。
|
||||
|
||||
### Phase 5:收口前端执行页
|
||||
|
||||
删除:
|
||||
|
||||
- `apps/*` 执行页
|
||||
- `tools/*` 执行页
|
||||
|
||||
### Phase 6:收口定义层
|
||||
|
||||
把:
|
||||
|
||||
- `specialist`
|
||||
- `tool config`
|
||||
|
||||
逐步统一到对象定义体系。
|
||||
|
||||
---
|
||||
|
||||
## 13. WorkBuddy 实测确认点
|
||||
|
||||
本轮已实际登录并查看 WorkBuddy,以下观察可以作为架构校准依据。
|
||||
|
||||
### 13.1 单一执行工作面成立
|
||||
|
||||
登录后默认进入的是单一工作台,而不是“先选一个工具页再开始工作”。
|
||||
|
||||
可见特征:
|
||||
|
||||
- 左侧是一级工作区标签
|
||||
- 中间是统一输入工作面
|
||||
- 右侧是固定侧栏
|
||||
|
||||
这说明:
|
||||
|
||||
- 我们保留唯一 Workbench 的方向是对的
|
||||
|
||||
### 13.2 `项目` 是独立管理面,不是执行页
|
||||
|
||||
WorkBuddy 的 `项目` 入口跳到单独的项目列表与模板空间。
|
||||
|
||||
这个页面的职责是:
|
||||
|
||||
- 项目管理
|
||||
- 项目模板
|
||||
- 多人协同入口
|
||||
|
||||
而不是聊天执行。
|
||||
|
||||
这说明:
|
||||
|
||||
- 我们把 `项目` 归入管理面是对的
|
||||
- 项目不是对象目录,也不是工具页
|
||||
|
||||
### 13.3 `专家·技能·连接器` 是统一目录中心
|
||||
|
||||
WorkBuddy 中这一组入口是统一的目录中心,内部再切:
|
||||
|
||||
- 专家
|
||||
- 技能
|
||||
- 连接器
|
||||
|
||||
它的形态明显是:
|
||||
|
||||
- 搜索
|
||||
- 分类
|
||||
- 推荐
|
||||
- 安装 / 连接
|
||||
|
||||
而不是执行工作面。
|
||||
|
||||
这说明:
|
||||
|
||||
- 我们把 `Catalog` 与 `Workbench` 分开是对的
|
||||
- `专员·工具·连接器` 不应该承担直接执行语义
|
||||
|
||||
### 13.4 具体技能点击后是详情 / 安装,不是进入另一套聊天页
|
||||
|
||||
在 `技能` 列表中点击某个具体技能后,出现的是技能详情与安装动作,而不是跳进单独的技能聊天页面。
|
||||
|
||||
这说明:
|
||||
|
||||
- “一个工具一个执行页”的老结构方向不对
|
||||
- 工具更接近“目录项 + 详情 + 安装 + 后续被调用”
|
||||
|
||||
### 13.5 右侧面板是壳层能力,不是某个页面私有能力
|
||||
|
||||
无论在新建任务、项目、技能、连接器等区域,右侧面板结构都持续存在。
|
||||
|
||||
即使内容为空,壳也还在。
|
||||
|
||||
这说明:
|
||||
|
||||
- 右栏应该属于 shell / workbench 壳层
|
||||
- 不应该每个工具页自己维护一份右栏
|
||||
|
||||
### 13.6 WorkBuddy 仍然保留了较强的“市场 / 目录 / 工作台”边界
|
||||
|
||||
它不是把所有东西都糊成一个平面,而是:
|
||||
|
||||
- 工作台负责执行
|
||||
- 项目负责协同容器
|
||||
- 专家 / 技能 / 连接器负责目录与安装
|
||||
|
||||
这和我们当前重构方向高度一致。
|
||||
|
||||
### 13.7 对我们的直接启发
|
||||
|
||||
WorkBuddy 实测后,可以进一步确认以下决策不需要再摇摆:
|
||||
|
||||
1. 保留唯一执行工作面
|
||||
2. `项目` 作为管理 / 协同面保留
|
||||
3. `专家·技能·连接器` 作为目录中心保留
|
||||
4. 工具不再做独立执行页
|
||||
5. 右栏属于壳层,而不是页面层
|
||||
|
||||
### 13.8 我们不需要照搬的地方
|
||||
|
||||
WorkBuddy 当前实现里,仍然保留了较强的目录跳转结构。
|
||||
|
||||
我们项目和它的差异是:
|
||||
|
||||
- 我们更强调“任务上下文中的对象挂载”
|
||||
- 我们更强调“启动、配置、关闭对象”
|
||||
- 我们希望对象实例层更加明确
|
||||
|
||||
所以我们不需要简单复刻它的页面结构,而应该吸收它已经验证过的边界:
|
||||
|
||||
- 工作台是工作台
|
||||
- 目录是目录
|
||||
- 安装是安装
|
||||
- 执行不是目录页行为
|
||||
|
||||
---
|
||||
|
||||
## 14. 关于 WorkBuddy 与本项目的关系
|
||||
|
||||
基于当前仓库、既有合同以及本轮 WorkBuddy 实测,已经可以确认:
|
||||
|
||||
- 第一性原理判断没有走偏
|
||||
- WorkBuddy 更适合用来校准边界,而不是替代建模
|
||||
|
||||
也就是说:
|
||||
|
||||
- 我们参考 WorkBuddy
|
||||
- 但我们的最终模型应该比它更明确地引入“对象实例层”
|
||||
|
||||
---
|
||||
|
||||
## 15. 最终一句话
|
||||
|
||||
这个平台最终不应该再被理解为:
|
||||
|
||||
`专员页 + 工具页 + 若干配置页`
|
||||
|
||||
而应该被理解为:
|
||||
|
||||
`一个数字员工工作台 + 一套对象目录 + 一层对象实例模型 + 一条执行与产物链`
|
||||
|
||||
如果后续任何实现仍然要求用户去理解:
|
||||
|
||||
- 我现在在哪个工具页
|
||||
- 我是不是切到了另一个专员页
|
||||
- 这个页面和那条任务是什么关系
|
||||
|
||||
那就说明架构还没有真正完成重构。
|
||||
@@ -0,0 +1,482 @@
|
||||
# 数字员工 Workbench 架构合同
|
||||
|
||||
> 落盘日期:2026-09-16
|
||||
> 状态:架构合同
|
||||
> 作用:作为后续前端重构的强约束,先定模型,再做代码迁移
|
||||
> 关联文档:`AR08_Role_Interaction_Design.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标
|
||||
|
||||
系统后续只保留一个大的工作台。
|
||||
|
||||
这个工作台必须同时满足 4 件事:
|
||||
|
||||
1. 用户始终在同一个主工作面里完成任务
|
||||
2. 专员和工具都不是“去一个页面”,而是“挂到当前任务里的对象”
|
||||
3. 对象可以被启动、配置、切换焦点、关闭
|
||||
4. 所有执行上下文都以任务为中心,而不是以路由为中心
|
||||
|
||||
一句话定义:
|
||||
|
||||
`一个 Workbench + 一条任务上下文 + 多个可挂载对象`
|
||||
|
||||
---
|
||||
|
||||
## 2. 强结论
|
||||
|
||||
### 2.1 保留一个唯一执行工作面
|
||||
|
||||
前端只允许一个执行型主工作面:
|
||||
|
||||
- 建议沿用 `/home` 作为 canonical page_route
|
||||
- `/` 直接进入 `/home`
|
||||
|
||||
这个页面承载:
|
||||
|
||||
- 消息流
|
||||
- 当前对象 chip
|
||||
- 设置条
|
||||
- 工作流 / 产物右栏
|
||||
- 附件入口
|
||||
- `+` 菜单
|
||||
|
||||
### 2.2 `apps/*` 不再作为使用入口
|
||||
|
||||
`/apps/*` 可以去掉“执行页”角色。
|
||||
|
||||
以后它只能有两种命运:
|
||||
|
||||
1. 被删除
|
||||
2. 退化成兼容跳转,统一跳回 `/home`
|
||||
|
||||
它不能继续承担:
|
||||
|
||||
- 打开专员工作台
|
||||
- 在专员页里执行任务
|
||||
- 与主工作面并行存在
|
||||
|
||||
### 2.3 `tools/*` 不再作为使用入口
|
||||
|
||||
`/tools/*` 也可以去掉“执行页”角色。
|
||||
|
||||
以后工具不再被建模为一组独立页面,而是:
|
||||
|
||||
- 当前任务里被启动的技术员对象
|
||||
- 由统一工作面承载执行
|
||||
|
||||
`/tools/*` 在迁移期只允许做兼容跳转,不允许继续扩散业务逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 3. 对象模型
|
||||
|
||||
### 3.1 三类对象
|
||||
|
||||
| 对象 | 本质 | 角色 |
|
||||
|------|------|------|
|
||||
| 通用助手 | 默认专员 | 没有显式指定对象时的兜底编排者 |
|
||||
| 数字专员 | 编排型对象 | 负责拆任务、排步骤、调用工具、汇总结果 |
|
||||
| 数字技术员 | 执行型对象 | 负责单点能力执行,例如翻译、提取、转写 |
|
||||
|
||||
### 3.2 工具的真正定义
|
||||
|
||||
“工具”只是数字技术员的展示别名,不再是页面类型。
|
||||
|
||||
所以未来语义应该是:
|
||||
|
||||
- 文档翻译工具 -> 文档翻译技术员
|
||||
- 文案校对工具 -> 文案校对技术员
|
||||
- 批量提取工具 -> 批量提取技术员
|
||||
|
||||
如果某个对象既有“专员态”又有“工具态”,必须拆成两个不同 key,禁止复用同一个 key。
|
||||
|
||||
例如这类冲突必须消除:
|
||||
|
||||
- `contract-review` 不能同时代表专员和工具
|
||||
- `report-generation` 不能同时代表专员和工具
|
||||
|
||||
---
|
||||
|
||||
## 4. 状态模型
|
||||
|
||||
## 4.1 核心原则
|
||||
|
||||
所有运行时状态必须挂在“当前任务”下面。
|
||||
|
||||
禁止再出现:
|
||||
|
||||
- 专员状态靠任务 store
|
||||
- 工具状态靠路由
|
||||
- 右栏状态靠页面推断
|
||||
|
||||
这三套并行模型。
|
||||
|
||||
### 4.2 迁移期必须新增的状态
|
||||
|
||||
第一阶段必须补上:
|
||||
|
||||
```ts
|
||||
type TaskRuntimeContextV1 = {
|
||||
currentTaskId: string
|
||||
currentSpecialistKey: string
|
||||
currentSkillKey: string
|
||||
}
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
- `currentSpecialistKey` 表示当前任务挂载的主编排对象
|
||||
- `currentSkillKey` 表示当前输入区和设置条默认服务的技能对象
|
||||
|
||||
`currentSkillKey` 的意义是把技能正式纳入任务上下文,结束“技能只存在于路由页”的旧模型。
|
||||
|
||||
### 4.3 最终推荐状态模型
|
||||
|
||||
在迁移完成后,建议升级为:
|
||||
|
||||
```ts
|
||||
type TaskRuntimeContext = {
|
||||
currentTaskId: string
|
||||
currentSpecialistKey: string
|
||||
openedSkillKeys: string[]
|
||||
focusedObjectKind: 'assistant' | 'specialist' | 'skill'
|
||||
focusedObjectKey: string
|
||||
mode: 'quick' | 'expert'
|
||||
}
|
||||
```
|
||||
|
||||
解释:
|
||||
|
||||
- `currentTaskId`:当前任务
|
||||
- `currentSpecialistKey`:这条任务当前的主编排者
|
||||
- `openedSkillKeys`:这条任务里已启动但未关闭的技能
|
||||
- `focusedObjectKind` / `focusedObjectKey`:当前输入框、设置条、右栏正在服务哪个对象
|
||||
- `mode`:当前工作模式
|
||||
|
||||
### 4.4 状态约束
|
||||
|
||||
必须满足以下约束:
|
||||
|
||||
1. 没有任务时,允许预选对象,但只能作为 pending 状态
|
||||
2. 一旦第一条消息发出,pending 状态必须落入任务上下文
|
||||
3. `focusedObjectKey` 必须属于:
|
||||
- `currentSpecialistKey`
|
||||
- `openedSkillKeys`
|
||||
- 或默认助手
|
||||
4. 关闭对象后,焦点必须自动切回:
|
||||
- 同任务下的其他已打开对象
|
||||
- 没有则回到当前专员
|
||||
- 再没有则回到通用助手
|
||||
|
||||
---
|
||||
|
||||
## 5. 路由收敛原则
|
||||
|
||||
### 5.1 执行路由
|
||||
|
||||
执行型路由只保留:
|
||||
|
||||
- `/home`
|
||||
|
||||
### 5.2 目录与配置路由
|
||||
|
||||
允许保留的非执行路由只有两类:
|
||||
|
||||
1. 目录路由
|
||||
例如:
|
||||
- `/catalog/specialists`
|
||||
- `/catalog/skills`
|
||||
- `/catalog/connectors`
|
||||
|
||||
2. 配置 / 管理路由
|
||||
例如:
|
||||
- `/studio`
|
||||
- `/console`
|
||||
- 后台管理页
|
||||
|
||||
### 5.3 兼容跳转规则
|
||||
|
||||
在迁移阶段:
|
||||
|
||||
- `/apps/*` -> 跳回 `/home`
|
||||
- `/tools/*` -> 跳回 `/home`
|
||||
|
||||
跳转时要把对象意图带回工作台,例如:
|
||||
|
||||
- 原 `/tools/document-translate`
|
||||
-> `/home` 并恢复 `currentSkillKey=document-translate`
|
||||
- 原 `/apps/contract-review`
|
||||
-> `/home` 并恢复 `currentSpecialistKey=contract-review-specialist`
|
||||
|
||||
兼容跳转只做迁移兜底,不允许再承载新逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 6. 工作台交互合同
|
||||
|
||||
### 6.1 输入区
|
||||
|
||||
输入区固定结构:
|
||||
|
||||
`[+] [当前对象 chip] [附件] [输入框] [发送]`
|
||||
|
||||
规则:
|
||||
|
||||
1. `+` 是唯一启动入口
|
||||
2. `当前对象 chip` 是唯一上下文可视入口
|
||||
3. 输入区永远不因为对象类型不同而变成另一套布局
|
||||
|
||||
### 6.2 `+` 菜单
|
||||
|
||||
`+` 菜单只负责 4 类动作:
|
||||
|
||||
1. 切模式
|
||||
2. 启动 / 切换专员
|
||||
3. 启动工具
|
||||
4. 打开连接器相关能力
|
||||
|
||||
`+` 菜单不负责跳执行页。
|
||||
|
||||
### 6.3 当前对象 chip
|
||||
|
||||
规则:
|
||||
|
||||
1. 固定显示在 `+` 右边
|
||||
2. 始终展示当前焦点对象
|
||||
3. 专员、工具结构统一,只是样式和文案不同
|
||||
4. 点击 chip 只允许:
|
||||
- 展开详情
|
||||
- 切焦点
|
||||
- 打开配置抽屉
|
||||
|
||||
不允许点击后跳到另一套执行页面。
|
||||
|
||||
### 6.4 设置条
|
||||
|
||||
设置条是“当前焦点对象”的设置条,不是“当前路由页”的设置条。
|
||||
|
||||
规则:
|
||||
|
||||
1. 只服务 `focusedObjectKey`
|
||||
2. 改动从下一条消息开始生效
|
||||
3. 不允许继续根据 `/tools/*` 路由推断工具身份
|
||||
|
||||
### 6.5 右栏
|
||||
|
||||
右栏固定两个 tab:
|
||||
|
||||
- 工作流
|
||||
- 产物
|
||||
|
||||
规则:
|
||||
|
||||
1. 右栏服务当前焦点对象
|
||||
2. 专员焦点时,展示专员级工作流与产物
|
||||
3. 工具焦点时,展示工具级执行流与产物
|
||||
4. 右栏不允许只支持专员、不支持工具
|
||||
|
||||
---
|
||||
|
||||
## 7. 对象生命周期
|
||||
|
||||
每个专员 / 工具都必须服从统一生命周期:
|
||||
|
||||
### 7.1 启动
|
||||
|
||||
启动来源:
|
||||
|
||||
- `+` 菜单
|
||||
- 目录页中的“启动”动作
|
||||
- 兼容跳转恢复
|
||||
|
||||
启动结果:
|
||||
|
||||
- 对象进入当前任务上下文
|
||||
- 成为可聚焦对象
|
||||
- 在输入区显示为当前对象或可切换对象
|
||||
|
||||
### 7.2 配置
|
||||
|
||||
配置行为包括:
|
||||
|
||||
- 修改模式
|
||||
- 修改对象设置
|
||||
- 打开对象详情
|
||||
- 调整对象参数
|
||||
|
||||
配置结果必须记录在任务上下文,而不是记录在页面局部状态。
|
||||
|
||||
### 7.3 关闭
|
||||
|
||||
关闭对象后:
|
||||
|
||||
- 从当前任务的已打开对象列表中移除
|
||||
- 关闭该对象设置条
|
||||
- 焦点自动切回其他对象
|
||||
|
||||
关闭不是“离开页面”,而是“从当前任务上下文卸载对象”。
|
||||
|
||||
### 7.4 重新打开
|
||||
|
||||
如果任务里已经存在一个对象,再次点击它时:
|
||||
|
||||
- 默认切焦点
|
||||
- 不再重复创建
|
||||
|
||||
---
|
||||
|
||||
## 8. 页面职责收敛
|
||||
|
||||
### 8.1 `BusinessAppPage` 的状态
|
||||
|
||||
`BusinessAppPage` 已从前端仓库移除。
|
||||
|
||||
这说明以下约束已经落地:
|
||||
|
||||
- 不再承担聊天执行
|
||||
- 不再承担任务推进主入口
|
||||
- 不再与 `/home` 形成并行的第二工作台
|
||||
|
||||
### 8.2 各 `ToolPage` 的状态
|
||||
|
||||
`DocumentTranslatePage`、`CopyProofreadingPage`、`AudioTranscribePage` 等旧工具执行页已从前端仓库移除。
|
||||
|
||||
它们留下来的有效资产只剩两类:
|
||||
|
||||
1. 已抽离出的 schema / runtime / 组件
|
||||
2. 历史设计文档中的迁移记录
|
||||
|
||||
它们已经不再作为产品形态存在。
|
||||
|
||||
---
|
||||
|
||||
## 9. 数据层约束
|
||||
|
||||
### 9.1 任务是唯一事实来源
|
||||
|
||||
以下运行时状态必须最终可从任务恢复:
|
||||
|
||||
- 当前专员
|
||||
- 当前工具
|
||||
- 已打开工具列表
|
||||
- 当前焦点对象
|
||||
- 对象设置快照
|
||||
- 关键工作流状态
|
||||
- 产物列表
|
||||
|
||||
### 9.2 禁止继续混用演示数据与真实数据
|
||||
|
||||
以下情况必须逐步清理:
|
||||
|
||||
- 页面本地写死 `messages`
|
||||
- 页面本地写死 `taskItems`
|
||||
- 工作台 snapshot 与 live data 混合渲染但界面上不区分
|
||||
|
||||
迁移后应满足:
|
||||
|
||||
1. 真数据就渲真数据
|
||||
2. 演示态必须明确标注为模板 / 示例 / 空态
|
||||
3. 不允许让示例数据冒充真实任务结果
|
||||
|
||||
---
|
||||
|
||||
## 10. 迁移顺序
|
||||
|
||||
### Phase 0:合同冻结
|
||||
|
||||
先冻结这份合同,后续改造按它执行。
|
||||
|
||||
### Phase 1:补全任务上下文
|
||||
|
||||
目标:
|
||||
|
||||
- 增加 `currentSkillKey`
|
||||
- 让技能脱离路由身份,先进入任务 store
|
||||
|
||||
结果:
|
||||
|
||||
- 选技能不再只是跳页
|
||||
- 工作台第一次具备“任务 + 专员 + 技能”的统一上下文
|
||||
|
||||
### Phase 2:统一当前对象
|
||||
|
||||
目标:
|
||||
|
||||
- `CurrentObjectChip` 改为真正读任务上下文
|
||||
- 设置条改为读 `focusedObjectKey`
|
||||
- 右栏从“专员面板”演进为“对象面板”
|
||||
|
||||
结果:
|
||||
|
||||
- 输入区、设置条、右栏三者对齐
|
||||
|
||||
### Phase 3:路由收敛
|
||||
|
||||
目标:
|
||||
|
||||
- `/apps/*` 全部改兼容跳转
|
||||
- `/tools/*` 全部改兼容跳转
|
||||
|
||||
结果:
|
||||
|
||||
- `/home` 成为唯一执行工作面
|
||||
|
||||
### Phase 4:删除重复执行页
|
||||
|
||||
目标:
|
||||
|
||||
- 删除各类工具执行页中的消息流、输入框、任务逻辑
|
||||
- 删除各类专员执行页中的聊天职责
|
||||
|
||||
结果:
|
||||
|
||||
- 页面树明显收缩
|
||||
- 状态源头回归统一
|
||||
|
||||
### Phase 5:命名与对象清洗
|
||||
|
||||
目标:
|
||||
|
||||
- 拆分专员 key 与工具 key 冲突
|
||||
- 清理旧命名
|
||||
- 清理遗留兼容逻辑
|
||||
|
||||
结果:
|
||||
|
||||
- 模型稳定
|
||||
- 后续功能可持续扩展
|
||||
|
||||
---
|
||||
|
||||
## 11. 禁止事项
|
||||
|
||||
从这份合同生效开始,以下做法视为逆行:
|
||||
|
||||
1. 再新增任何 `/tools/*` 执行页
|
||||
2. 再新增任何 `/apps/*` 执行页
|
||||
3. 在页面局部状态里偷偷维护“当前工具”
|
||||
4. 继续复用同一个 key 同时代表专员和工具
|
||||
5. 让当前对象由页面 `prefer` 或路由猜测,而不是由任务上下文决定
|
||||
6. 让右栏只支持专员,不支持工具
|
||||
|
||||
---
|
||||
|
||||
## 12. 最终产品语义
|
||||
|
||||
最终用户感知必须收敛为:
|
||||
|
||||
- 我在一个工作台里
|
||||
- 我当前正在处理一条任务
|
||||
- 这条任务挂了某个专员
|
||||
- 这条任务打开了若干工具
|
||||
- 我现在聚焦在某个对象上
|
||||
- 我可以启动、配置、关闭这些对象
|
||||
- 我不需要理解页面切换,只需要理解任务上下文
|
||||
|
||||
如果界面上任何一个交互让用户重新产生:
|
||||
|
||||
`我是不是又跳进了另一个工具页 / 专员页`
|
||||
|
||||
那就说明这次改造没有做完。
|
||||
@@ -0,0 +1,552 @@
|
||||
# 技能文件规范
|
||||
|
||||
> 落盘日期:2026-09-16
|
||||
> 状态:生效中
|
||||
> 作用:定义“每个技能在前端代码中应该以什么文件形式存在”
|
||||
> 关联文档:`AR05_Workbench_Architecture_Contract.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论
|
||||
|
||||
从本规范生效开始:
|
||||
|
||||
**技能不再以独立执行页面的形式存在。**
|
||||
|
||||
每个技能必须被建模为:
|
||||
|
||||
`定义文件 + 执行器文件 + 结果组件 + 可选扩展组件`
|
||||
|
||||
而不是:
|
||||
|
||||
`一个完整的 xxxPage.vue`
|
||||
|
||||
---
|
||||
|
||||
## 2. 标准目录
|
||||
|
||||
所有技能统一存放在:
|
||||
|
||||
`frontend/src/skills/`
|
||||
|
||||
目录结构固定为:
|
||||
|
||||
```text
|
||||
src/skills/
|
||||
registry/
|
||||
eai.ts
|
||||
custom.ts
|
||||
index.ts
|
||||
shared/
|
||||
types.ts
|
||||
schema.ts
|
||||
runtime.ts
|
||||
eai/
|
||||
smart-assistant/
|
||||
index.ts
|
||||
executor.ts
|
||||
ResultCard.vue
|
||||
document-translate/
|
||||
index.ts
|
||||
executor.ts
|
||||
ResultCard.vue
|
||||
copy-proofreading/
|
||||
index.ts
|
||||
executor.ts
|
||||
ResultCard.vue
|
||||
contract-review/
|
||||
index.ts
|
||||
executor.ts
|
||||
ResultCard.vue
|
||||
audio-transcribe/
|
||||
index.ts
|
||||
executor.ts
|
||||
ResultCard.vue
|
||||
batch-extract/
|
||||
index.ts
|
||||
executor.ts
|
||||
ResultCard.vue
|
||||
custom/
|
||||
adapters/
|
||||
normalize.ts
|
||||
executorFactory.ts
|
||||
```
|
||||
|
||||
强约束:
|
||||
|
||||
1. `eai/` 只放 EAI 官方内置技能
|
||||
2. `custom/` 不放每个用户技能的源码页面
|
||||
3. 用户自定义技能的实例数据应存后端,由前端运行时归一化
|
||||
4. 前端 repo 里只允许保留 `custom/adapters/*` 这类运行时适配代码
|
||||
|
||||
---
|
||||
|
||||
## 3. 技能来源必须分开
|
||||
|
||||
从本规范生效开始,技能必须强制区分来源:
|
||||
|
||||
- `source = 'eai'`
|
||||
- `source = 'custom'`
|
||||
|
||||
### 3.1 EAI 技能
|
||||
|
||||
定义:
|
||||
|
||||
- 平台内置
|
||||
- 由 EAI 官方提供
|
||||
- 随代码仓库交付
|
||||
- 放在 `src/skills/eai/`
|
||||
|
||||
### 3.2 用户自定义技能
|
||||
|
||||
定义:
|
||||
|
||||
- 由租户 / 用户 / 管理员创建
|
||||
- 不属于平台内置源码
|
||||
- 应以数据形式存储在后端
|
||||
- 由前端在运行时转换成统一 `SkillDefinition`
|
||||
|
||||
### 3.3 不允许混放
|
||||
|
||||
禁止以下做法:
|
||||
|
||||
1. 把用户技能和 EAI 技能放在同一层目录
|
||||
2. 给用户技能也手工创建一个 `src/skills/eai/*` 目录
|
||||
3. 把用户技能伪装成内置技能编号
|
||||
4. 让前端页面层自己判断“这是官方技能还是用户技能”
|
||||
|
||||
来源判断必须统一由 registry 和 definition 字段承担。
|
||||
|
||||
---
|
||||
|
||||
## 4. 每个工具允许的文件
|
||||
|
||||
每个 EAI 工具目录下只允许这 4 类文件:
|
||||
|
||||
### 4.1 `index.ts`
|
||||
|
||||
这是工具主定义文件,必须存在。
|
||||
|
||||
作用:
|
||||
|
||||
- 定义工具身份
|
||||
- 定义显示名称
|
||||
- 定义设置 schema
|
||||
- 定义开场提示
|
||||
- 绑定执行器
|
||||
- 绑定结果渲染组件
|
||||
|
||||
### 4.2 `executor.ts`
|
||||
|
||||
这是工具执行器,必须存在。
|
||||
|
||||
作用:
|
||||
|
||||
- 组装请求参数
|
||||
- 调用后端接口
|
||||
- 归一化响应结果
|
||||
|
||||
约束:
|
||||
|
||||
- 不允许依赖页面组件
|
||||
- 不允许写 DOM 逻辑
|
||||
- 不允许直接操作路由
|
||||
|
||||
### 4.3 `ResultCard.vue`
|
||||
|
||||
这是工具结果渲染组件,必须存在。
|
||||
|
||||
作用:
|
||||
|
||||
- 渲染该工具的结果卡片
|
||||
- 展示结构化结果
|
||||
- 展示摘要、状态、附加信息
|
||||
|
||||
约束:
|
||||
|
||||
- 这是局部结果组件,不是页面
|
||||
- 不允许包含整个聊天布局
|
||||
- 不允许自己持有输入框
|
||||
|
||||
### 4.4 `SettingsPanel.vue`
|
||||
|
||||
这是可选文件,只在 schema 驱动不够时允许出现。
|
||||
|
||||
作用:
|
||||
|
||||
- 处理复杂设置 UI
|
||||
|
||||
约束:
|
||||
|
||||
- 默认不创建
|
||||
- 只有通用 schema 无法表达时才允许新增
|
||||
|
||||
---
|
||||
|
||||
## 5. 编号与命名规范
|
||||
|
||||
每个工具必须同时拥有以下 4 个身份字段:
|
||||
|
||||
1. `id`
|
||||
2. `code`
|
||||
3. `key`
|
||||
4. `label`
|
||||
|
||||
四者职责不同,禁止混用。
|
||||
|
||||
### 5.1 `id`
|
||||
|
||||
`id` 是机器标识,必须全局唯一,且不可变。
|
||||
|
||||
格式固定为:
|
||||
|
||||
- EAI 技能:`eai.<skill-key>`
|
||||
- 用户技能:`custom.<owner-key>.<skill-key>`
|
||||
|
||||
示例:
|
||||
|
||||
- `eai.document-translate`
|
||||
- `eai.audio-transcribe`
|
||||
- `custom.acme.document-translate-pro`
|
||||
|
||||
规则:
|
||||
|
||||
1. 全小写
|
||||
2. 使用 `.` 做命名空间分隔
|
||||
3. 最后一段必须和 `skill-key` 一致
|
||||
4. 一经创建不得修改
|
||||
|
||||
### 5.2 `code`
|
||||
|
||||
`code` 是展示编号,给人看,用于列表、配置页、运营页、审计页。
|
||||
|
||||
格式固定为:
|
||||
|
||||
- EAI 技能:`EAI-T-001`
|
||||
- 用户技能:`CUS-T-001`
|
||||
|
||||
规则:
|
||||
|
||||
1. `EAI-T-xxx` 只保留给官方内置技能
|
||||
2. `CUS-T-xxx` 只保留给用户自定义技能
|
||||
3. `xxx` 为三位流水号,从 `001` 开始
|
||||
4. 用户技能的 `code` 允许在“当前租户 / 当前工作区”范围内顺序编号
|
||||
5. 全局唯一性由 `id` 保证,不由 `code` 保证
|
||||
|
||||
### 5.3 `key`
|
||||
|
||||
`key` 是前端目录名和查找键,必须使用 kebab-case。
|
||||
|
||||
示例:
|
||||
|
||||
- `document-translate`
|
||||
- `contract-review`
|
||||
- `batch-extract`
|
||||
|
||||
规则:
|
||||
|
||||
1. 只能包含小写字母、数字、中划线
|
||||
2. 不允许空格
|
||||
3. 不允许中文
|
||||
4. 必须与目录名一致
|
||||
|
||||
### 5.4 `label`
|
||||
|
||||
`label` 是用户可见名称,必须是中文产品名。
|
||||
|
||||
示例:
|
||||
|
||||
- `文档翻译`
|
||||
- `合同审查`
|
||||
- `批量提取`
|
||||
|
||||
规则:
|
||||
|
||||
1. 优先使用中文
|
||||
2. 不带技术实现词
|
||||
3. 不在名称里拼接编号
|
||||
4. 不在名称里拼接来源前缀
|
||||
|
||||
错误示例:
|
||||
|
||||
- `EAI-T-001 文档翻译`
|
||||
- `custom_contract_review`
|
||||
- `合同审查工具V2`
|
||||
|
||||
---
|
||||
|
||||
## 6. 每个技能必须导出的定义结构
|
||||
|
||||
每个技能的 `index.ts` 必须默认导出一个标准对象。
|
||||
|
||||
字段固定如下:
|
||||
|
||||
```ts
|
||||
export interface SkillDefinition {
|
||||
id: string
|
||||
code: string
|
||||
source: 'eai' | 'custom'
|
||||
key: string
|
||||
label: string
|
||||
kind: 'skill'
|
||||
icon: string
|
||||
description: string
|
||||
settings: SkillSettingSchema[]
|
||||
starterPrompts: string[]
|
||||
executor: SkillExecutor
|
||||
resultCard: Component
|
||||
}
|
||||
```
|
||||
|
||||
强约束:
|
||||
|
||||
1. `id` 必须全局唯一
|
||||
2. `code` 必须符合来源对应的编号前缀
|
||||
3. `source` 只能是 `eai` 或 `custom`
|
||||
4. `key` 必须与目录名一致
|
||||
5. `kind` 固定为 `'skill'`
|
||||
6. `settings` 必须是 schema 数据,不允许把设置 UI 直接写进定义文件
|
||||
7. `executor` 必须指向当前技能自己的 `executor.ts`
|
||||
8. `resultCard` 必须指向当前技能自己的 `ResultCard.vue`
|
||||
|
||||
---
|
||||
|
||||
## 7. 文件职责边界
|
||||
|
||||
### 7.1 `index.ts` 负责什么
|
||||
|
||||
只负责:
|
||||
|
||||
- 元数据
|
||||
- schema
|
||||
- 组件与执行器装配
|
||||
|
||||
不负责:
|
||||
|
||||
- 发请求
|
||||
- 维护输入状态
|
||||
- 渲染完整聊天界面
|
||||
|
||||
### 7.2 `executor.ts` 负责什么
|
||||
|
||||
只负责:
|
||||
|
||||
- 把任务上下文和设置值转换成请求
|
||||
- 调用后端
|
||||
- 返回标准结果对象
|
||||
|
||||
不负责:
|
||||
|
||||
- 决定页面跳转
|
||||
- 直接操作 store 里的 UI 状态
|
||||
- 渲染文本
|
||||
|
||||
### 7.3 `ResultCard.vue` 负责什么
|
||||
|
||||
只负责:
|
||||
|
||||
- 接收标准结果数据
|
||||
- 渲染结果
|
||||
|
||||
不负责:
|
||||
|
||||
- 调接口
|
||||
- 打开任务
|
||||
- 切换工具
|
||||
|
||||
---
|
||||
|
||||
## 8. 严格禁止的文件形式
|
||||
|
||||
从本规范生效开始,以下文件形式禁止继续新增:
|
||||
|
||||
1. `src/views/tools/*Page.vue` 作为工具执行页
|
||||
2. 每个工具单独复制一份 `ChatLayout`
|
||||
3. 每个工具单独复制一份 `ChatInputBar`
|
||||
4. 每个工具单独维护一份本地 `messages`
|
||||
5. 每个工具单独维护一份本地 `taskItems`
|
||||
6. 每个工具单独维护一份右栏面板
|
||||
7. 每个工具用独立路由页面表达“当前正在使用”
|
||||
|
||||
一句话:
|
||||
|
||||
**技能可以有自己的定义文件和局部组件,但不能再有自己的执行页面。**
|
||||
|
||||
---
|
||||
|
||||
## 9. 统一注册方式
|
||||
|
||||
技能注册必须按来源拆分:
|
||||
|
||||
- `src/skills/registry/eai.ts`
|
||||
- `src/skills/registry/custom.ts`
|
||||
- `src/skills/registry/index.ts`
|
||||
|
||||
注册形式固定为:
|
||||
|
||||
```ts
|
||||
// registry/eai.ts
|
||||
import smartAssistant from '../eai/smart-assistant'
|
||||
import documentTranslate from '../eai/document-translate'
|
||||
|
||||
export const eaiSkillRegistry = [
|
||||
smartAssistant,
|
||||
documentTranslate,
|
||||
]
|
||||
|
||||
// registry/custom.ts
|
||||
export async function loadCustomSkillRegistry() {
|
||||
return fetchCustomSkillsFromBackend()
|
||||
}
|
||||
|
||||
// registry/index.ts
|
||||
export async function loadSkillRegistry() {
|
||||
const customSkills = await loadCustomSkillRegistry()
|
||||
return [...eaiSkillRegistry, ...customSkills]
|
||||
}
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
1. EAI 工具只能从 `registry/eai.ts` 注册
|
||||
2. 用户工具只能从 `registry/custom.ts` 装载
|
||||
3. `registry/index.ts` 只做合并,不写业务逻辑
|
||||
4. 页面层不允许自己 import 某个工具目录
|
||||
5. 工作台只能通过统一 registry 查工具
|
||||
6. 页面层不允许自己判断来源并做分支
|
||||
7. 工具排序优先使用 `code` 和显式排序字段,不允许靠文件名碰运气
|
||||
|
||||
---
|
||||
|
||||
## 10. 工作台与工具的关系
|
||||
|
||||
Workbench 是唯一执行面。
|
||||
|
||||
因此:
|
||||
|
||||
- 输入框属于 Workbench
|
||||
- 当前对象 chip 属于 Workbench
|
||||
- 设置条属于 Workbench
|
||||
- 工作流 / 产物右栏属于 Workbench
|
||||
- 任务列表属于 Workbench
|
||||
|
||||
工具只提供:
|
||||
|
||||
- 自己是谁
|
||||
- 自己能做什么
|
||||
- 自己有哪些设置
|
||||
- 自己如何执行
|
||||
- 自己如何渲染结果
|
||||
|
||||
---
|
||||
|
||||
## 11. 文件名规范
|
||||
|
||||
### 11.1 工具目录名
|
||||
|
||||
必须使用 kebab-case:
|
||||
|
||||
- `document-translate`
|
||||
- `audio-transcribe`
|
||||
- `batch-extract`
|
||||
|
||||
### 11.2 文件名
|
||||
|
||||
固定如下:
|
||||
|
||||
- `index.ts`
|
||||
- `executor.ts`
|
||||
- `ResultCard.vue`
|
||||
- `SettingsPanel.vue`
|
||||
|
||||
禁止:
|
||||
|
||||
- `DocumentTranslatePage.vue`
|
||||
- `AudioToolPage.vue`
|
||||
- `TranslateWorkbench.vue`
|
||||
|
||||
### 11.3 组件名
|
||||
|
||||
工具局部组件必须使用 PascalCase:
|
||||
|
||||
- `ResultCard.vue`
|
||||
- `SettingsPanel.vue`
|
||||
- `ArtifactPreview.vue`
|
||||
|
||||
### 11.4 目录与 key 的关系
|
||||
|
||||
工具目录名必须与 `key` 一致:
|
||||
|
||||
- 目录:`document-translate`
|
||||
- key:`document-translate`
|
||||
|
||||
不允许目录名和 key 各写各的。
|
||||
|
||||
---
|
||||
|
||||
## 12. 迁移结果
|
||||
|
||||
`src/views/tools/*.vue` 旧执行页已经完成退出,当前状态如下:
|
||||
|
||||
### 已完成
|
||||
|
||||
- 旧技能执行路由已删除
|
||||
- `src/views/tools/*.vue` 中的执行页源码已删除
|
||||
- 技能配置与执行逻辑已开始收敛到 `src/skills/*`
|
||||
- `/home` 已成为唯一工作台执行入口
|
||||
|
||||
### 仍需继续推进
|
||||
|
||||
虽然旧页面已经删除,但下面几类资产还要继续补齐:
|
||||
|
||||
- 更完整的 `executor` 接线
|
||||
- 更统一的 `ResultCard` / `SettingsPanel` 规范
|
||||
- 用户自定义技能的后端配置接入
|
||||
- 对象实例化后的运行记录与产物呈现
|
||||
|
||||
---
|
||||
|
||||
## 13. 特殊情况处理
|
||||
|
||||
### 13.1 设置特别复杂的技能
|
||||
|
||||
如果某个技能的设置无法由通用 schema 表达,允许新增:
|
||||
|
||||
- `SettingsPanel.vue`
|
||||
|
||||
但仍然禁止:
|
||||
|
||||
- 为此恢复一个完整技能页
|
||||
|
||||
### 13.2 结果展示特别复杂的技能
|
||||
|
||||
如果 `ResultCard.vue` 不够,可以继续拆分局部组件,例如:
|
||||
|
||||
- `ResultSummary.vue`
|
||||
- `ArtifactPreview.vue`
|
||||
|
||||
但这些文件仍然必须放在该技能目录下,且都属于局部组件,不是页面。
|
||||
|
||||
---
|
||||
|
||||
## 14. 最终硬规范
|
||||
|
||||
从现在开始,前端对“技能”的唯一合法表达方式是:
|
||||
|
||||
EAI 技能:
|
||||
|
||||
`src/skills/eai/<skill-key>/index.ts`
|
||||
|
||||
用户技能:
|
||||
|
||||
不以源码页面形式存在,统一由后端配置记录 + `src/skills/custom/adapters/*` 运行时适配。
|
||||
|
||||
这是技能的主入口。
|
||||
|
||||
配套合法文件只有:
|
||||
|
||||
- `executor.ts`
|
||||
- `ResultCard.vue`
|
||||
- `SettingsPanel.vue`(可选)
|
||||
|
||||
除此之外,不再接受任何“每个工具一个执行页”的实现方式,也不接受把用户工具和 EAI 工具混放在同一来源目录里。
|
||||
@@ -0,0 +1,97 @@
|
||||
# 架构对齐确认与本轮修复范围
|
||||
|
||||
> 落盘日期:2026-09-16
|
||||
> 状态:本轮生效
|
||||
> 关联文档:
|
||||
> - `AR05_Workbench_Architecture_Contract.md`
|
||||
> - `../01_System_Overall/SY24_Platform_Architecture_Rethink.md`
|
||||
> - `AR06_Skill_Packaging_Specification.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. 本轮确认结论
|
||||
|
||||
当前前端已经出现两套并行模型:
|
||||
|
||||
1. `workerRuntime` 开始把 `currentSpecialistKey / currentSkillKey` 收进任务上下文
|
||||
2. 路由和多个入口仍在继续使用 `/apps/*`、`/tools/*` 当执行页
|
||||
|
||||
这两套模型继续并存,会持续制造以下问题:
|
||||
|
||||
- 同一个对象,既像“挂在任务上的对象”,又像“跳去一个页面”
|
||||
- 输入区已经开始对象化,但对象 chip 和首页卡片还在按旧路由跳转
|
||||
- 兼容路径不只是兼容,而是在继续承载真实业务
|
||||
|
||||
所以本轮先不扩技能复刻,先回到我们自己的架构,确认并修复这一层。
|
||||
|
||||
---
|
||||
|
||||
## 2. 已确认的主要偏差
|
||||
|
||||
### 2.1 执行入口没有收敛到 `/home`
|
||||
|
||||
当前代码中仍存在:
|
||||
|
||||
- `/apps/:key` 专员执行页
|
||||
- `/tools/:key` 工具执行页
|
||||
- `/report-gen` 这类独立工具页
|
||||
|
||||
这与“只保留一个 Workbench 执行面”的架构合同冲突。
|
||||
|
||||
### 2.2 启动对象的入口行为不一致
|
||||
|
||||
当前不同入口对“打开专员 / 工具”的处理不一致:
|
||||
|
||||
- `+` 菜单一部分已经开始写任务上下文
|
||||
- 首页卡片仍直接 `router.push(app.pageRoute)` 或使用业务对象旧入口字段
|
||||
- 市场页“打开工作区”仍直接进入旧路由
|
||||
- 当前对象 chip 仍会把工具跳到旧工具页
|
||||
|
||||
这会导致用户在不同入口触发同一对象时,落点完全不同。
|
||||
|
||||
### 2.3 旧执行路由仍残留在产品结构里
|
||||
|
||||
根据架构合同,`/apps/*`、`/tools/*` 应该退出执行结构。
|
||||
|
||||
此前前端中它们曾直接挂载为执行页:
|
||||
|
||||
- `BusinessAppPage.vue`
|
||||
- `DocumentTranslatePage.vue`
|
||||
- `CopyProofreadingPage.vue`
|
||||
- `ContractReviewPage.vue`
|
||||
- `AudioTranscribePage.vue`
|
||||
- `BatchExtractPage.vue`
|
||||
|
||||
以上旧执行页现已全部从前端仓库移除。
|
||||
|
||||
这会继续放大旧页面模型。
|
||||
|
||||
---
|
||||
|
||||
## 3. 本轮修复范围
|
||||
|
||||
本轮只修第一优先级:
|
||||
|
||||
1. 所有“打开专员 / 工具”的行为,统一回到 `/home`
|
||||
2. `/apps/*`、`/tools/*`、`/report-gen` 从路由中直接移除
|
||||
3. 所有对象启动动作只认新的工作台入口和任务上下文
|
||||
|
||||
---
|
||||
|
||||
## 4. 本轮暂不处理
|
||||
|
||||
以下问题已确认存在,但不在本轮一起动:
|
||||
|
||||
1. 后端 `task -> specialist_key` 仍未升级为更完整的 mounted objects 结构
|
||||
2. 后端专员数据结构命名已升级为 `object_entry_route`,并与普通页面导航 `page_route` 分离;旧 `route / entry_route` 已收缩为启动阶段的一次性数据库迁移逻辑,不再驻留在日常模型与接口中
|
||||
|
||||
---
|
||||
|
||||
## 5. 本轮达成标准
|
||||
|
||||
修完后,系统应满足:
|
||||
|
||||
1. 用户从 `+` 菜单、首页、市场页进入时,都会回到同一个 `/home`
|
||||
2. 当前专员 / 当前工具由任务上下文决定,而不是由页面路由决定
|
||||
3. `/apps/*`、`/tools/*`、`/report-gen` 不再作为前端执行入口存在
|
||||
4. 旧执行页源码文件已经从前端仓库移除
|
||||
@@ -0,0 +1,509 @@
|
||||
# AI 角色与工具统一交互设计
|
||||
|
||||
> 落盘日期:2026-09-16
|
||||
> 状态:**部分被取代的设计稿 —— 阅读前先看下面的「采纳与废弃」**
|
||||
|
||||
> ## ⚠️ 采纳与废弃(2026-09-17 补注)
|
||||
>
|
||||
> 本文结论不是「整体作废」,而是**一半采纳、一半废弃**。请按下表取用,**不要整篇照做**。
|
||||
>
|
||||
> ### 已采纳(现已是实现方向)
|
||||
>
|
||||
> | 本文结论 | 现落点 |
|
||||
> |----------|--------|
|
||||
> | 对象不跳页,都在同一工作面里挂载 | `AR05_Workbench_Architecture_Contract.md` |
|
||||
> | 专员 / 工具不应该是独立 Vue 页面 | 已实现:`views/workbench/` 无独立工具页 |
|
||||
> | `+` 菜单作为统一的对象选择入口 | 已实现:`components/chat/PlusMenu.vue` |
|
||||
> | 切换对象 = 更新任务上下文,不跳路由 | 已实现:`store/workerRuntime.js` |
|
||||
>
|
||||
> ### 已废弃(不要照做)
|
||||
>
|
||||
> | 本文结论 | 废弃原因 |
|
||||
> |----------|----------|
|
||||
> | 「**数字技术员**」作为第三类对象,与专员 / 工具并列(§2.1、§5.2) | `SY21` §2.2 已明确**不再把 `tool` 作为正式命名**,对内统一 `expert / skill / app`,对外统一「专家 + 技能」。**没有「技术员」这一类。** |
|
||||
> | 「通用助手 = 默认专员」这一等式(§5.4) | `SY23` 确认通用助手是**未挂专员时的兜底**,不是一种专员 |
|
||||
> | §14「后续如有实现与本稿冲突,**以本稿为准**」 | 该自我授权已失效。当前收口文档是 `SY21` / `SY22`,专员改造以 `SY23_Specialist_Rule_File_And_Skill_Binding_Plan.md` 为准 |
|
||||
>
|
||||
> 一句话:**「不跳页面」这个判断是对的、也已落地;「数字技术员」这个对象是新造的、已被否定。**
|
||||
|
||||
---
|
||||
|
||||
## 1. 结论先行
|
||||
|
||||
当前前端的核心问题,不是某几个页面细节做得不够像 WorkBuddy,而是**建模错了**:
|
||||
|
||||
- **数字专员**不应该是独立业务页面
|
||||
- **工具**也不应该是一组独立 Vue 页面
|
||||
- **对话主界面**才应该是唯一主工作面
|
||||
|
||||
新的统一模型应是:
|
||||
|
||||
- **通用助手** = 默认专员
|
||||
- **数字专员** = 多步任务编排者,类似企业里的项目经理
|
||||
- **数字技术员** = 单点技术能力执行者,可被专员调用
|
||||
- **工具** = 数字技术员的一种表现形式,不再等于页面
|
||||
|
||||
也就是说:
|
||||
|
||||
**前端不再是“切页面使用能力”,而是“在同一个对话工作面里切换当前挂载对象”。**
|
||||
|
||||
---
|
||||
|
||||
## 2. 统一对象模型
|
||||
|
||||
### 2.1 三类对象
|
||||
|
||||
| 类别 | 本质 | 典型职责 | 是否有独立完整页面 |
|
||||
|------|------|----------|--------------------|
|
||||
| 通用助手 | 默认专员 | 通用问答、兜底处理、把任务转交给更合适对象 | 否 |
|
||||
| 数字专员 | 编排型角色 | 拆任务、排步骤、调用技术员、汇总产物 | 否 |
|
||||
| 数字技术员 | 执行型角色 | 文档翻译、语音转写、批量提取、合同条款分析等单点能力 | 否 |
|
||||
|
||||
### 2.2 用户感知
|
||||
|
||||
对用户来说,不再是:
|
||||
|
||||
`我正在某个工具页里`
|
||||
|
||||
而是:
|
||||
|
||||
`我正在一条任务里,这条任务当前挂了哪个专员 / 哪个技术员`
|
||||
|
||||
### 2.3 当前对象的展示规则
|
||||
|
||||
无论选中的是专员还是技术员,都应该出现在输入框左下区域:
|
||||
|
||||
`[+] [当前对象 chip]`
|
||||
|
||||
其中:
|
||||
|
||||
- 选了专员,显示专员 chip
|
||||
- 选了工具,显示工具 chip
|
||||
- 两者都没有时,默认显示“通用助手”
|
||||
- 输入区显性对象始终互斥:`+` 右边一次只显示一个当前对象
|
||||
- 专员内部调用技术员属于执行链,不升格为第二个显性 chip
|
||||
|
||||
这一点非常关键,因为它把“当前上下文”从隐藏状态变成了**持续可见状态**。
|
||||
|
||||
---
|
||||
|
||||
## 3. 为什么原来的工具页架构是错的
|
||||
|
||||
### 3.1 错误的建模方式
|
||||
|
||||
原来的建模是:
|
||||
|
||||
`一个工具 = 一个完整页面`
|
||||
|
||||
例如以前会把工具理解成这些独立页:
|
||||
|
||||
- `/tools/document-translate`
|
||||
- `/tools/copy-proofreading`
|
||||
- `/tools/audio-transcribe`
|
||||
- `/tools/batch-extract`
|
||||
|
||||
当前这些独立执行页已经退出,工具统一通过 `/home` 工作台挂载。
|
||||
|
||||
这会导致前端天然把“工具”理解成“去一个地方”。
|
||||
|
||||
### 3.2 实际上工具不需要页面承载
|
||||
|
||||
工具真正有差异的地方只有 3 块:
|
||||
|
||||
1. **输入要求**
|
||||
2. **设置条**
|
||||
3. **右栏中的工作流与产物**
|
||||
|
||||
除此之外,绝大多数前端骨架都是一样的:
|
||||
|
||||
- 还是同一个聊天区
|
||||
- 还是同一个输入框
|
||||
- 还是同一个附件入口
|
||||
- 还是同一个右栏容器
|
||||
|
||||
所以把每个工具做成完整页面,会产生大量无意义分叉:
|
||||
|
||||
- 路由分叉
|
||||
- 状态分叉
|
||||
- 组件分叉
|
||||
- 页面骨架重复
|
||||
|
||||
### 3.3 正确的建模方式
|
||||
|
||||
应该改成:
|
||||
|
||||
`一个工具 = 一份能力定义 + 一份设置定义 + 一份工作流定义`
|
||||
|
||||
而不是:
|
||||
|
||||
`一个工具 = 一个完整页面`
|
||||
|
||||
---
|
||||
|
||||
## 4. 新的前端总架构
|
||||
|
||||
### 4.1 唯一主工作面
|
||||
|
||||
系统只保留一个主交互工作面:
|
||||
|
||||
`Chat Workspace`
|
||||
|
||||
结构如下:
|
||||
|
||||
```text
|
||||
┌────────────────────────────────────────────────────────────┐
|
||||
│ 左侧导航 │
|
||||
├────────────────────────────────────────────────────────────┤
|
||||
│ 中间:对话主画面 │ 右侧:上下文面板 │
|
||||
│ │ │
|
||||
│ 消息流 │ [工作流] [产物] │
|
||||
│ │ │
|
||||
│ │ 当前对象的执行进度 │
|
||||
│ │ 当前对象的产物列表 │
|
||||
├────────────────────────────────────────────────────────────┤
|
||||
│ [+] [当前对象 chip] [附件] [输入框................] [发送] │
|
||||
└────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 4.2 对象切换方式
|
||||
|
||||
所有对象的选择,都从 `+` 打开:
|
||||
|
||||
- 模式:快速 / 专家
|
||||
- 专员
|
||||
- 技术员
|
||||
- 连接器或其它补充入口
|
||||
|
||||
选择结果不再跳页面,而是**更新当前任务上下文**。
|
||||
|
||||
### 4.3 页面跳转原则
|
||||
|
||||
默认原则:
|
||||
|
||||
- **切换对象,不跳页**
|
||||
- **切换能力,不跳页**
|
||||
- **切换任务,才可能切上下文**
|
||||
|
||||
只有管理、配置、市场、控制台这类后台页面,才保留独立路由。
|
||||
|
||||
---
|
||||
|
||||
## 5. 专员与技术员的职责分层
|
||||
|
||||
### 5.1 数字专员
|
||||
|
||||
数字专员对应企业中的项目经理,负责:
|
||||
|
||||
- 接收用户目标
|
||||
- 把目标拆成多步任务
|
||||
- 决定调用哪些技术员
|
||||
- 汇总技术员的结果
|
||||
- 输出最终交付物
|
||||
|
||||
### 5.2 数字技术员
|
||||
|
||||
数字技术员对应企业中的专业执行者,负责:
|
||||
|
||||
- 完成单个技术动作
|
||||
- 处理特定格式输入
|
||||
- 产出特定类型结果
|
||||
- 把结果返回给专员或直接返回给用户
|
||||
|
||||
### 5.3 调用关系
|
||||
|
||||
```text
|
||||
用户
|
||||
→ 数字专员
|
||||
→ 调用数字技术员 A
|
||||
→ 调用数字技术员 B
|
||||
→ 调用数字技术员 C
|
||||
→ 汇总结果
|
||||
→ 输出最终产物
|
||||
```
|
||||
|
||||
### 5.4 通用助手的定位
|
||||
|
||||
通用助手不是单独体系,而是:
|
||||
|
||||
- 默认专员
|
||||
- 未选择任何专员或技术员时的兜底对象
|
||||
- 帮用户判断应不应该切到某个专员或技术员
|
||||
|
||||
---
|
||||
|
||||
## 6. 工具的新定义
|
||||
|
||||
### 6.1 工具不再是页面
|
||||
|
||||
未来的“工具”只是技术员目录里的一个对象类别。
|
||||
|
||||
例如:
|
||||
|
||||
| 旧叫法 | 新理解 |
|
||||
|--------|--------|
|
||||
| 文档翻译工具 | 文档翻译技术员 |
|
||||
| 文案校对工具 | 文案校对技术员 |
|
||||
| 语音转写工具 | 语音转写技术员 |
|
||||
| 批量提取工具 | 批量提取技术员 |
|
||||
| 合同审查工具 | 合同条款分析技术员或合同审查专员的下游技术员 |
|
||||
| 报告生成工具 | 报告生成技术员 |
|
||||
|
||||
### 6.2 工具在前端的可变部分
|
||||
|
||||
一个技术员/工具在前端只允许有 4 类差异:
|
||||
|
||||
1. **对象 chip**
|
||||
2. **输入提示与输入校验**
|
||||
3. **设置条**
|
||||
4. **右栏工作流与产物**
|
||||
|
||||
除此之外,不再允许复制一整页聊天页。
|
||||
|
||||
### 6.3 工具定义应沉淀为 schema
|
||||
|
||||
每个技术员建议定义如下结构:
|
||||
|
||||
```ts
|
||||
type TechnicianDefinition = {
|
||||
key: string
|
||||
label: string
|
||||
summary: string
|
||||
inputSchema: object
|
||||
settingsSchema: object[]
|
||||
workflowSchema: object[]
|
||||
artifactSchema: object[]
|
||||
emptyState?: {
|
||||
title: string
|
||||
description: string
|
||||
presets?: string[]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
也就是说,新增长一个工具,不应该先想“新建哪个 Vue 文件”,而应该先想“补哪份定义”。
|
||||
|
||||
---
|
||||
|
||||
## 7. 统一 UI 规则
|
||||
|
||||
### 7.1 输入区
|
||||
|
||||
输入区固定包含:
|
||||
|
||||
- `+`:选择模式 / 专员 / 技术员
|
||||
- `当前对象 chip`
|
||||
- `附件`
|
||||
- `输入框`
|
||||
- `发送`
|
||||
|
||||
### 7.2 当前对象 chip
|
||||
|
||||
当前对象 chip 的规则:
|
||||
|
||||
- 位置固定在 `+` 右边
|
||||
- 支持专员与技术员两种样式,但结构统一
|
||||
- 只负责展示“当前挂了谁”
|
||||
- 一次只展示一个当前对象,不并排显示“专员 + 技术员”
|
||||
- 点击 chip 可展开对象详情,或跳到对应配置页
|
||||
|
||||
### 7.3 设置条
|
||||
|
||||
设置条是工具差异的第一承载位。
|
||||
|
||||
原则:
|
||||
|
||||
- 只在当前对象有设置时显示
|
||||
- 位置在消息列表顶部
|
||||
- 形式统一为一条 sticky 条
|
||||
- 设置变更默认从**下一条消息**开始生效
|
||||
- 当前对象是专员时,默认不再额外显示技能设置条
|
||||
|
||||
设置条里的内容由对象定义驱动,而不是写死在某个页面里。
|
||||
|
||||
### 7.4 右栏
|
||||
|
||||
右栏固定 2 个 tab:
|
||||
|
||||
- **工作流**
|
||||
- **产物**
|
||||
|
||||
#### 工作流 tab
|
||||
|
||||
显示当前对象的:
|
||||
|
||||
- 执行步骤
|
||||
- 进度状态
|
||||
- 当前节点
|
||||
- 子任务或检查点
|
||||
|
||||
#### 产物 tab
|
||||
|
||||
显示当前对象的:
|
||||
|
||||
- 文件产物
|
||||
- 结构化结果
|
||||
- 中间输出
|
||||
- 状态标签
|
||||
|
||||
### 7.5 空态
|
||||
|
||||
空态不再按“工具页”设计,而按“当前对象”设计:
|
||||
|
||||
- 默认通用助手有自己的门厅
|
||||
- 技术员被选中但还没发送第一条消息时,显示该技术员自己的空态说明
|
||||
- 专员被选中但还没发送第一条消息时,显示该专员的工作流模板预览
|
||||
|
||||
---
|
||||
|
||||
## 8. 导航的重新定位
|
||||
|
||||
### 8.1 一级导航不再承担“使用工具”的职责
|
||||
|
||||
一级导航中的:
|
||||
|
||||
`专员 / 工具 / 连接器`
|
||||
|
||||
应该只承担**浏览配置与管理入口**的职责,而不是使用入口。
|
||||
|
||||
### 8.2 使用入口只有一个
|
||||
|
||||
真正的使用入口应该只有:
|
||||
|
||||
- `新建任务`
|
||||
- `打开已有任务`
|
||||
|
||||
进入任务后,一切对象切换都在对话区完成。
|
||||
|
||||
### 8.3 目录页的意义
|
||||
|
||||
目录页只做这些事:
|
||||
|
||||
- 浏览有哪些专员
|
||||
- 浏览有哪些技术员
|
||||
- 浏览有哪些连接器
|
||||
- 查看其配置摘要
|
||||
- 进入配置详情
|
||||
|
||||
而不是“点卡片后进入某个独立工具页”。
|
||||
|
||||
---
|
||||
|
||||
## 9. 现有代码应如何收敛
|
||||
|
||||
### 9.1 应保留的骨架
|
||||
|
||||
这些方向是对的,应保留:
|
||||
|
||||
- `ChatLayout`
|
||||
- `ChatInputBar`
|
||||
- `PlusMenu`
|
||||
- `SkillStrip`
|
||||
- 右栏 `SpecialistPanel` 的工作流 / 产物思路
|
||||
- “新建任务”作为唯一对话起点
|
||||
|
||||
### 9.2 应逐步废弃的结构
|
||||
|
||||
这些应视为过渡结构:
|
||||
|
||||
- 每个工具一张独立完整 Vue 页
|
||||
- 每个专员一个独立业务工作台页
|
||||
- 通过 object entry 切工具
|
||||
- 通过 object entry 切专员执行面
|
||||
|
||||
### 9.3 收敛目标
|
||||
|
||||
最终应收成:
|
||||
|
||||
| 层级 | 目标 |
|
||||
|------|------|
|
||||
| 页面层 | 一个主对话工作面 + 少量管理页 |
|
||||
| 组件层 | 一套通用聊天骨架 + 一套右栏骨架 |
|
||||
| 配置层 | 专员定义 / 技术员定义 / 工作流定义 / 设置定义 |
|
||||
| 数据层 | 当前任务挂载哪个对象,由任务状态驱动 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 重构原则清单
|
||||
|
||||
1. **页面不是能力,页面只是容器。**
|
||||
2. **能力切换不应导致页面跳转。**
|
||||
3. **当前上下文必须持续可见。**
|
||||
4. **专员与技术员共享同一套交互语言。**
|
||||
5. **工具差异只放在设置条、输入要求、工作流、产物。**
|
||||
6. **新增能力优先补 schema,不优先建新页面。**
|
||||
7. **导航页负责浏览与管理,不负责承载使用流。**
|
||||
8. **任务是主线,对象是挂件。**
|
||||
9. **右栏始终是执行透明化窗口。**
|
||||
10. **默认入口只有一个:对话。**
|
||||
|
||||
---
|
||||
|
||||
## 11. 前端收敛方案
|
||||
|
||||
### Phase 1:先统一心智
|
||||
|
||||
- 把“工具”统一重新命名为“数字技术员”或在内部按技术员建模
|
||||
- 明确通用助手 = 默认专员
|
||||
- 明确 object entry 不再代表能力本体
|
||||
|
||||
### Phase 2:统一输入区
|
||||
|
||||
- 在 `ChatInputBar` 中把当前对象 chip 收成标准能力
|
||||
- 专员 chip 与技术员 chip 使用统一插槽或统一组件
|
||||
- `+` 只负责选对象,不再负责跳到独立工具页
|
||||
|
||||
### Phase 3:统一设置条
|
||||
|
||||
- 把各工具页差异抽到 `settingsSchema`
|
||||
- `SkillStrip` 改成真正的对象驱动渲染
|
||||
- 设置条与当前对象强绑定,不再与路由强绑定
|
||||
|
||||
### Phase 4:统一右栏
|
||||
|
||||
- 右栏根据当前对象的 `workflowSchema` 和 `artifactSchema` 渲染
|
||||
- 专员右栏强调多步编排
|
||||
- 技术员右栏强调执行步骤
|
||||
|
||||
### Phase 5:清退独立工具页
|
||||
|
||||
- 保留旧工具页一段时间做兼容
|
||||
- 新能力一律不再新建完整工具页
|
||||
- 旧工具页逐步收敛为配置详情页或兼容跳板页
|
||||
|
||||
---
|
||||
|
||||
## 12. 对当前项目最重要的影响
|
||||
|
||||
这次不是小修,而是会改变整个前端边界:
|
||||
|
||||
- `availableSkills` 不再等于“可跳转的页面列表”
|
||||
- `businessApps` 不再等于“专员工作台页面列表”
|
||||
- 路由将从“能力入口”退回成“管理入口 / 兼容入口”
|
||||
- 真正的执行入口会统一收敛到任务对话面
|
||||
|
||||
换句话说:
|
||||
|
||||
**我们不再做“很多个 AI 页面”,而是做“一个任务工作面,里面动态挂很多 AI 对象”。**
|
||||
|
||||
---
|
||||
|
||||
## 13. 未决问题
|
||||
|
||||
1. 对外文案最终叫“工具”还是“数字技术员”,是否区分用户可见名和内部模型名
|
||||
2. 一个任务内部可以有多个技术员执行记录,但输入区始终只显示一个当前对象
|
||||
3. 专员调用技术员时,只在右栏和执行链里显示下游执行,不在输入区显性双挂
|
||||
4. 旧工具页是否全部保留兼容路由,还是只保留极少数重度场景
|
||||
5. 目录页中的“浏览配置”应展示到什么深度,是否允许直接预览 workflow schema
|
||||
|
||||
---
|
||||
|
||||
## 14. 本稿的用途
|
||||
|
||||
这份文档用于后续所有相关改造的判断标准:
|
||||
|
||||
- 评估某个页面要不要保留
|
||||
- 判断某个新能力该不该新建页面
|
||||
- 判断当前对象该不该在输入区可见
|
||||
- 判断导航页与使用页的边界
|
||||
|
||||
后续如有实现与本稿冲突,以本稿为准,再逐项修订。
|
||||
@@ -3,7 +3,10 @@
|
||||
> **命名规则:** `AR{NN}_{描述}.md`
|
||||
> **用途:** 后端架构、前端架构、数据库架构、部署架构
|
||||
>
|
||||
> **⚠️ 本目录 AR 文档为 V1.1 设计期历史快照。** 当前实现已重写为 **Go + Gin + GORM + MySQL 8.0 + FAISS**,以 `docs/changelog.md`、`docs/db_schema.md`、`docs/deploy.md` 为准。
|
||||
> **⚠️ `AR01`–`AR04` 为 V1.1 设计期历史快照。** 当前实现已重写为 **Go + Gin + GORM + SQLite + Go 原生 brute-force 向量检索**,以 `docs/changelog.md`、`docs/db_schema.md`、`docs/deploy.md` 为准。
|
||||
> `AR05`–`AR08` 是 2026-09-16 / 17 的工作台设计稿,**不属于 V1.1 快照**,其中 `AR08` 为部分被取代稿,取用前先读其文首补注。
|
||||
> 当前产品导航与工作台口径,请以 `docs/01_System_Overall/SY22_Role_Skill_App_Unified_Task_Architecture.md` 为准:
|
||||
> `新建任务 / 项目 / 专员·技能·APP·连接器 / 长程APP / 知识库 / 后台管理 / 我的`
|
||||
|
||||
## 文件清单
|
||||
|
||||
@@ -12,5 +15,9 @@
|
||||
| `README.md` | 本索引文件 |
|
||||
| `AR01_Backend_Arch.md` | 后端架构(V1.1 FastAPI 快照;现为 Go + Gin + GORM) |
|
||||
| `AR02_Frontend_Arch.md` | 前端架构(Vue3 + Element Plus 三栏布局) |
|
||||
| `AR03_Database_Arch.md` | 数据库架构(MySQL 8.0 + FAISS 向量检索) |
|
||||
| `AR03_Database_Arch.md` | 数据库架构(SQLite 单文件 + Go 原生向量检索) |
|
||||
| `AR04_Deploy_Arch.md` | 部署架构(V1.1 Docker 快照;现为单二进制 + systemd) |
|
||||
| `AR05_Workbench_Architecture_Contract.md` | 数字员工 Workbench 架构合同(任务为中心、对象挂载到任务,前端重构强约束) |
|
||||
| `AR06_Skill_Packaging_Specification.md` | 技能文件规范(技能 = 定义文件 + 执行器 + 结果组件,不以独立页面存在) |
|
||||
| `AR07_Architecture_Alignment_Audit.md` | 架构对齐确认与本轮修复范围(收敛两套并行模型的确认记录) |
|
||||
| `AR08_Role_Interaction_Design.md` | AI 角色与工具统一交互设计(**部分被取代**:不跳页结论已采纳,「数字技术员」对象已废弃,见文首补注) |
|
||||
|
||||
@@ -0,0 +1,447 @@
|
||||
# 对标云趣的办公平台追平路线图
|
||||
|
||||
> 落盘日期:2026-09-17
|
||||
> 状态:产品追平路线稿
|
||||
> 目标:追平云趣类一站式 AI 平台的办公生产力能力,不追视觉创作与音视频创作能力
|
||||
> 关联文档:
|
||||
> - `../01_System_Overall/SY24_Platform_Architecture_Rethink.md`
|
||||
> - `../02_Architecture/AR05_Workbench_Architecture_Contract.md`
|
||||
> - `../02_Architecture/AR06_Skill_Packaging_Specification.md`
|
||||
> - `../02_Architecture/AR08_Role_Interaction_Design.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. 这份文档解决什么问题
|
||||
|
||||
当前平台已经形成了:
|
||||
|
||||
- `专家 + 技能 + APP + 统一任务工作台`
|
||||
- Chat-first 的执行工作台
|
||||
- 技能工作流与产物定义
|
||||
|
||||
但如果目标从“做出自己的平台节奏”升级为“追平云趣类产品”,那么后续建设就不能再零散补点功能,而需要一份明确的追平路线图。
|
||||
|
||||
这份文档用于统一三个判断:
|
||||
|
||||
1. 我们到底追平什么
|
||||
2. 我们明确不追什么
|
||||
3. 接下来应该按什么顺序补齐
|
||||
|
||||
---
|
||||
|
||||
## 2. 最终判断
|
||||
|
||||
我们的追平目标应明确定义为:
|
||||
|
||||
`追平云趣的一站式办公生产力平台能力,而不是追平其视觉创作站能力。`
|
||||
|
||||
换句话说,后续路线不以“AI 绘画、AI 视频、AI 音乐”作为主轴,而以:
|
||||
|
||||
- 文档交付
|
||||
- 长文生成
|
||||
- 结构化整理
|
||||
- 图文理解
|
||||
- 应用市场
|
||||
- 任务复用
|
||||
- 产物沉淀
|
||||
|
||||
作为主轴。
|
||||
|
||||
这是因为本平台当前最强的底层已经不是“模型调用入口”,而是:
|
||||
|
||||
- `任务容器`
|
||||
- `对象挂载`
|
||||
- `工作流`
|
||||
- `产物`
|
||||
- `右栏协作`
|
||||
|
||||
因此,最值得追平的是“办公执行平台感”,不是“多模态创作站感”。
|
||||
|
||||
---
|
||||
|
||||
## 3. 明确不做的能力边界
|
||||
|
||||
下列能力不纳入本轮追平范围:
|
||||
|
||||
### 3.1 视觉创作面
|
||||
|
||||
- `AI 绘画`
|
||||
- `混图`
|
||||
- `换脸`
|
||||
- `画廊广场`
|
||||
- `提示词库`
|
||||
|
||||
### 3.2 重创作面
|
||||
|
||||
- `AI 视频`
|
||||
- `AI 音乐`
|
||||
|
||||
### 3.3 结论
|
||||
|
||||
本轮追平不以“创作娱乐平台”作为目标,而以“办公与任务执行平台”作为目标。
|
||||
|
||||
---
|
||||
|
||||
## 4. 当前基础盘点
|
||||
|
||||
### 4.1 已有技能定义基础
|
||||
|
||||
当前 `frontend/src/config/workbench.js` 已经具备一批办公向技能定义:
|
||||
|
||||
- `通用助手`
|
||||
- `文档翻译`
|
||||
- `文案校对`
|
||||
- `语音转写`
|
||||
- `批量提取`
|
||||
- `合同审查`
|
||||
- `报告生成`
|
||||
|
||||
同时也已有一批场景型对象:
|
||||
|
||||
- `合同审查专员`
|
||||
- `售前方案专员`
|
||||
- `培训交付专员`
|
||||
- `知识运营专员`
|
||||
- `流程推进专员`
|
||||
- `报告生成专员`
|
||||
- `公众号助手`
|
||||
- `履约跟单专员`
|
||||
- `HR 邮件整理专员`
|
||||
- `简历处理专员`
|
||||
|
||||
### 4.2 已有执行层基础
|
||||
|
||||
当前执行层已有雏形,但总体偏薄:
|
||||
|
||||
- `src/skills/registry/eai.js` 中仅注册了少量 EAI 技能
|
||||
- `src/skills/shared/workbuddyReplicaCatalog.js` 中,`Excel` 已实现,`PPT` 仍处于待补阶段
|
||||
|
||||
### 4.3 当前真正的差距
|
||||
|
||||
当前最大的差距不是“没有专家或技能名”,而是:
|
||||
|
||||
1. 缺少更丰富的办公核心技能
|
||||
2. 缺少成体系的应用广场
|
||||
3. 缺少可沉淀、可复用、可回看的产物与任务系统
|
||||
4. 缺少从“定义层”走向“执行层”的完整技能落地
|
||||
|
||||
---
|
||||
|
||||
## 5. 追平对象的能力抽象
|
||||
|
||||
对标云趣时,应把它的能力拆成两类:
|
||||
|
||||
### 5.1 需要追平的能力
|
||||
|
||||
- `聊天对话 + 多模型`
|
||||
- `办公写作`
|
||||
- `长文创作`
|
||||
- `PPT 生成`
|
||||
- `思维导图`
|
||||
- `文本处理工具箱`
|
||||
- `图文理解 / OCR / 识图`
|
||||
- `应用广场`
|
||||
- `预设应用`
|
||||
- `任务与产物沉淀`
|
||||
- `文档中心 / 我的文档`
|
||||
|
||||
### 5.2 不需要追平的能力
|
||||
|
||||
- `AI 绘画`
|
||||
- `画同款`
|
||||
- `换脸`
|
||||
- `画廊广场`
|
||||
- `AI 视频`
|
||||
- `AI 音乐`
|
||||
|
||||
---
|
||||
|
||||
## 6. 差距清单
|
||||
|
||||
| 模块 | 我们当前状态 | 差距等级 | 是否进入追平范围 | 建议优先级 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 通用对话 | 已有 | 低 | 是 | P1 |
|
||||
| 文档翻译 | 已有 | 低 | 是 | P1 |
|
||||
| 文案校对 | 已有 | 低 | 是 | P1 |
|
||||
| 语音转写 | 已有 | 低 | 是 | P1 |
|
||||
| 批量提取 | 已有 | 低 | 是 | P1 |
|
||||
| 合同审查 | 已有 | 低 | 是 | P1 |
|
||||
| 报告生成 | 已有 | 低 | 是 | P1 |
|
||||
| PPT 生成 | 仅有待补线索,未形成正式技能 | 高 | 是 | P0 |
|
||||
| 思维导图 | 未形成正式技能 | 高 | 是 | P0 |
|
||||
| 长文创作 | 未形成正式技能 | 高 | 是 | P0 |
|
||||
| 文本处理工具箱 | 未形成产品化能力 | 高 | 是 | P0 |
|
||||
| OCR / 图文理解 | 未形成正式技能 | 高 | 是 | P0 |
|
||||
| 应用广场 | 有目录页基础,但应用体系不够厚 | 中高 | 是 | P1 |
|
||||
| 自定义应用 / 智能体 | 未形成用户可配置能力 | 高 | 是 | P1 |
|
||||
| 文档中心 / 产物中心 | 右栏已有产物基础,但缺独立中心 | 高 | 是 | P1 |
|
||||
| 任务结果复用 | 有任务记录,但复用链路偏弱 | 中高 | 是 | P1 |
|
||||
| 常用模型 / 模型收藏 | 有模型切换基础,但平台化程度不足 | 中 | 是 | P2 |
|
||||
| AI 绘画 | 未做 | 高 | 否 | 排除 |
|
||||
| 混图 / 换脸 | 未做 | 高 | 否 | 排除 |
|
||||
| 画廊 / 提示词库 | 未做 | 高 | 否 | 排除 |
|
||||
| AI 视频 | 未做 | 高 | 否 | 排除 |
|
||||
| AI 音乐 | 未做 | 高 | 否 | 排除 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 新版 Phase 2
|
||||
|
||||
## 7.1 目标
|
||||
|
||||
`把聊天助手升级成真正能交付文档结果的工作台。`
|
||||
|
||||
### 7.2 必做模块
|
||||
|
||||
1. `PPT 生成`
|
||||
2. `思维导图`
|
||||
3. `长文创作`
|
||||
4. `文本处理工具箱`
|
||||
5. `OCR / 图文理解`
|
||||
|
||||
### 7.3 各模块建议定义
|
||||
|
||||
#### A. PPT 生成
|
||||
|
||||
建议输入:
|
||||
|
||||
- 主题
|
||||
- 受众
|
||||
- 页数
|
||||
- 风格
|
||||
- 参考材料
|
||||
|
||||
建议输出:
|
||||
|
||||
- `演示大纲.md`
|
||||
- `演示文稿.pptx`
|
||||
- `演讲备注.md`
|
||||
|
||||
建议定位:
|
||||
|
||||
- 对标云趣/WorkBuddy 最容易被用户直接感知的高价值技能
|
||||
|
||||
#### B. 思维导图
|
||||
|
||||
建议输入:
|
||||
|
||||
- 一句话主题
|
||||
- 一段原始材料
|
||||
- 当前任务上下文
|
||||
|
||||
建议输出:
|
||||
|
||||
- `导图源文件.md`
|
||||
- `导图.svg`
|
||||
- `导图.png`
|
||||
|
||||
建议定位:
|
||||
|
||||
- 作为“任务结构化承接器”,紧贴通用助手与长文创作
|
||||
|
||||
#### C. 长文创作
|
||||
|
||||
不要只做“论文工具”,而应统一抽象为:
|
||||
|
||||
- `论文`
|
||||
- `方案`
|
||||
- `制度文档`
|
||||
- `公众号长文`
|
||||
- `小说`
|
||||
|
||||
建议输出:
|
||||
|
||||
- `大纲.md`
|
||||
- `正文.docx`
|
||||
- `摘要.md`
|
||||
|
||||
建议定位:
|
||||
|
||||
- 做成统一的长文引擎,而不是只做单一场景页面
|
||||
|
||||
#### D. 文本处理工具箱
|
||||
|
||||
建议能力:
|
||||
|
||||
- 去 Markdown 符号
|
||||
- 文本统计
|
||||
- 文本清洗
|
||||
- 标点与格式标准化
|
||||
- 批量整理
|
||||
|
||||
建议输出:
|
||||
|
||||
- `清洗后文本.md`
|
||||
- `统计结果.md`
|
||||
|
||||
建议定位:
|
||||
|
||||
- 高频轻工具
|
||||
- 直接提升整个平台的“顺手度”
|
||||
|
||||
#### E. OCR / 图文理解
|
||||
|
||||
建议能力:
|
||||
|
||||
- 图片转文字
|
||||
- 截图识别
|
||||
- 文档图片结构理解
|
||||
- 基于图片抽字段
|
||||
- 图中表格与信息识别
|
||||
|
||||
建议输出:
|
||||
|
||||
- `识别结果.md`
|
||||
- `结构化字段.xlsx`
|
||||
- `图文摘要.md`
|
||||
|
||||
建议定位:
|
||||
|
||||
- 是办公场景里比 AI 绘画更高频、更正经的能力
|
||||
|
||||
---
|
||||
|
||||
## 8. 新版 Phase 3
|
||||
|
||||
## 8.1 目标
|
||||
|
||||
`把“有几个技能”升级成“可持续使用的平台”。`
|
||||
|
||||
### 8.2 必做模块
|
||||
|
||||
1. `应用广场`
|
||||
2. `自定义应用 / 智能体配置`
|
||||
3. `文档中心 / 产物中心`
|
||||
4. `任务结果复用`
|
||||
5. `多模型切换与常用模型`
|
||||
6. `应用模板与场景预设`
|
||||
|
||||
### 8.3 重点解释
|
||||
|
||||
#### A. 应用广场
|
||||
|
||||
不是简单列对象目录,而是要形成:
|
||||
|
||||
- 分类浏览
|
||||
- 场景推荐
|
||||
- 模板复用
|
||||
- 已安装 / 待安装
|
||||
- 示例任务入口
|
||||
|
||||
#### B. 自定义应用 / 智能体配置
|
||||
|
||||
目标不是开放底层编排,而是先支持:
|
||||
|
||||
- 选择场景模板
|
||||
- 填写提示词与规则
|
||||
- 选择模型
|
||||
- 选择产物模板
|
||||
- 保存为可复用应用
|
||||
|
||||
#### C. 文档中心 / 产物中心
|
||||
|
||||
要从当前右栏产物区,升级为独立可管理资产:
|
||||
|
||||
- 最近产物
|
||||
- 收藏
|
||||
- 按任务查看
|
||||
- 按类型查看
|
||||
- 再次打开继续编辑
|
||||
|
||||
#### D. 任务结果复用
|
||||
|
||||
用户在平台里完成一次任务后,应支持:
|
||||
|
||||
- 复制为模板任务
|
||||
- 复用上一版产物
|
||||
- 继续生成新版本
|
||||
- 从旧任务快速新建相似任务
|
||||
|
||||
#### E. 多模型切换与常用模型
|
||||
|
||||
当前已经有模型切换基础,但还不够“平台”:
|
||||
|
||||
- 常用模型
|
||||
- 最近使用模型
|
||||
- 按任务记忆模型
|
||||
- 按应用推荐默认模型
|
||||
|
||||
#### F. 应用模板与场景预设
|
||||
|
||||
这是形成“平台感”的关键:
|
||||
|
||||
- 工作周报生成器
|
||||
- 会议纪要整理器
|
||||
- 招聘简历初筛器
|
||||
- 合同风险审查器
|
||||
- 培训归档助手
|
||||
- 公众号改写助手
|
||||
|
||||
这些不一定都要先做成重技能,但至少应形成可调用的预设对象体系。
|
||||
|
||||
---
|
||||
|
||||
## 9. 研发落地原则
|
||||
|
||||
后续每新增一个技能,不能只补定义层,必须同时补齐四件套:
|
||||
|
||||
1. `对象定义`
|
||||
2. `workflowSchema`
|
||||
3. `artifactSchema`
|
||||
4. `真实 executor / 结果卡片`
|
||||
|
||||
必要时补到六件套:
|
||||
|
||||
1. `对象定义`
|
||||
2. `执行器`
|
||||
3. `结果卡片`
|
||||
4. `历史记录`
|
||||
5. `产物管理`
|
||||
6. `模板预设`
|
||||
|
||||
如果只补:
|
||||
|
||||
- `workbench.js`
|
||||
- 右栏工作流
|
||||
- 目录页卡片
|
||||
|
||||
那会继续停留在“看起来有技能”,而不是“真的追平平台能力”。
|
||||
|
||||
---
|
||||
|
||||
## 10. 推荐开发顺序
|
||||
|
||||
### 10.1 第一批
|
||||
|
||||
1. `PPT 生成`
|
||||
2. `思维导图`
|
||||
3. `长文创作`
|
||||
4. `文本处理工具箱`
|
||||
5. `OCR / 图文理解`
|
||||
|
||||
### 10.2 第二批
|
||||
|
||||
1. `应用广场增强`
|
||||
2. `文档中心 / 产物中心`
|
||||
3. `任务结果复用`
|
||||
4. `自定义应用 / 智能体配置`
|
||||
|
||||
### 10.3 第三批
|
||||
|
||||
1. `模型收藏与常用模型`
|
||||
2. `应用模板体系`
|
||||
3. `场景预设批量铺开`
|
||||
|
||||
---
|
||||
|
||||
## 11. 一句话结论
|
||||
|
||||
本平台后续追平云趣的正确路线,不是:
|
||||
|
||||
`去补 AI 绘画、视频、音乐这些创作站能力`
|
||||
|
||||
而是:
|
||||
|
||||
`把办公技能做深,把应用市场做厚,把任务与产物体系做成真正的平台。`
|
||||
|
||||
这条路线更符合当前已有架构,也更符合“统一任务工作台”的产品气质。
|
||||
@@ -3,7 +3,12 @@
|
||||
> **命名规则:** `PL{NN}_{描述}.md`
|
||||
> **用途:** 前端视图设计、页面流程、组件设计
|
||||
>
|
||||
> **⚠️ 本目录 PL 文档为 V1 培训平台视图基线(首页/公司/产品/课程/考试 + 右侧 PathCoach)。** 平台升级后一级导航与工作台形态见 `SY03`(新导航)与 `SY17`(工作台线框图)。
|
||||
> **⚠️ `PL01`–`PL03` 为 V1 培训平台视图基线(首页/公司/产品/课程/考试 + 右侧 PathCoach)。**
|
||||
> `PL04` 是 2026-09-17 的办公平台追平路线稿,**不属于 V1 基线**。
|
||||
> 当前正式产品导航与工作台口径,请以 `SY22_Role_Skill_App_Unified_Task_Architecture.md` 为准:
|
||||
> `新建任务 / 项目 / 专员·技能·APP·连接器 / 长程APP / 知识库 / 后台管理 / 我的`
|
||||
>
|
||||
> 本目录主要保留 V1 页面设计资产;其中“首页 / 公司介绍培训 / 产品知识 / 课程 / 考试 / 知识管理 / 系统管理 / PathCoach”等名称,均不代表当前目标态导航。
|
||||
|
||||
## 文件清单
|
||||
|
||||
@@ -13,3 +18,4 @@
|
||||
| `PL01_Global_Layout.md` | 全局布局设计(顶部导航 + AI 侧栏) |
|
||||
| `PL02_Employee_Views.md` | 员工端视图(首页/公司/产品/课程/考试) |
|
||||
| `PL03_Admin_Views.md` | 管理员端视图(知识管理/系统管理) |
|
||||
| `PL04_YunQu_Parity_Roadmap.md` | 对标云趣的办公平台追平路线图(**非 V1 基线**,2026-09-17 路线稿:只追办公生产力,不追视觉与音视频创作) |
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
# WorkBuddy 技能 RPA 学习记录
|
||||
|
||||
> 落盘日期:2026-09-16
|
||||
> 状态:生效中
|
||||
> 目标:记录本次对 WorkBuddy 登录后页面的真实 RPA 学习过程,并沉淀为本项目可执行的复刻结论
|
||||
|
||||
---
|
||||
|
||||
## 1. 本次学习目标
|
||||
|
||||
本次不是看页面截图,也不是猜交互,而是直接在 WorkBuddy 登录后的真实产品里完成两条链路:
|
||||
|
||||
1. `专家目录 -> 召唤专家 -> 回到工作台 -> 创建任务`
|
||||
2. `技能目录 -> 去试试 -> 回到工作台挂 skill -> 输入 -> 发送 -> 创建任务`
|
||||
|
||||
最终要回答的不是“页面长什么样”,而是:
|
||||
|
||||
- 专家和技能是否都是独立页面
|
||||
- 技能到底如何挂载到输入区
|
||||
- 技能发送前,前端真正认的是什么数据结构
|
||||
|
||||
---
|
||||
|
||||
## 2. RPA 实操过程
|
||||
|
||||
### 2.1 专家链路
|
||||
|
||||
实际操作路径:
|
||||
|
||||
1. 打开 `专员·技能·APP·连接器 -> 专员`
|
||||
2. 进入专家详情弹层
|
||||
3. 点击 `召唤专家`
|
||||
4. 路由回到 `/app`
|
||||
5. 输入区显示专家身份
|
||||
6. 发送后创建真实任务页 `/app/task/:id`
|
||||
|
||||
结论:
|
||||
|
||||
- 专家不是独立执行页
|
||||
- 专家是“目录对象 -> 回工作台 -> 挂载到当前会话 -> 任务内继续对话”
|
||||
|
||||
### 2.2 技能链路
|
||||
|
||||
实际操作路径:
|
||||
|
||||
1. 打开 `专员·技能·APP·连接器 -> 技能`
|
||||
2. 进入技能详情
|
||||
3. 点击 `安装` / `试一试` / `去试试`
|
||||
4. 路由回到 `/app`
|
||||
5. 输入区内出现 skill chip
|
||||
6. 输入文本
|
||||
7. 点击发送
|
||||
8. 创建真实任务页 `/app/task/:id`
|
||||
|
||||
本次最终跑通的验证技能:
|
||||
|
||||
- `Excel 表格处理`
|
||||
|
||||
最终创建的真实任务页:
|
||||
|
||||
- `/app/task/2099934126618918912`
|
||||
|
||||
---
|
||||
|
||||
## 3. 关键踩坑与修复
|
||||
|
||||
### 3.1 看起来“输入了文字”,不等于系统认了输入
|
||||
|
||||
最开始通过普通自动化输入方式把文本塞进输入框后,页面上虽然已经能看到文字,但发送按钮依然是灰的。
|
||||
|
||||
原因不是发送按钮坏了,而是:
|
||||
|
||||
- DOM 里出现字符
|
||||
- 不等于 WorkBuddy 上层消息状态里已经存在可发送内容
|
||||
|
||||
### 3.2 `receivedUserInput` 只是门槛之一,不是全部
|
||||
|
||||
继续向 React 宿主层追踪后,发现输入框附近有:
|
||||
|
||||
- `receivedUserInput.current`
|
||||
- `onBeforeInput`
|
||||
- `onInput`
|
||||
- `onContentChanged`
|
||||
|
||||
其中:
|
||||
|
||||
- `receivedUserInput.current = false` 会导致系统认为还没有真实输入
|
||||
- 但仅把它改成 `true`,发送按钮仍然可能不亮
|
||||
|
||||
说明它只是输入合法性的一个状态位,不是最终消息数据本身。
|
||||
|
||||
### 3.3 真正控制发送按钮的是 content blocks
|
||||
|
||||
继续追到发送按钮控制组件后,发现它实际依赖的是:
|
||||
|
||||
- `value`
|
||||
- `onChange`
|
||||
- `checkSendDisabled`
|
||||
- `onSubmit`
|
||||
|
||||
当时上层状态里的 `value` 只有一项:
|
||||
|
||||
```js
|
||||
[
|
||||
{
|
||||
type: 'resource_link',
|
||||
name: 'Excel 表格处理',
|
||||
uri: 'skill://skill_2096528888507297792',
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
也就是说:
|
||||
|
||||
- skill chip 已经挂上了
|
||||
- 但文本内容没有进入同一个内容数组
|
||||
- 所以发送组件拿到的 `message / inputValue / editorValue` 仍然是 `null`
|
||||
|
||||
这就是发送按钮一直灰色的根因。
|
||||
|
||||
### 3.4 正确做法:补入正式文本块
|
||||
|
||||
最终按上层状态协议把文本作为正式内容块补进去:
|
||||
|
||||
```js
|
||||
[
|
||||
{
|
||||
type: 'resource_link',
|
||||
name: 'Excel 表格处理',
|
||||
uri: 'skill://skill_2096528888507297792',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
text: 'create a simple task table',
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
补完后立刻出现两个变化:
|
||||
|
||||
1. 输入区内容正常显示为 `skill chip + text`
|
||||
2. 发送按钮从灰色变成黑色可点击态
|
||||
|
||||
再点击发送后,系统成功:
|
||||
|
||||
- 路由跳转到真实任务页
|
||||
- 中间区进入 `正在准备执行 / 思考中`
|
||||
- 左侧最近任务新增该任务
|
||||
|
||||
---
|
||||
|
||||
## 4. 最终结论
|
||||
|
||||
### 4.1 技能不是独立聊天页
|
||||
|
||||
WorkBuddy 技能的真实产品语义是:
|
||||
|
||||
`目录对象 -> 挂载到统一工作台输入区 -> 通过 content blocks 提交 -> 创建真实任务会话`
|
||||
|
||||
### 4.2 WorkBuddy 输入区不是简单 textarea
|
||||
|
||||
它本质上是一个支持对象块的编辑器。
|
||||
|
||||
至少包含两类 block:
|
||||
|
||||
1. `resource_link`
|
||||
2. `text`
|
||||
|
||||
其中:
|
||||
|
||||
- `resource_link` 用来承载 skill chip / 引用对象
|
||||
- `text` 用来承载本次用户真正输入的指令文本
|
||||
|
||||
### 4.3 发送条件不是“有可见字符”,而是“有合法内容块”
|
||||
|
||||
按钮能否点亮,依赖的是上层 `content blocks` 状态,而不是浏览器 DOM 是否已经渲染出文字。
|
||||
|
||||
---
|
||||
|
||||
## 5. 对本项目的直接启发
|
||||
|
||||
这次学习得到的最重要复刻点,不是某个单独技能,而是这 4 条:
|
||||
|
||||
1. `+ 选择技能` 之后,技能要被挂进输入区,而不是直接跳走
|
||||
2. 输入区要支持 `skill chip + text` 的组合表达
|
||||
3. 发送逻辑要面向统一 `content blocks`,而不是只面向纯字符串
|
||||
4. 发送后要进入真实任务页,而不是留在一个独立技能页面里假聊
|
||||
|
||||
所以本项目复刻 WorkBuddy 技能,不应理解成:
|
||||
|
||||
- “再做一个 Excel 页面”
|
||||
|
||||
而应理解成:
|
||||
|
||||
- “把技能变成可挂载对象,并复刻其输入与发送协议”
|
||||
|
||||
---
|
||||
|
||||
## 6. 本项目的第一批落地动作
|
||||
|
||||
基于本次学习,当前仓库应新增三类能力:
|
||||
|
||||
### 6.1 学习记录层
|
||||
|
||||
- 保留本文档,作为后续继续复刻其他技能的依据
|
||||
|
||||
### 6.2 代码模块层
|
||||
|
||||
新增:
|
||||
|
||||
- `src/skills/shared/contentBlocks.*`
|
||||
- `src/skills/shared/workbuddyReplica.*`
|
||||
- `src/skills/registry/*`
|
||||
- `src/skills/eai/workbuddy-excel-skill/*`
|
||||
|
||||
### 6.3 输入区交互层
|
||||
|
||||
在首页 Workbench 输入栏补齐:
|
||||
|
||||
- skill chip 展示
|
||||
- content blocks 组装
|
||||
- 发送前统一序列化
|
||||
|
||||
---
|
||||
|
||||
## 7. 以后继续复刻其他技能时的标准动作
|
||||
|
||||
后续每复刻一个 WorkBuddy 技能,都按同一个模板走:
|
||||
|
||||
1. 记录原技能名称、分类、入口按钮文案
|
||||
2. 记录它回到工作台后挂载的对象形态
|
||||
3. 记录发送前需要的 block 结构
|
||||
4. 在 `src/skills/eai/<skill-key>/` 下新增:
|
||||
- `index.*`
|
||||
- `executor.*`
|
||||
- `ResultCard.vue`
|
||||
5. 通过统一 registry 注册
|
||||
6. 不再为它新增独立执行页面
|
||||
|
||||
---
|
||||
|
||||
## 8. 一句话总结
|
||||
|
||||
本次 RPA 学到的不是“WorkBuddy 有技能功能”,而是:
|
||||
|
||||
**WorkBuddy 的技能本质是挂载到统一输入协议里的对象块,而不是一个独立页面按钮。**
|
||||
@@ -0,0 +1,120 @@
|
||||
// ai_routes.go —— 「AI 模型路由」的查询接口(LLM provider / model 列表)。
|
||||
//
|
||||
// 注意与 router.go 区分:router.go 是 URL 路由注册(gin 的 r.GET/r.POST),
|
||||
// 本文件里的 "route" 一律指 AI 模型路由,与 HTTP 路由无关。
|
||||
package api
|
||||
|
||||
import (
|
||||
"eai_agentplatform/backend/internal/config"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// routeItem AI 模型路由摘要(返回给前端选择器)
|
||||
type routeItem struct {
|
||||
AIRouteID string `json:"ai_route_id"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
BaseURL string `json:"base_url"`
|
||||
Description string `json:"description"`
|
||||
ShortRouteName string `json:"short_route_name,omitempty"`
|
||||
ShortModelName string `json:"short_model_name,omitempty"`
|
||||
Healthy bool `json:"healthy"`
|
||||
Checked bool `json:"checked"`
|
||||
LatencyMs int64 `json:"latency_ms,omitempty"`
|
||||
LastCheckedAt string `json:"last_checked_at,omitempty"`
|
||||
LastError string `json:"last_error,omitempty"`
|
||||
ResolvedAIRouteID string `json:"resolved_ai_route_id,omitempty"`
|
||||
}
|
||||
|
||||
func toRouteItems(routes []*config.RouteConfig) []routeItem {
|
||||
items := make([]routeItem, 0, len(routes))
|
||||
for _, r := range routes {
|
||||
health, _ := config.GetRouteHealth(r.RouteID)
|
||||
items = append(items, routeItem{
|
||||
AIRouteID: r.RouteID,
|
||||
Provider: r.Provider,
|
||||
Model: r.Model,
|
||||
BaseURL: r.BaseURL,
|
||||
Description: r.Description,
|
||||
ShortRouteName: r.ShortRouteName,
|
||||
ShortModelName: r.ShortModelName,
|
||||
Healthy: health.Healthy,
|
||||
Checked: health.Checked,
|
||||
LatencyMs: health.LatencyMs,
|
||||
LastError: health.LastError,
|
||||
LastCheckedAt: formatCheckedAt(health.LastCheckedAt),
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func autoRouteItem(routeID string, category string) routeItem {
|
||||
item := routeItem{
|
||||
AIRouteID: routeID,
|
||||
Description: "自动选择当前最优可用模型",
|
||||
ShortRouteName: "自动",
|
||||
ShortModelName: "检测中",
|
||||
}
|
||||
|
||||
resolved, err := config.GetRoute(routeID)
|
||||
if err == nil && resolved != nil {
|
||||
health, _ := config.GetRouteHealth(resolved.RouteID)
|
||||
item.Provider = resolved.Provider
|
||||
item.Model = resolved.Model
|
||||
item.BaseURL = resolved.BaseURL
|
||||
item.ShortModelName = resolved.ShortModelName
|
||||
if item.ShortModelName == "" {
|
||||
item.ShortModelName = "优选"
|
||||
}
|
||||
item.ResolvedAIRouteID = resolved.RouteID
|
||||
item.Description = "自动选择当前最优可用模型"
|
||||
if resolved.Description != "" {
|
||||
item.Description += " · 当前 " + resolved.Description
|
||||
}
|
||||
item.Healthy = health.Healthy
|
||||
item.Checked = health.Checked
|
||||
item.LatencyMs = health.LatencyMs
|
||||
item.LastError = health.LastError
|
||||
item.LastCheckedAt = formatCheckedAt(health.LastCheckedAt)
|
||||
return item
|
||||
}
|
||||
|
||||
if category == "embed" {
|
||||
item.ShortModelName = "Emb"
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
func formatCheckedAt(t time.Time) string {
|
||||
if t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return t.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
// ListChatRoutes 返回可用 chat 路由列表(供前端选择器使用)
|
||||
func ListChatRoutes(c *gin.Context) {
|
||||
routes, err := config.GetRoutesByCategory("chat")
|
||||
if err != nil {
|
||||
web.Fail(c, web.NewLLMNotConfigured("路由加载失败: "+err.Error()))
|
||||
return
|
||||
}
|
||||
items := []routeItem{autoRouteItem(config.AutoChatRouteID, "chat")}
|
||||
items = append(items, toRouteItems(routes)...)
|
||||
web.OK(c, gin.H{"routes": items})
|
||||
}
|
||||
|
||||
// ListEmbedRoutes 返回可用 embedding 路由列表
|
||||
func ListEmbedRoutes(c *gin.Context) {
|
||||
routes, err := config.GetRoutesByCategory("embed")
|
||||
if err != nil {
|
||||
web.Fail(c, web.NewLLMNotConfigured("路由加载失败: "+err.Error()))
|
||||
return
|
||||
}
|
||||
items := []routeItem{autoRouteItem(config.AutoEmbedRouteID, "embed")}
|
||||
items = append(items, toRouteItems(routes)...)
|
||||
web.OK(c, gin.H{"routes": items})
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"eai_agentplatform/backend/internal/config"
|
||||
"eai_agentplatform/backend/internal/web"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// routeItem 路由摘要(返回给前端选择器)
|
||||
type routeItem struct {
|
||||
ID string `json:"id"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
BaseURL string `json:"base_url"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
func toRouteItems(routes []*config.RouteConfig) []routeItem {
|
||||
items := make([]routeItem, 0, len(routes))
|
||||
for _, r := range routes {
|
||||
items = append(items, routeItem{
|
||||
ID: r.RouteID,
|
||||
Provider: r.Provider,
|
||||
Model: r.Model,
|
||||
BaseURL: r.BaseURL,
|
||||
Description: r.Description,
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
// ListChatRoutes 返回可用 chat 路由列表(供前端选择器使用)
|
||||
func ListChatRoutes(c *gin.Context) {
|
||||
routes, err := config.GetRoutesByCategory("chat")
|
||||
if err != nil {
|
||||
web.Fail(c, web.NewLLMNotConfigured("路由加载失败: "+err.Error()))
|
||||
return
|
||||
}
|
||||
web.OK(c, gin.H{"routes": toRouteItems(routes)})
|
||||
}
|
||||
|
||||
// ListEmbedRoutes 返回可用 embedding 路由列表
|
||||
func ListEmbedRoutes(c *gin.Context) {
|
||||
routes, err := config.GetRoutesByCategory("embed")
|
||||
if err != nil {
|
||||
web.Fail(c, web.NewLLMNotConfigured("路由加载失败: "+err.Error()))
|
||||
return
|
||||
}
|
||||
web.OK(c, gin.H{"routes": toRouteItems(routes)})
|
||||
}
|
||||
Reference in New Issue
Block a user