refactor(team-communication): 移除配置表,规范改为 skill
团队角色/问题类型/冒泡路径不再用 DB 表 + CRUD,改为 team-communication skill (产线默认规范,项目可覆盖): - 删 pipeline_team_roles/pipeline_problem_types 两表 model+json+api dspy - 回退 pipeline_core/init.py CRUD 函数 + load_path.py 路段 - 重写 team-communication SKILL.md 为分层可覆盖规范文档
This commit is contained in:
parent
ff02533cb6
commit
17ad169829
@ -1,27 +0,0 @@
|
||||
{
|
||||
"tblname": "pipeline_problem_types",
|
||||
"title": "问题类型",
|
||||
"params": {
|
||||
"sortby": "name",
|
||||
"browserfields": {
|
||||
"exclouded": ["id", "description", "escalation_path"],
|
||||
"cwidth": {}
|
||||
},
|
||||
"editexclouded": [
|
||||
"id", "created_at"
|
||||
],
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('../api/pipeline_problem_types_create.dspy')}}",
|
||||
"update_data_url": "{{entire_url('../api/pipeline_problem_types_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('../api/pipeline_problem_types_delete.dspy')}}"
|
||||
},
|
||||
"confidential_fields": [],
|
||||
"subtables": [
|
||||
{
|
||||
"field": "pipeline_id",
|
||||
"title": "所属产线",
|
||||
"subtable": "pipelines"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
{
|
||||
"tblname": "pipeline_team_roles",
|
||||
"title": "团队角色",
|
||||
"params": {
|
||||
"sortby": "role_name",
|
||||
"browserfields": {
|
||||
"exclouded": ["id", "description"],
|
||||
"cwidth": {}
|
||||
},
|
||||
"editexclouded": [
|
||||
"id", "created_at"
|
||||
],
|
||||
"editable": {
|
||||
"new_data_url": "{{entire_url('../api/pipeline_team_roles_create.dspy')}}",
|
||||
"update_data_url": "{{entire_url('../api/pipeline_team_roles_update.dspy')}}",
|
||||
"delete_data_url": "{{entire_url('../api/pipeline_team_roles_delete.dspy')}}"
|
||||
},
|
||||
"confidential_fields": [],
|
||||
"subtables": [
|
||||
{
|
||||
"field": "pipeline_id",
|
||||
"title": "所属产线",
|
||||
"subtable": "pipelines"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"name": "pipeline_problem_types",
|
||||
"title": "问题类型表",
|
||||
"primary": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
"title": "id",
|
||||
"type": "str",
|
||||
"length": 32,
|
||||
"nullable": "no",
|
||||
"uitype": "hidden"
|
||||
},
|
||||
{
|
||||
"name": "pipeline_id",
|
||||
"title": "所属产线",
|
||||
"type": "str",
|
||||
"length": 32,
|
||||
"nullable": "no",
|
||||
"uitype": "select"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"title": "问题类型标识",
|
||||
"type": "str",
|
||||
"length": 50,
|
||||
"nullable": "no",
|
||||
"uitype": "text"
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"title": "显示名",
|
||||
"type": "str",
|
||||
"length": 100,
|
||||
"uitype": "text"
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"title": "说明",
|
||||
"type": "text",
|
||||
"uitype": "textarea"
|
||||
},
|
||||
{
|
||||
"name": "escalation_path",
|
||||
"title": "冒泡路径(JSON角色数组,如[\"main_agent\",\"customer\"])",
|
||||
"type": "text",
|
||||
"uitype": "textarea"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"title": "创建时间",
|
||||
"type": "timestamp",
|
||||
"uitype": "timestamp"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
{
|
||||
"name": "idx_problemtype_pipeline",
|
||||
"idxtype": "index",
|
||||
"idxfields": [
|
||||
"pipeline_id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "idx_problemtype_name",
|
||||
"idxtype": "unique",
|
||||
"idxfields": [
|
||||
"pipeline_id",
|
||||
"name"
|
||||
]
|
||||
}
|
||||
],
|
||||
"codes": [
|
||||
{
|
||||
"field": "pipeline_id",
|
||||
"table": "pipelines",
|
||||
"valuefield": "id",
|
||||
"textfield": "name"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
{
|
||||
"summary": [
|
||||
{
|
||||
"name": "pipeline_team_roles",
|
||||
"title": "团队角色表",
|
||||
"primary": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"name": "id",
|
||||
"title": "id",
|
||||
"type": "str",
|
||||
"length": 32,
|
||||
"nullable": "no",
|
||||
"uitype": "hidden"
|
||||
},
|
||||
{
|
||||
"name": "pipeline_id",
|
||||
"title": "所属产线",
|
||||
"type": "str",
|
||||
"length": 32,
|
||||
"nullable": "no",
|
||||
"uitype": "select"
|
||||
},
|
||||
{
|
||||
"name": "role_name",
|
||||
"title": "角色标识",
|
||||
"type": "str",
|
||||
"length": 50,
|
||||
"nullable": "no",
|
||||
"uitype": "text"
|
||||
},
|
||||
{
|
||||
"name": "agentid",
|
||||
"title": "Agent标识(同角色多agent区分,人可空)",
|
||||
"type": "str",
|
||||
"length": 64,
|
||||
"nullable": "yes",
|
||||
"uitype": "text"
|
||||
},
|
||||
{
|
||||
"name": "role_type",
|
||||
"title": "角色类型",
|
||||
"type": "str",
|
||||
"length": 20,
|
||||
"nullable": "no",
|
||||
"default": "agent",
|
||||
"uitype": "select"
|
||||
},
|
||||
{
|
||||
"name": "display_name",
|
||||
"title": "显示名",
|
||||
"type": "str",
|
||||
"length": 100,
|
||||
"uitype": "text"
|
||||
},
|
||||
{
|
||||
"name": "description",
|
||||
"title": "职责说明",
|
||||
"type": "text",
|
||||
"uitype": "textarea"
|
||||
},
|
||||
{
|
||||
"name": "created_at",
|
||||
"title": "创建时间",
|
||||
"type": "timestamp",
|
||||
"uitype": "timestamp"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
{
|
||||
"name": "idx_teamrole_pipeline",
|
||||
"idxtype": "index",
|
||||
"idxfields": [
|
||||
"pipeline_id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "idx_teamrole_name",
|
||||
"idxtype": "unique",
|
||||
"idxfields": [
|
||||
"pipeline_id",
|
||||
"role_name",
|
||||
"agentid"
|
||||
]
|
||||
}
|
||||
],
|
||||
"codes": [
|
||||
{
|
||||
"field": "pipeline_id",
|
||||
"table": "pipelines",
|
||||
"valuefield": "id",
|
||||
"textfield": "name"
|
||||
},
|
||||
{
|
||||
"field": "role_type",
|
||||
"table": "appcodes_kv",
|
||||
"valuefield": "k",
|
||||
"textfield": "v",
|
||||
"cond": "parentid='team_role_type'"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -297,67 +297,6 @@ async def delete_llm(params_kw):
|
||||
return json.dumps(result, ensure_ascii=False, default=str)
|
||||
|
||||
|
||||
async def _simple_crud(table, op, params_kw):
|
||||
"""团队沟通配置表通用 CRUD(table: 表名, op: create/update/delete)。"""
|
||||
result = {'success': False, 'message': ''}
|
||||
try:
|
||||
db, dbname = _get_sor()
|
||||
async with db.sqlorContext(dbname) as sor:
|
||||
data = params_kw.copy()
|
||||
data.pop('page', None)
|
||||
data.pop('rows', None)
|
||||
data.pop('data_filter', None)
|
||||
if op == 'create':
|
||||
data['id'] = getID()
|
||||
await sor.C(table, data)
|
||||
result['id'] = data['id']
|
||||
result['success'] = True
|
||||
result['message'] = '创建成功'
|
||||
elif op == 'update':
|
||||
rid = data.pop('id', None)
|
||||
if not rid:
|
||||
result['message'] = '缺少id'
|
||||
else:
|
||||
await sor.U(table, {**data, 'id': rid})
|
||||
result['success'] = True
|
||||
result['message'] = '更新成功'
|
||||
else:
|
||||
rid = params_kw.get('id')
|
||||
if not rid:
|
||||
result['message'] = '缺少id'
|
||||
else:
|
||||
await sor.D(table, {'id': rid})
|
||||
result['success'] = True
|
||||
result['message'] = '删除成功'
|
||||
except Exception as e:
|
||||
result['message'] = str(e)
|
||||
return json.dumps(result, ensure_ascii=False, default=str)
|
||||
|
||||
|
||||
async def create_pipeline_team_role(params_kw):
|
||||
return await _simple_crud('pipeline_team_roles', 'create', params_kw)
|
||||
|
||||
|
||||
async def update_pipeline_team_role(params_kw):
|
||||
return await _simple_crud('pipeline_team_roles', 'update', params_kw)
|
||||
|
||||
|
||||
async def delete_pipeline_team_role(params_kw):
|
||||
return await _simple_crud('pipeline_team_roles', 'delete', params_kw)
|
||||
|
||||
|
||||
async def create_pipeline_problem_type(params_kw):
|
||||
return await _simple_crud('pipeline_problem_types', 'create', params_kw)
|
||||
|
||||
|
||||
async def update_pipeline_problem_type(params_kw):
|
||||
return await _simple_crud('pipeline_problem_types', 'update', params_kw)
|
||||
|
||||
|
||||
async def delete_pipeline_problem_type(params_kw):
|
||||
return await _simple_crud('pipeline_problem_types', 'delete', params_kw)
|
||||
|
||||
|
||||
def load_pipeline_core():
|
||||
"""注册函数到 ServerEnv"""
|
||||
env = ServerEnv()
|
||||
@ -386,19 +325,6 @@ def load_pipeline_core():
|
||||
env.update_pipeline_versions = update_pipeline_version
|
||||
env.delete_pipeline_version = delete_pipeline_version
|
||||
env.delete_pipeline_versions = delete_pipeline_version
|
||||
# Team communication (团队沟通:团队角色 + 问题类型)
|
||||
env.create_pipeline_team_role = create_pipeline_team_role
|
||||
env.create_pipeline_team_roles = create_pipeline_team_role
|
||||
env.update_pipeline_team_role = update_pipeline_team_role
|
||||
env.update_pipeline_team_roles = update_pipeline_team_role
|
||||
env.delete_pipeline_team_role = delete_pipeline_team_role
|
||||
env.delete_pipeline_team_roles = delete_pipeline_team_role
|
||||
env.create_pipeline_problem_type = create_pipeline_problem_type
|
||||
env.create_pipeline_problem_types = create_pipeline_problem_type
|
||||
env.update_pipeline_problem_type = update_pipeline_problem_type
|
||||
env.update_pipeline_problem_types = update_pipeline_problem_type
|
||||
env.delete_pipeline_problem_type = delete_pipeline_problem_type
|
||||
env.delete_pipeline_problem_types = delete_pipeline_problem_type
|
||||
# Publish
|
||||
env.publish_pipeline = publish_pipeline
|
||||
debug(f'[{MODULE_NAME}] module loaded')
|
||||
|
||||
@ -45,23 +45,6 @@ PATHS_LOGINED = [
|
||||
f"/{MOD}/api/pipelines_create.dspy",
|
||||
f"/{MOD}/api/pipelines_update.dspy",
|
||||
f"/{MOD}/api/pipelines_delete.dspy",
|
||||
# Team communication (团队沟通:团队角色 + 问题类型 CRUD)
|
||||
f"/{MOD}/pipeline_team_roles/index.ui",
|
||||
f"/{MOD}/pipeline_team_roles/get_pipeline_team_roles.dspy",
|
||||
f"/{MOD}/pipeline_team_roles/add_pipeline_team_roles.dspy",
|
||||
f"/{MOD}/pipeline_team_roles/update_pipeline_team_roles.dspy",
|
||||
f"/{MOD}/pipeline_team_roles/delete_pipeline_team_roles.dspy",
|
||||
f"/{MOD}/pipeline_problem_types/index.ui",
|
||||
f"/{MOD}/pipeline_problem_types/get_pipeline_problem_types.dspy",
|
||||
f"/{MOD}/pipeline_problem_types/add_pipeline_problem_types.dspy",
|
||||
f"/{MOD}/pipeline_problem_types/update_pipeline_problem_types.dspy",
|
||||
f"/{MOD}/pipeline_problem_types/delete_pipeline_problem_types.dspy",
|
||||
f"/{MOD}/api/pipeline_team_roles_create.dspy",
|
||||
f"/{MOD}/api/pipeline_team_roles_update.dspy",
|
||||
f"/{MOD}/api/pipeline_team_roles_delete.dspy",
|
||||
f"/{MOD}/api/pipeline_problem_types_create.dspy",
|
||||
f"/{MOD}/api/pipeline_problem_types_update.dspy",
|
||||
f"/{MOD}/api/pipeline_problem_types_delete.dspy",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -1,66 +1,73 @@
|
||||
---
|
||||
name: team-communication
|
||||
description: 团队沟通(通用问题冒泡)——问题按类型沿冒泡路径在团队角色间流转,解决即停、未解决继续冒泡、尽头由人兜底。触发:agent 发现问题、角色提问、PM 退回、故障上报、客户提问等。
|
||||
description: 团队沟通规范(问题冒泡)——定义团队角色、问题类型、冒泡路径,agent 有问题时据此处理(提问题/找自己要处理的/回答/转交)。产线定义默认规范,项目可用同名 skill 覆盖。触发:agent 发现问题、角色缺信息、PM 退回、故障上报、客户提问、待处理问题>0。
|
||||
---
|
||||
|
||||
# 团队沟通(通用问题冒泡)
|
||||
# 团队沟通(问题冒泡)规范
|
||||
|
||||
## 核心概念
|
||||
本 skill 是**规范**(团队结构 + 问题类型 + 冒泡路径)。问题操作的工具由系统固化,
|
||||
agent 读本 skill 理解规范后,用工具执行。
|
||||
|
||||
- **团队** = 一组不同角色的 agent + 人(`pipeline_team_roles` 表,每个成员 = role_name + agentid)。
|
||||
- 多 agent 存在:同一角色可有多个 agent,必须用 `agentid` 区分到具体处理方。
|
||||
- `role_type`:`agent`(AI agent)/ `human`(人,如客户)。
|
||||
- **问题类型**(`pipeline_problem_types`)= 一条冒泡路径 `escalation_path`(处理方序列)。
|
||||
- **冒泡路径条目**:`"role_name"`(该角色任意 agent/人)或 `{"role":"x","agentid":"y"}`(指定 agent)。
|
||||
## 一、核心模型
|
||||
|
||||
## 冒泡规则(核心)
|
||||
- **团队** = 一组不同角色的 agent + 人。多 agent 存在:同一角色可有多个 agent,
|
||||
处理方必须精确到 `角色 + agentid`(agentid 空 = 该角色任意 agent)。
|
||||
- **问题类型** = 一种问题 + 一条冒泡路径(处理方序列)。
|
||||
- **冒泡规则**:问题产生后从路径第一个处理方开始;处理方解决了→停(answered);
|
||||
没解决→沿路径转给下一个处理方;路径尽头通常是「人」兜底。
|
||||
|
||||
```
|
||||
提出问题 raise → 沿路径第一个处理方开始
|
||||
↓
|
||||
处理方判断:
|
||||
解决了 → resolve(status=answered,停止冒泡,任务恢复)
|
||||
没解决 → escalate(escalation_pos+1,沿路径继续走到下一个处理方)
|
||||
↓
|
||||
路径尽头 = 最后一个处理方(通常是"人" customer,兜底)
|
||||
```
|
||||
## 二、团队角色(产线默认)
|
||||
|
||||
## 工具
|
||||
| 角色 | 类型 | 职责 |
|
||||
|---|---|---|
|
||||
| main_agent | agent | 用户面对话 agent,回答问题、路由到客户 |
|
||||
| pm | agent | 项目经理,审核交付件、退回意见 |
|
||||
| requirement | agent | 需求分析师 |
|
||||
| design | agent | 系统设计师 |
|
||||
| develop | agent | 开发工程师 |
|
||||
| test | agent | 测试工程师 |
|
||||
| deploy | agent | 部署运维 |
|
||||
| customer | human | 人类客户,最终兜底 |
|
||||
|
||||
| 工具 | 作用 |
|
||||
|---|---|
|
||||
| `list_questions` | 列出「当前该我(主agent)处理」的问题(不混入退回给角色 agent 的) |
|
||||
| `answer_question` | 回答/解决 → 停止冒泡,任务恢复 |
|
||||
| `escalate_question` | 答不了 → 沿冒泡路径转下一个处理方(通常转客户) |
|
||||
| `diagnose_project` | 「待回答问题」计数 = 当前该主 agent 处理的问题数 |
|
||||
|
||||
后端引擎(`pipeline_service/communication.py`):`raise_problem` / `resolve_problem` / `escalate_problem` / `list_problems_for`。
|
||||
|
||||
## 处理流程(发现「待回答问题」> 0 时必须执行)
|
||||
|
||||
1. `list_questions` 列出所有「待我处理」的 pending 问题,不要只报统计数字。
|
||||
2. 对每个问题:
|
||||
- 你能解决 → `answer_question` 直接回答(任务自动恢复,冒泡停止)。
|
||||
- 你答不了 → `escalate_question` 沿冒泡路径转下一个处理方(客户),等对方回答后再闭环。
|
||||
|
||||
## SDLC 产线默认问题类型(sdlc_general)
|
||||
## 三、问题类型与冒泡路径(产线默认)
|
||||
|
||||
| 问题类型 | 冒泡路径 | 说明 |
|
||||
|---|---|---|
|
||||
| `need_info` | `[main_agent, customer]` | 角色 agent 缺信息 → 主 agent 答 / 转客户 |
|
||||
| `review_reject` | `[被退角色, pm]` | PM 退回 → 被退角色响应 / 兜回 pm |
|
||||
| `fault_report` | `[main_agent, customer]` | 任务失败报障 → 主 agent / 客户人工介入 |
|
||||
| need_info | main_agent → customer | 角色缺信息向上提问,主 agent 答 / 转客户 |
|
||||
| review_reject | 被退角色 → pm | PM 退回,被退角色响应后复审 |
|
||||
| fault_report | main_agent → customer | 任务失败报障,主 agent / 客户人工介入 |
|
||||
|
||||
## 多 agent 路由规则
|
||||
冒泡路径是**规范**,由 agent 读后决策「下一个转给谁」,系统不把路径存进数据。
|
||||
|
||||
- 处理方 `agentid` 为空 = 该角色任意 agent 可处理。
|
||||
- 处理方 `agentid` 指定 = 只有该 agent 能处理(同角色其他 agent 看不到)。
|
||||
- 角色 agent 重新认领任务时,只注入「本角色/本 agent」应响应的 pending 退回意见(`get_task_qa(include_pending_for=role, include_pending_agentid=agentid)`)。
|
||||
## 四、工具(系统固化,产线无关)
|
||||
|
||||
## 相关文件
|
||||
| 工具 | 作用 |
|
||||
|---|---|
|
||||
| raise_problem(problem_type, question, first_handler_role, first_handler_agentid) | 提问题,显式指定首处理方 |
|
||||
| list_problems_for(role, agentid) | 查「当前该我处理」的问题(确定性过滤) |
|
||||
| resolve_problem(question_id, answer) | 解决 → 停止冒泡 |
|
||||
| escalate_problem(question_id, next_handler_role, next_handler_agentid) | 没解决 → 显式转给下一个处理方 |
|
||||
|
||||
- `pipeline_service/communication.py` — 通用冒泡引擎(raise/resolve/escalate/list_for)
|
||||
- `pipeline_service/questions.py` — 向后兼容层(agent_ask/answer_question/forward_question 委托 communication)
|
||||
- `pipeline_service/agent_loop.py` — 角色提问(need_info)、PM 退回(review_reject)、故障(fault_report)、PM 审核通过答结
|
||||
- `pipeline_service/sdlc_ability.py` — cockpit 工具 list_questions/answer_question/escalate_question
|
||||
- `pipeline-core/models/pipeline_team_roles.json` + `pipeline_problem_types.json` — 团队角色 + 问题类型定义
|
||||
cockpit 侧包装:`list_questions`(查待我处理的)、`answer_question`(回答)、
|
||||
`escalate_question`(转给客户)。
|
||||
|
||||
## 五、处理流程(agent 侧)
|
||||
|
||||
1. 我发现问题 → `raise_problem`,按问题类型 + 冒泡路径指定首处理方。
|
||||
2. 我可能被指派处理问题 → `list_problems_for(我的角色, 我的 agentid)` 查待办,
|
||||
不要只报统计数字,逐条读。
|
||||
3. 我能解决 → `resolve_problem`(任务自动恢复,冒泡停止)。
|
||||
4. 我答不了 → `escalate_problem`,沿冒泡路径转给下一个处理方。
|
||||
|
||||
## 六、分层与覆盖
|
||||
|
||||
- 本 skill 是**产线级默认规范**(skills_library 模板)。
|
||||
- 项目可用**同名 team-communication skill** 放在项目 skills 目录覆盖:
|
||||
同名问题类型 → 项目覆盖;新增 → 追加;未定义 → 兜底到产线级。
|
||||
- 加载顺序:项目级 → 产线级 → 全局兜底。
|
||||
|
||||
## 七、状态与归属
|
||||
|
||||
- 状态只有 `pending`(冒泡中)/ `answered`(已解决)。
|
||||
- 归属 = `current_handler_role` + `current_handler_agentid` 两列,
|
||||
由工具维护,查询走确定性 SQL,不靠 LLM 扫全文。
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
func = create_pipeline_problem_type
|
||||
if func is None:
|
||||
return json.dumps({'status': 'error', 'message': 'function not found'})
|
||||
result = await func(params_kw)
|
||||
return result
|
||||
@ -1,5 +0,0 @@
|
||||
func = delete_pipeline_problem_type
|
||||
if func is None:
|
||||
return json.dumps({'status': 'error', 'message': 'function not found'})
|
||||
result = await func(params_kw)
|
||||
return result
|
||||
@ -1,5 +0,0 @@
|
||||
func = update_pipeline_problem_type
|
||||
if func is None:
|
||||
return json.dumps({'status': 'error', 'message': 'function not found'})
|
||||
result = await func(params_kw)
|
||||
return result
|
||||
@ -1,5 +0,0 @@
|
||||
func = create_pipeline_team_role
|
||||
if func is None:
|
||||
return json.dumps({'status': 'error', 'message': 'function not found'})
|
||||
result = await func(params_kw)
|
||||
return result
|
||||
@ -1,5 +0,0 @@
|
||||
func = delete_pipeline_team_role
|
||||
if func is None:
|
||||
return json.dumps({'status': 'error', 'message': 'function not found'})
|
||||
result = await func(params_kw)
|
||||
return result
|
||||
@ -1,5 +0,0 @@
|
||||
func = update_pipeline_team_role
|
||||
if func is None:
|
||||
return json.dumps({'status': 'error', 'message': 'function not found'})
|
||||
result = await func(params_kw)
|
||||
return result
|
||||
Loading…
x
Reference in New Issue
Block a user