pipeline-sdlc/wwwroot/api/cockpit_agent.dspy

127 lines
5.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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'
session_id = (params_kw or {}).get('session_id', '')
async def _get_context(sor, uid, session_id=''):
pid, iid = await get_session_context(sor, uid, session_id)
return {'project_id': pid, 'iteration_id': iid}
if action == 'start_agent':
async with DBPools().sqlorContext(dbname) as sor:
ctx = await _get_context(sor, uid, session_id)
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', 'develop')
# model_id 兼容 llm.id 与 llm.model_id 两种取值(下拉改为传 llm.id
# 统一解析为 llm.name 落库/传给引擎,保证同名不同供应商不漂移。
if model_id:
_r = await sor.sqlExe(
"SELECT name FROM llm WHERE status='active' AND (id=${m}$ OR model_id=${m}$) LIMIT 1",
{"m": model_id})
await sor.sqlExe("COMMIT", {})
if _r:
model_id = getattr(_r[0], 'name', '') or model_id
# 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, session_id)
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, session_id)
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)