diff --git a/bin/init_data.py b/bin/init_data.py index 9d610af..1bfe295 100644 --- a/bin/init_data.py +++ b/bin/init_data.py @@ -58,6 +58,36 @@ SDLC_STEPS = [ ] +# ---- 团队沟通(通用问题冒泡):sdlc_general 产线的团队角色 + 问题类型 ---- +TEAM_ROLE_TYPE_CODES = [ + # (k, v) + ('agent', 'Agent'), + ('human', '人'), +] + +SDLC_TEAM_ROLES = [ + # (role_name, agentid, role_type, display_name, description) + ('main_agent', '', 'agent', '主Agent', '用户面对话agent,回答问题、路由到客户'), + ('pm', '', 'agent', '项目经理', '审核交付件、退回意见'), + ('requirement', '', 'agent', '需求分析师', '产出需求规格文档'), + ('design', '', 'agent', '系统设计师', '产出架构/DB/API设计'), + ('develop', '', 'agent', '开发工程师', '产出可运行源码'), + ('test', '', 'agent', '测试工程师', '产出测试用例+报告'), + ('deploy', '', 'agent', '部署运维', '产出部署文档+配置'), + ('customer', '', 'human', '客户', '人类客户,最终兜底'), +] + +SDLC_PROBLEM_TYPES = [ + # (name, title, description, escalation_path) + ('need_info', '缺信息提问', '角色agent缺关键信息向上提问', + '["main_agent", "customer"]'), + ('review_reject', '审核退回', 'PM审核退回意见,被退角色响应后复审', + '["pm"]'), + ('fault_report', '故障报告', '任务失败报障,人工介入', + '["main_agent", "customer"]'), +] + + async def init_data(demo=False): config_file = os.path.join(ROOT_DIR, 'conf', 'config.json') if not os.path.exists(config_file): @@ -115,7 +145,55 @@ async def init_data(demo=False): else: print(f' SKIP {SDLC_PIPELINE["name"]} (exists)') - # 3. Demo data + # 3. 团队沟通:角色类型代码表 + sdlc_general 团队角色 + 问题类型 + print('\nTeam communication:') + for k, v in TEAM_ROLE_TYPE_CODES: + existing = await sor.sqlExe( + "SELECT id FROM appcodes_kv WHERE parentid='team_role_type' AND k=${k}$", {'k': k}) + if not existing: + await sor.C('appcodes_kv', {'id': getID(), 'parentid': 'team_role_type', 'k': k, 'v': v}) + print(f' ADD code team_role_type.{k}') + + # 确保 sdlc_general 产线存在(能力包注册的产线 id) + existing = await sor.sqlExe("SELECT id FROM pipelines WHERE id='sdlc_general'", {}) + if not existing: + await sor.C('pipelines', { + 'id': 'sdlc_general', 'name': '通用软件开发产线', + 'description': 'SDLC 开发产线(能力包注册)', + 'pipeline_type': 'dev', 'status': 'published', 'version': '1.0', + 'org_id': '0', 'created_by': 'system', + 'created_at': timestampstr(), 'updated_at': timestampstr(), + }) + print(' ADD pipeline sdlc_general') + + for rname, aid, rtype, dname, desc in SDLC_TEAM_ROLES: + existing = await sor.sqlExe( + "SELECT id FROM pipeline_team_roles WHERE pipeline_id='sdlc_general' AND role_name=${r}$", + {'r': rname}) + if existing: + continue + await sor.C('pipeline_team_roles', { + 'id': getID(), 'pipeline_id': 'sdlc_general', + 'role_name': rname, 'agentid': aid, 'role_type': rtype, + 'display_name': dname, 'description': desc, + 'created_at': timestampstr(), + }) + print(f' ADD role {rname}') + + for pname, ptitle, pdesc, ppath in SDLC_PROBLEM_TYPES: + existing = await sor.sqlExe( + "SELECT id FROM pipeline_problem_types WHERE pipeline_id='sdlc_general' AND name=${n}$", + {'n': pname}) + if existing: + continue + await sor.C('pipeline_problem_types', { + 'id': getID(), 'pipeline_id': 'sdlc_general', + 'name': pname, 'title': ptitle, 'description': pdesc, + 'escalation_path': ppath, 'created_at': timestampstr(), + }) + print(f' ADD problem_type {pname}') + + # 4. Demo data if demo: print('\nDemo data:') await _create_demo(sor) diff --git a/scripts/create_tables.py b/scripts/create_tables.py index 85f5a44..9bd3a81 100644 --- a/scripts/create_tables.py +++ b/scripts/create_tables.py @@ -110,6 +110,27 @@ async def main(): except Exception as e: print(f' WARN: appbase params ensure failed: {e}') + # pipeline_agent_questions 团队沟通列幂等迁移(多 agent 感知冒泡引擎) + try: + _q_cols = { + "from_agentid": "VARCHAR(64) NULL COMMENT '提问Agent标识'", + "problem_type": "VARCHAR(50) NULL COMMENT '问题类型'", + "escalation_path": "TEXT NULL COMMENT '冒泡路径(JSON角色/agent数组快照)'", + "escalation_pos": "INT NOT NULL DEFAULT 0 COMMENT '当前冒泡位置'", + } + for col, ddl in _q_cols.items(): + r = await sor.sqlExe( + "SELECT COUNT(*) as c FROM information_schema.COLUMNS " + "WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='pipeline_agent_questions' " + "AND COLUMN_NAME=${col}$", {"col": col}) + await sor.sqlExe("COMMIT", {}) + if not r or getattr(r[0], 'c', 0) == 0: + await sor.execute( + f"ALTER TABLE pipeline_agent_questions ADD COLUMN {col} {ddl}", {}) + print(' migrate: pipeline_agent_questions team-communication columns ensured') + except Exception as e: + print(f' WARN: pipeline_agent_questions migrate failed: {e}') + if __name__ == '__main__': asyncio.run(main()) diff --git a/wwwroot/index.ui b/wwwroot/index.ui index 5becb50..054636f 100644 --- a/wwwroot/index.ui +++ b/wwwroot/index.ui @@ -98,6 +98,18 @@ "icon": "", "script": "this.open_tab({name:'llm_manage',label:'模型管理',url:'/pipeline_core/llm',removable:true})" }, + { + "name": "team_roles", + "label": "团队角色", + "icon": "", + "script": "this.open_tab({name:'team_roles',label:'团队角色',url:'/pipeline_core/pipeline_team_roles',removable:true})" + }, + { + "name": "problem_types", + "label": "问题类型", + "icon": "", + "script": "this.open_tab({name:'problem_types',label:'问题类型',url:'/pipeline_core/pipeline_problem_types',removable:true})" + }, { "name": "generic_agent", "label": "通用助手",