cockpit agent: add task lifecycle tools (task_detail, deliverables, questions, start_agents)
This commit is contained in:
parent
ae1aaadd91
commit
915333d9bd
@ -17,9 +17,12 @@ dbname = get_module_dbname('pipeline-sdlc')
|
||||
AGENT_PROMPT = """你是开发产线驾驶舱 Agent。用工具获取数据,用 reply 回复。
|
||||
|
||||
工作流:
|
||||
- 切换项目:先调 list_projects 看有哪些项目,再调 switch_project
|
||||
- 创建项目:如果需要的项目不存在,调 create_project
|
||||
- 提交任务前确保已切换到正确项目
|
||||
- 切换项目:先 list_projects 看有哪些项目,再 switch_project
|
||||
- 创建项目:不存在则 create_project
|
||||
- 查看进度:list_tasks / task_detail / list_deliverables
|
||||
- 提交任务:先确保在正确项目,再 create_task
|
||||
- 启动Agent:任务提交后调 start_agents 让角色Agent执行
|
||||
- 回答问题:list_questions 看问题 → answer_question 回答
|
||||
- clone_repo 用于克隆 git 仓库到工作空间
|
||||
- run_command 用于在工作空间中执行 shell 命令
|
||||
|
||||
@ -34,9 +37,15 @@ TOOLS = [
|
||||
{"name":"list_projects","description":"列出所有可用项目","params":{}},
|
||||
{"name":"switch_project","description":"切换到指定项目(需先list_projects确认项目名)","params":{"project":"项目名称"}},
|
||||
{"name":"create_project","description":"创建新项目","params":{"name":"项目名称","description":"项目描述(可选)"}},
|
||||
{"name":"create_task","description":"提交任务","params":{"title":"标题","description":"描述","role":"requirement/design/develop/test/deploy"}},
|
||||
{"name":"list_tasks","description":"列出当前项目任务","params":{"state":"状态(可选)"}},
|
||||
{"name":"check_progress","description":"查进度","params":{"task_id":"任务ID(可选)"}},
|
||||
{"name":"task_detail","description":"查看任务详情(含交付件和问答)","params":{"task_id":"任务ID"}},
|
||||
{"name":"list_deliverables","description":"列出当前项目交付件","params":{"task_id":"任务ID(可选)"}},
|
||||
{"name":"view_deliverable","description":"查看交付件内容","params":{"deliverable_id":"交付件ID"}},
|
||||
{"name":"list_questions","description":"列出待回答的问题","params":{}},
|
||||
{"name":"answer_question","description":"回答agent提出的问题","params":{"question_id":"问题ID","answer":"回答内容"}},
|
||||
{"name":"create_task","description":"提交开发任务到指定角色","params":{"title":"标题","description":"描述","role":"requirement/design/develop/test/deploy"}},
|
||||
{"name":"start_agents","description":"启动项目角色agents执行待办任务","params":{}},
|
||||
{"name":"check_progress","description":"查看项目整体进度","params":{"task_id":"任务ID(可选)"}},
|
||||
{"name":"add_repo","description":"关联仓库到当前项目","params":{"url":"git地址","name":"名称(可选)"}},
|
||||
{"name":"list_repos","description":"列出当前项目仓库","params":{}},
|
||||
{"name":"clone_repo","description":"克隆仓库到工作空间","params":{"url":"git地址","branch":"分支名(可选,默认main)"}},
|
||||
@ -122,7 +131,7 @@ def _w_card(title, body, kind="success"):
|
||||
]}
|
||||
def _w_progress(text): return {"widgettype":"Text","options":{"text":text,"style":{"color":"#f59e0b","fontSize":"12px","padding":"2px 8px"}}}
|
||||
|
||||
_tool_labels = {'list_projects':'列出项目','switch_project':'切换项目','create_project':'创建项目','create_task':'创建任务','check_progress':'检查进度','list_tasks':'查询任务','add_repo':'关联仓库','list_repos':'查看仓库','clone_repo':'克隆仓库','add_bug':'报告Bug','run_command':'执行命令'}
|
||||
_tool_labels = {'list_projects':'列出项目','switch_project':'切换项目','create_project':'创建项目','list_tasks':'查询任务','task_detail':'任务详情','list_deliverables':'查看交付件','view_deliverable':'交付件内容','list_questions':'查看问题','answer_question':'回答问题','create_task':'创建任务','start_agents':'启动角色Agent','check_progress':'检查进度','add_repo':'关联仓库','list_repos':'查看仓库','clone_repo':'克隆仓库','add_bug':'报告Bug','run_command':'执行命令'}
|
||||
|
||||
async def _exec_tool(sor, tool, params, ctx, uid, org_id):
|
||||
p = params or {}
|
||||
@ -236,6 +245,60 @@ async def _exec_tool(sor, tool, params, ctx, uid, org_id):
|
||||
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=60, cwd=ws)
|
||||
out = (r.stdout + r.stderr)[:2000]
|
||||
return f'OK (rc={r.returncode}):\n{out}' if out else f'OK (rc={r.returncode})'
|
||||
elif tool == 'task_detail':
|
||||
tid = p.get('task_id','')
|
||||
if not tid: return 'FAIL: 需要任务ID'
|
||||
ts = await sor.sqlExe("SELECT * FROM pipeline_tasks WHERE id=${t}$",{"t":tid})
|
||||
if not ts: return 'FAIL: 任务不存在'
|
||||
t = ts[0]
|
||||
ds = await sor.sqlExe("SELECT deliverable_type,title,review_status,quality_score FROM pipeline_deliverables WHERE task_id=${t}$",{"t":tid})
|
||||
dl = '\n'.join([f" [{getattr(d,'review_status','')}] {getattr(d,'deliverable_type','')}: {getattr(d,'title','')[:60]}" for d in (ds or [])]) or ' 无'
|
||||
qs = await sor.sqlExe("SELECT question,answer,status FROM pipeline_questions WHERE task_id=${t}$ ORDER BY created_at DESC LIMIT 5",{"t":tid})
|
||||
ql = '\n'.join([f" [{getattr(q,'status','')}] Q:{getattr(q,'question','')[:60]}\n A:{getattr(q,'answer','') or '待回答'}" for q in (qs or [])]) or ' 无'
|
||||
return f"任务: {getattr(t,'title','')}\n状态: {getattr(t,'state','')}\n角色: {getattr(t,'role','')}\n交付件:\n{dl}\n问答:\n{ql}"
|
||||
elif tool == 'list_deliverables':
|
||||
if not ctx['pid']: return 'FAIL: 请先切换到项目'
|
||||
tid = p.get('task_id','')
|
||||
if tid:
|
||||
ds = await sor.sqlExe("SELECT id,deliverable_type,title,review_status,quality_score FROM pipeline_deliverables WHERE task_id=${t}$ ORDER BY created_at DESC",{"t":tid})
|
||||
else:
|
||||
ds = await sor.sqlExe("SELECT id,deliverable_type,title,review_status,quality_score FROM pipeline_deliverables WHERE project_id=${p}$ ORDER BY created_at DESC LIMIT 20",{"p":ctx['pid']})
|
||||
if not ds: return '无交付件'
|
||||
return '\n'.join([f"[{getattr(d,'review_status','?')}] {getattr(d,'id','')[:8]} {getattr(d,'deliverable_type','')}: {getattr(d,'title','')[:60]} ({getattr(d,'quality_score','-')}分)" for d in ds])
|
||||
elif tool == 'view_deliverable':
|
||||
did = p.get('deliverable_id','')
|
||||
if not did: return 'FAIL: 需要交付件ID'
|
||||
ds = await sor.sqlExe("SELECT deliverable_type,title,content,review_status,quality_score FROM pipeline_deliverables WHERE id=${d}$",{"d":did})
|
||||
if not ds: return 'FAIL: 交付件不存在'
|
||||
d = ds[0]
|
||||
return f"类型: {getattr(d,'deliverable_type','')}\n标题: {getattr(d,'title','')}\n状态: {getattr(d,'review_status','')} | 评分: {getattr(d,'quality_score','')}\n\n{getattr(d,'content','')[:3000]}"
|
||||
elif tool == 'list_questions':
|
||||
if not ctx['pid']: return 'FAIL: 请先切换到项目'
|
||||
qs = await sor.sqlExe("SELECT id,task_id,question,answer,status,created_at FROM pipeline_questions WHERE project_id=${p}$ AND status='pending' ORDER BY created_at DESC LIMIT 10",{"p":ctx['pid']})
|
||||
if not qs: return '无待回答问题'
|
||||
return '\n'.join([f"[{getattr(q,'id','')[:8]}] 任务:{getattr(q,'task_id','')[:8]} Q:{getattr(q,'question','')[:80]}" for q in qs])
|
||||
elif tool == 'answer_question':
|
||||
qid = p.get('question_id','')
|
||||
ans = p.get('answer','')
|
||||
if not qid: return 'FAIL: 需要问题ID'
|
||||
if not ans: return 'FAIL: 需要回答内容'
|
||||
qs = await sor.sqlExe("SELECT id,status FROM pipeline_questions WHERE id=${q}$",{"q":qid})
|
||||
if not qs: return 'FAIL: 问题不存在'
|
||||
await sor.sqlExe("UPDATE pipeline_questions SET answer=${a}$, status='answered', answered_at=NOW() WHERE id=${q}$",{"a":ans,"q":qid})
|
||||
return f'OK: 已回答'
|
||||
elif tool == 'start_agents':
|
||||
if not ctx['pid']: return 'FAIL: 请先切换到项目'
|
||||
from pipeline_service.agent_loop import role_agent_run, pm_review_run
|
||||
import asyncio as _asyncio
|
||||
results = []
|
||||
for role in ['requirement','design','develop','test','deploy']:
|
||||
r = await role_agent_run(ctx['pid'], role)
|
||||
if r['status'] != 'idle':
|
||||
results.append(f"{role}: {r['status']} task={r.get('task_id','')[:8]}")
|
||||
pm_r = await pm_review_run(ctx['pid'])
|
||||
if pm_r['status'] != 'idle':
|
||||
results.append(f"pm_review: {pm_r['status']} task={pm_r.get('task_id','')[:8]}")
|
||||
return '\n'.join(results) if results else '无待执行任务'
|
||||
elif tool == 'add_bug':
|
||||
if not ctx['pid']: return 'FAIL: 请先切换到项目'
|
||||
title = p.get('title','')[:100]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user