147 lines
5.2 KiB
Plaintext
147 lines
5.2 KiB
Plaintext
# cockpit_chat.dspy - Send message or list conversation
|
|
# POST: action=send_message, iteration_id, message_text
|
|
# GET: action=list_messages, iteration_id (optional), task_id (optional)
|
|
|
|
action = (params_kw or {}).get('action', 'list_messages')
|
|
dbname = get_module_dbname('pipeline-sdlc')
|
|
|
|
if action == 'send_message':
|
|
iteration_id = (params_kw or {}).get('iteration_id', '')
|
|
task_id = (params_kw or {}).get('task_id', '')
|
|
message_text = (params_kw or {}).get('message_text', '').strip()
|
|
|
|
if not iteration_id or not message_text:
|
|
return json.dumps({"error": "Missing iteration_id or message_text"}, ensure_ascii=False)
|
|
|
|
uid = await get_user()
|
|
|
|
async with DBPools().sqlorContext(dbname) as sor:
|
|
# Save user message
|
|
msg_id = getID()
|
|
await sor.I('sd_conversations', {
|
|
'id': msg_id,
|
|
'iteration_id': iteration_id,
|
|
'task_id': task_id or '',
|
|
'step_name': '',
|
|
'role': 'user',
|
|
'content': message_text,
|
|
'attachments': '[]',
|
|
'msg_type': 'text',
|
|
'org_id': '0',
|
|
'created_by': uid
|
|
})
|
|
|
|
# Generate agent response
|
|
# 1. Check if there's an active pipeline task for this iteration
|
|
if task_id:
|
|
agent_reply = f"收到你的消息。当前任务 {task_id} 正在执行中,你的输入已记录。"
|
|
else:
|
|
# Check for existing iterations
|
|
iters = await sor.sqlExe(
|
|
"SELECT id, task_id, status FROM sd_iterations WHERE id=${iid}$", {"iid": iteration_id})
|
|
if iters:
|
|
it = iters[0]
|
|
if hasattr(it, 'task_id') and it.task_id:
|
|
agent_reply = f"收到。迭代任务 {it.task_id} 状态: {it.status}。"
|
|
else:
|
|
agent_reply = f"收到你的需求:「{message_text[:50]}...」。请确认是否要为此迭代启动开发产线?"
|
|
else:
|
|
agent_reply = f"收到你的需求:「{message_text[:50]}...」。建议先在项目管理中创建项目和迭代。"
|
|
|
|
# Save agent message
|
|
agent_msg_id = getID()
|
|
await sor.I('sd_conversations', {
|
|
'id': agent_msg_id,
|
|
'iteration_id': iteration_id,
|
|
'task_id': task_id or '',
|
|
'step_name': '',
|
|
'role': 'agent',
|
|
'content': agent_reply,
|
|
'attachments': '[]',
|
|
'msg_type': 'text',
|
|
'org_id': '0',
|
|
'created_by': 'system'
|
|
})
|
|
|
|
return json.dumps({"success": True, "message_id": msg_id}, ensure_ascii=False)
|
|
|
|
else:
|
|
# list_messages - return messages as Bricks widget JSON
|
|
iteration_id = (params_kw or {}).get('iteration_id', '')
|
|
task_id = (params_kw or {}).get('task_id', '')
|
|
|
|
msgs = []
|
|
if iteration_id or task_id:
|
|
async with DBPools().sqlorContext(dbname) as sor:
|
|
where = []
|
|
params = {}
|
|
if task_id:
|
|
where.append("task_id=${tid}$")
|
|
params["tid"] = task_id
|
|
if iteration_id:
|
|
where.append("iteration_id=${iid}$")
|
|
params["iid"] = iteration_id
|
|
|
|
sql = f"SELECT role, content, msg_type, created_at FROM sd_conversations WHERE {' OR '.join(where)} ORDER BY created_at ASC LIMIT 50"
|
|
msgs = await sor.sqlExe(sql, params)
|
|
|
|
# Build chat messages widget
|
|
msg_widgets = []
|
|
for m in msgs:
|
|
role = m.role if hasattr(m, 'role') else ''
|
|
content = m.content if hasattr(m, 'content') else ''
|
|
|
|
if role == 'agent':
|
|
bg = '#e8f0fe'
|
|
align = 'flex-start'
|
|
label = 'Agent'
|
|
label_color = '#3b82f6'
|
|
elif role == 'user':
|
|
bg = '#dbeafe'
|
|
align = 'flex-end'
|
|
label = '你'
|
|
label_color = '#2563eb'
|
|
else:
|
|
bg = '#f1f5f9'
|
|
align = 'center'
|
|
label = '系统'
|
|
label_color = '#94a3b8'
|
|
|
|
msg_widgets.append({
|
|
"widgettype": "VBox",
|
|
"options": {
|
|
"width": "85%",
|
|
"alignSelf": align,
|
|
"bgcolor": bg,
|
|
"borderRadius": "12px",
|
|
"padding": "12px 16px",
|
|
"marginBottom": "10px",
|
|
"gap": "4px"
|
|
},
|
|
"subwidgets": [
|
|
{"widgettype": "Text", "options": {
|
|
"text": label, "cfontsize": 0.75,
|
|
"color": label_color, "fontWeight": "bold"
|
|
}},
|
|
{"widgettype": "Text", "options": {
|
|
"text": content, "cfontsize": 0.95,
|
|
"color": "#1e293b", "whiteSpace": "pre-wrap"
|
|
}}
|
|
]
|
|
})
|
|
|
|
if not msg_widgets:
|
|
msg_widgets.append({
|
|
"widgettype": "Text",
|
|
"options": {
|
|
"text": "暂无对话记录。选择一个迭代后,在下方输入框中开始对话。",
|
|
"cfontsize": 0.9, "color": "#94a3b8", "padding": "20px"
|
|
}
|
|
})
|
|
|
|
return {
|
|
"widgettype": "VBox",
|
|
"options": {"width": "100%", "padding": "4px"},
|
|
"subwidgets": msg_widgets
|
|
}
|