feat: Phase 3 — cockpit_agent.dspy (start/status/deliverables/review)
This commit is contained in:
parent
bb09bd36a0
commit
ee8005644f
120
wwwroot/api/cockpit_agent.dspy
Normal file
120
wwwroot/api/cockpit_agent.dspy
Normal file
@ -0,0 +1,120 @@
|
||||
# cockpit_agent.dspy — Agent control: start/stop, status, deliverables
|
||||
# POST: action=start_agent | agent_status | list_deliverables | review_deliverable
|
||||
|
||||
import aiohttp
|
||||
|
||||
action = (params_kw or {}).get('action', 'agent_status')
|
||||
dbname = get_module_dbname('pipeline-sdlc')
|
||||
uid = await get_user()
|
||||
org_id = await get_userorgid() or '0'
|
||||
|
||||
|
||||
async def _get_context(sor, uid):
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT current_project_id, current_iteration_id FROM pipeline_agent_settings WHERE user_id=${uid}$",
|
||||
{"uid": uid})
|
||||
if recs:
|
||||
return {'project_id': getattr(recs[0], 'current_project_id', '') or '',
|
||||
'iteration_id': getattr(recs[0], 'current_iteration_id', '') or ''}
|
||||
return {'project_id': '', 'iteration_id': ''}
|
||||
|
||||
|
||||
if action == 'start_agent':
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
ctx = await _get_context(sor, uid)
|
||||
pid = ctx['project_id']
|
||||
if not pid:
|
||||
return json.dumps({"success": False, "error": "请先选择项目"}, ensure_ascii=False)
|
||||
|
||||
model_id = (params_kw or {}).get('model_id', '')
|
||||
role = (params_kw or {}).get('role', 'developer')
|
||||
|
||||
# Ensure agent config exists
|
||||
existing = await sor.sqlExe(
|
||||
"SELECT id FROM pipeline_project_agents WHERE project_id=${pid}$ AND role_name=${role}$",
|
||||
{"pid": pid, "role": role})
|
||||
if not existing:
|
||||
await sor.C('pipeline_project_agents', {
|
||||
'id': getID(), 'project_id': pid, 'role_name': role,
|
||||
'model_name': model_id, 'status': 'running'
|
||||
})
|
||||
else:
|
||||
await sor.sqlExe(
|
||||
"UPDATE pipeline_project_agents SET status='running', model_name=${mid}$ WHERE project_id=${pid}$ AND role_name=${role}$",
|
||||
{"pid": pid, "role": role, "mid": model_id})
|
||||
|
||||
# Run one iteration synchronously
|
||||
try:
|
||||
result = await run_agent_loop(pid, role, model_id or None)
|
||||
return json.dumps({"success": True, "result": result}, ensure_ascii=False)
|
||||
except Exception as e:
|
||||
return json.dumps({"success": False, "error": str(e)[:200]}, ensure_ascii=False)
|
||||
|
||||
|
||||
elif action == 'agent_status':
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
ctx = await _get_context(sor, uid)
|
||||
pid = ctx['project_id']
|
||||
|
||||
agents = []
|
||||
if pid:
|
||||
recs = await sor.sqlExe(
|
||||
"SELECT role_name, status, model_name FROM pipeline_project_agents WHERE project_id=${pid}$",
|
||||
{"pid": pid})
|
||||
agents = [{'role': getattr(r, 'role_name', ''), 'status': getattr(r, 'status', ''),
|
||||
'model': getattr(r, 'model_name', '')} for r in recs]
|
||||
|
||||
# Recent deliverables
|
||||
delivs = []
|
||||
if pid:
|
||||
drecs = await sor.sqlExe(
|
||||
"SELECT id, title, deliverable_type, quality_score, review_status, created_by, created_at "
|
||||
"FROM pipeline_deliverables WHERE project_id=${pid}$ ORDER BY created_at DESC LIMIT 10",
|
||||
{"pid": pid})
|
||||
delivs = [{'id': d.id, 'title': d.title, 'type': d.deliverable_type,
|
||||
'score': d.quality_score, 'review': d.review_status,
|
||||
'by': d.created_by, 'at': str(d.created_at)[:16]} for d in drecs]
|
||||
|
||||
return json.dumps({"success": True, "agents": agents, "deliverables": delivs,
|
||||
"project_name": ctx.get('project_name', '')}, ensure_ascii=False)
|
||||
|
||||
|
||||
elif action == 'list_deliverables':
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
ctx = await _get_context(sor, uid)
|
||||
pid = ctx['project_id']
|
||||
if not pid:
|
||||
return json.dumps([], ensure_ascii=False)
|
||||
|
||||
drecs = await sor.sqlExe(
|
||||
"SELECT id, task_id, title, deliverable_type, quality_score, review_status, "
|
||||
"LEFT(content,200) as preview, created_by, created_at "
|
||||
"FROM pipeline_deliverables WHERE project_id=${pid}$ ORDER BY created_at DESC LIMIT 50",
|
||||
{"pid": pid})
|
||||
rows = []
|
||||
for d in drecs:
|
||||
rows.append({
|
||||
'id': d.id, 'task_id': d.task_id, 'title': d.title,
|
||||
'type': d.deliverable_type, 'score': d.quality_score,
|
||||
'review': d.review_status, 'preview': getattr(d, 'preview', ''),
|
||||
'by': d.created_by, 'at': str(d.created_at)[:16]
|
||||
})
|
||||
return json.dumps(rows, ensure_ascii=False)
|
||||
|
||||
|
||||
elif action == 'review_deliverable':
|
||||
did = (params_kw or {}).get('id', '')
|
||||
status = (params_kw or {}).get('status', 'approved')
|
||||
comment = (params_kw or {}).get('comment', '')
|
||||
if not did:
|
||||
return json.dumps({"success": False, "error": "缺少id"}, ensure_ascii=False)
|
||||
|
||||
async with DBPools().sqlorContext(dbname) as sor:
|
||||
await sor.sqlExe(
|
||||
"UPDATE pipeline_deliverables SET review_status=${st}$, reviewed_by=${uid}$, review_comment=${cm}$ WHERE id=${did}$",
|
||||
{"st": status, "uid": uid, "cm": comment, "did": did})
|
||||
return json.dumps({"success": True}, ensure_ascii=False)
|
||||
|
||||
|
||||
else:
|
||||
return json.dumps({"success": False, "error": f"Unknown action: {action}"}, ensure_ascii=False)
|
||||
Loading…
x
Reference in New Issue
Block a user