pipeline-sdlc/wwwroot/sd_dashboard/dashboard_data.dspy
yumoqing 72cd262cdb feat(cockpit): product-grade LLM integration with context + model mgmt
Backend:
- cockpit_chat.dspy: real LLM calls via llm table config, Hermes-style
  context (system prompt + project/iteration + history), auto model
  selection (multimodal if files, text otherwise)
- cockpit_model_options.dspy: returns active models with capabilities
- llm table: added capabilities column (text/vision/multimodal)

Frontend:
- inputed script: no page reload, updates agent bubble with LLM reply
- stats_row refreshed on success, error shown in bubble

DB:
- sd_agent_settings table for per-user agent preferences
2026-07-31 18:06:27 +08:00

85 lines
3.4 KiB
Plaintext

"""
SDLC Dashboard Data API
Returns real-time stats for the dashboard widgets
"""
from sqlor.dbpools import DBPools
async def main():
dbname = get_module_dbname('pipeline-sdlc')
async with DBPools().sqlorContext(dbname) as sor:
# 1) Project stats
projects = await sor.sqlExe(
"SELECT COUNT(*) as total, SUM(CASE WHEN status='active' THEN 1 ELSE 0 END) as active FROM sd_projects", {})
p = projects[0] if projects else None
# 2) Active iterations
iters = await sor.sqlExe(
"SELECT COUNT(*) as cnt FROM sd_iterations WHERE status='in_progress'", {})
active_iters = iters[0].cnt if iters else 0
# 3) Open bugs
bugs = await sor.sqlExe(
"SELECT COUNT(*) as cnt FROM sd_bugs WHERE status!='closed' AND status!='resolved'", {})
open_bugs = bugs[0].cnt if bugs else 0
# 4) Pending reviews
reviews = await sor.sqlExe(
"SELECT COUNT(*) as cnt FROM pipeline_human_tasks WHERE status='pending' AND task_type='review'", {})
pending_reviews = reviews[0].cnt if reviews else 0
# 5) Recent iterations with progress
recent_iters = await sor.sqlExe("""
SELECT i.name, i.status, i.start_date, i.end_date,
COALESCE(tc.total,0) as total_tasks,
COALESCE(tc.completed,0) as completed_tasks
FROM sd_iterations i
LEFT JOIN (
SELECT iteration_id, COUNT(*) as total,
SUM(CASE WHEN status='completed' THEN 1 ELSE 0 END) as completed
FROM sd_test_plans GROUP BY iteration_id
) tc ON tc.iteration_id = i.id
WHERE i.status != 'closed'
ORDER BY i.start_date DESC LIMIT 5
""", {})
iter_list = []
for r in recent_iters:
pct = round(r.completed_tasks / r.total_tasks * 100) if r.total_tasks > 0 else 0
iter_list.append({
'name': r.name,
'status': r.status,
'progress': pct,
'total': r.total_tasks,
'completed': r.completed_tasks
})
# 6) Bug by severity
bug_by_sev = await sor.sqlExe("""
SELECT COALESCE(severity,'unset') as severity, COUNT(*) as cnt
FROM sd_bugs WHERE status!='closed'
GROUP BY severity ORDER BY cnt DESC
""", {})
severity_map = {
'critical': {'label': '严重', 'color': '#FF4444'},
'major': {'label': '主要', 'color': '#FF8800'},
'minor': {'label': '次要', 'color': '#FFAA00'},
'trivial': {'label': '轻微', 'color': '#888888'},
'unset': {'label': '未分类', 'color': '#666666'}
}
bugs_data = []
for r in bug_by_sev:
sev = severity_map.get(r.severity, {'label': r.severity, 'color': '#888'})
bugs_data.append({'label': sev['label'], 'count': r.cnt, 'color': sev['color']})
return {
'projects_total': p.total if p else 0,
'projects_active': p.active if p else 0,
'active_iterations': active_iters,
'open_bugs': open_bugs,
'pending_reviews': pending_reviews,
'recent_iterations': iter_list,
'bugs_by_severity': bugs_data
}