# agent_menus.dspy - 返回当前产线的功能菜单(AgentIO 上方菜单/按钮) # 由 core 通用 agent 的 index.ui 通过 urlwidget 加载,动态渲染产线固化的联机功能入口 import json as _json uid = await get_user() if not uid: uid = 'user-01' # 1. 解析当前产线:用户当前项目 → sd_projects.pipeline_id pipeline_id = '' try: dbname = get_module_dbname('pipeline_core') async with DBPools().sqlorContext(dbname) as sor: recs = await sor.sqlExe( "SELECT current_project_id FROM pipeline_agent_settings WHERE user_id=${u}$", {"u": uid}) pid = getattr(recs[0], 'current_project_id', '') if recs else '' if pid: precs = await sor.sqlExe( "SELECT pipeline_id FROM sd_projects WHERE id=${p}$", {"p": pid}) if precs: pipeline_id = getattr(precs[0], 'pipeline_id', '') or '' except Exception: pass if not pipeline_id: try: from pipeline_core import DEFAULT_ABILITY_ID pipeline_id = DEFAULT_ABILITY_ID except Exception: pipeline_id = 'sdlc_general' # 2. 读产线功能菜单 try: from pipeline_core.ability import get_ability_menus menus = get_ability_menus(pipeline_id) except Exception: menus = [] # 3. 构建菜单按钮(actiontype=urlwidget 打开通用弹窗 agent_menu_open,控制弹窗大小) import urllib.parse as _urlparse buttons = [] # 固定「工作空间」按钮(通用能力,所有 agent 都有) buttons.append({ "widgettype": "Button", "options": {"label": "🗂 工作空间", "css": "small", "id": "menu_btn_ws"}, "binds": [{ "wid": "self", "event": "click", "actiontype": "urlwidget", "target": "self", "options": {"url": "/pipeline-sdlc/api/workspace_popup.dspy"}, }], }) for i, m in enumerate(menus): label = str(m.get("label", "") or "") url = str(m.get("url", "") or "") if not url: continue cwidth = str(m.get("cwidth", "62") or "62") cheight = str(m.get("cheight", "32") or "32") query = _urlparse.urlencode({"url": url, "title": label, "cwidth": cwidth, "cheight": cheight}) open_url = "/pipeline_core/api/agent_menu_open.dspy?" + query buttons.append({ "widgettype": "Button", "options": {"label": label, "css": "small", "id": "menu_btn_%d" % i}, "binds": [{ "wid": "self", "event": "click", "actiontype": "urlwidget", "target": "self", "options": {"url": open_url}, }], }) return _json.dumps({ "widgettype": "HBox", "options": {"width": "100%", "padding": "0 24px 8px 24px", "gap": "8px", "alignItems": "center"}, "subwidgets": buttons, }, ensure_ascii=False)