From 7842d2570fc1649e5308006b2da863bd5d0b8321 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 24 Aug 2026 16:40:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(agent):=20=E5=B7=A5=E4=BD=9C=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E6=8E=A7=E4=BB=B6=E6=8C=89=E4=BC=9A=E8=AF=9D=E4=BC=A0?= =?UTF-8?q?=E9=80=92session=5Fid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - agent_menus.dspy 按 session 解析项目 + 工作空间按钮URL拼 session_id - index.ui 默认tab/新建会话 tab 的 agent_menus urlwidget 带 session_id --- wwwroot/agent/index.ui | 4 ++-- wwwroot/api/agent_menus.dspy | 29 +++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/wwwroot/agent/index.ui b/wwwroot/agent/index.ui index 961b74b..d84c506 100644 --- a/wwwroot/agent/index.ui +++ b/wwwroot/agent/index.ui @@ -18,7 +18,7 @@ "event": "click", "actiontype": "script", "target": "self", - "script": "var tp=bricks.getWidgetById('session_tabs',bricks.app);if(!tp)return;var sid='s'+Date.now()+'_'+Math.floor(Math.random()*100000);var n=tp.opts.items.length+1;tp.open_tab({name:'session_'+sid,label:'会话 '+n,removable:true,content:{widgettype:'VBox',options:{css:'filler',width:'100%',height:'100%'},subwidgets:[{widgettype:'urlwidget',options:{url:'/pipeline_core/api/agent_menus.dspy',method:'GET'}},{widgettype:'AgentIO',options:{css:'filler',margin:'0 24px 24px 24px',url:'/pipeline_core/api/agent_chat.dspy?session_id='+sid,model_dataurl:'/pipeline_core/api/agent_model_options.dspy',model_cwidth:14,placeholder:'输入你的需求...'}}]}});" + "script": "var tp=bricks.getWidgetById('session_tabs',bricks.app);if(!tp)return;var sid='s'+Date.now()+'_'+Math.floor(Math.random()*100000);var n=tp.opts.items.length+1;tp.open_tab({name:'session_'+sid,label:'会话 '+n,removable:true,content:{widgettype:'VBox',options:{css:'filler',width:'100%',height:'100%'},subwidgets:[{widgettype:'urlwidget',options:{url:'/pipeline_core/api/agent_menus.dspy?session_id='+sid,method:'GET'}},{widgettype:'AgentIO',options:{css:'filler',margin:'0 24px 24px 24px',url:'/pipeline_core/api/agent_chat.dspy?session_id='+sid,model_dataurl:'/pipeline_core/api/agent_model_options.dspy',model_cwidth:14,placeholder:'输入你的需求...'}}]}});" }] } ] @@ -42,7 +42,7 @@ "subwidgets": [ { "widgettype": "urlwidget", - "options": {"url": "{{entire_url('/pipeline_core/api/agent_menus.dspy')}}", "method": "GET"} + "options": {"url": "{{entire_url('/pipeline_core/api/agent_menus.dspy')}}?session_id=default", "method": "GET"} }, { "widgettype": "AgentIO", diff --git a/wwwroot/api/agent_menus.dspy b/wwwroot/api/agent_menus.dspy index 6c3009e..ed7e492 100644 --- a/wwwroot/api/agent_menus.dspy +++ b/wwwroot/api/agent_menus.dspy @@ -7,16 +7,30 @@ uid = await get_user() if not uid: uid = 'user-01' -# 1. 解析当前产线:用户当前项目 → sd_projects.pipeline_id +# 会话内唯一标识(web 多 tab;工作空间按钮按会话解析项目) +session_id = (params_kw or {}).get('session_id', '') or '' + +# 1. 解析当前产线:当前会话项目 → sd_projects.pipeline_id pipeline_id = '' pid = '' 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 '' + # 按会话解析项目:session 表优先,回退全局(多 tab 各自项目,互不覆盖) + if session_id: + try: + _srecs = await sor.sqlExe( + "SELECT current_project_id FROM pipeline_session_settings " + "WHERE user_id=${u}$ AND session_id=${s}$", + {"u": uid, "s": session_id}) + pid = getattr(_srecs[0], 'current_project_id', '') if _srecs else '' + except Exception: + pid = '' + if not pid: + 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}) @@ -61,10 +75,13 @@ def _bind(url, require_project): } # 固定「工作空间」按钮(通用能力,所有 agent 都有;依赖当前项目) +_ws_url = entire_url("/pipeline-sdlc/api/workspace_popup.dspy") +if session_id: + _ws_url += "?session_id=" + session_id buttons.append({ "widgettype": "Button", "options": {"label": "🗂 工作空间", "css": "small", "id": "menu_btn_ws"}, - "binds": [_bind(entire_url("/pipeline-sdlc/api/workspace_popup.dspy"), True)], + "binds": [_bind(_ws_url, True)], }) for i, m in enumerate(menus):