# cockpit_context_update.dspy - Save user's selected project/iteration to pipeline_agent_settings # POST params: project_id, iteration_id (at least one required) # Also looks up names for the newly set values import json uid = await get_user() if not uid: return json.dumps({"success": False, "error": "请先登录"}, ensure_ascii=False) pid = (params_kw or {}).get('project_id', '') iid = (params_kw or {}).get('iteration_id', '') if not pid and not iid: return json.dumps({"success": False, "error": "请提供 project_id 或 iteration_id"}, ensure_ascii=False) dbname = get_module_dbname('pipeline-sdlc') async with DBPools().sqlorContext(dbname) as sor: # Upsert agent_settings existing = await sor.sqlExe( "SELECT id, current_project_id, current_iteration_id FROM pipeline_agent_settings WHERE user_id=${uid}$", {"uid": uid} ) if existing: cur_pid = getattr(existing[0], 'current_project_id', '') or '' cur_iid = getattr(existing[0], 'current_iteration_id', '') or '' new_pid = pid if pid else cur_pid new_iid = iid if iid else ('' if pid else cur_iid) # If project changed but iteration not specified, clear iteration if pid and pid != cur_pid and not iid: new_iid = '' await sor.sqlExe( "UPDATE pipeline_agent_settings SET current_project_id=${pid}$, current_iteration_id=${iid}$ WHERE user_id=${uid}$", {"pid": new_pid, "iid": new_iid, "uid": uid} ) else: new_pid = pid new_iid = iid await sor.C('pipeline_agent_settings', { 'id': getID(), 'user_id': uid, 'current_project_id': new_pid, 'current_iteration_id': new_iid, }) # Look up names pname = '' iname = '' ws_dir = '' if new_pid: precs = await sor.sqlExe( "SELECT name, workspace_dir FROM sd_projects WHERE id=${pid}$", {"pid": new_pid} ) if precs and len(precs) > 0: pname = getattr(precs[0], 'name', '') or '' ws_dir = getattr(precs[0], 'workspace_dir', '') or '' if new_iid: irecs = await sor.sqlExe( "SELECT iteration_name FROM sd_iterations WHERE id=${iid}$", {"iid": new_iid} ) if irecs and len(irecs) > 0: iname = getattr(irecs[0], 'iteration_name', '') or '' # Return widget descriptor that auto-closes popup and refreshes context if pid: label = "项目「" + pname + "」" else: label = "迭代「" + iname + "」" widget = { "widgettype": "VBox", "options": {"padding": "16px", "alignItems": "center", "gap": "8px"}, "subwidgets": [ {"widgettype": "Text", "options": {"text": "\u2713 \u5df2\u8bbe\u7f6e", "cfontsize": 1.2, "color": "#16a34a", "fontWeight": "bold"}}, {"widgettype": "Text", "options": {"text": label, "cfontsize": 0.95, "color": "#475569"}}, {"widgettype": "Text", "options": {"text": "\u5f39\u7a97\u5c06\u81ea\u52a8\u5173\u95ed", "cfontsize": 0.8, "color": "#94a3b8"}}, ], "binds": [{ "wid": "self", "event": "render", "actiontype": "script", "target": "self", "script": "setTimeout(function(){var pps=document.querySelectorAll('.popup-window');for(var i=0;i