Merge PR #7765 into stage/7765-subagent-project
This commit is contained in:
commit
3f85d3bbc4
7 files changed
+266
-20
No files matched your search
+58
-9
@@ -7671,7 +7671,50 @@ function _sidebarRowHasVisibleMessages(s, activeSidForSidebar){
|
||||
(S.session&&s.session_id===S.session.session_id&&(S.session.message_count||0)>0);
|
||||
}
|
||||
|
||||
function _isDelegatedSubagentRow(s){
|
||||
if(!_isChildSession(s)) return false;
|
||||
const role=[s.raw_source,s.source_tag,s.source].map(v=>String(v||'').trim().toLowerCase()).find(Boolean)||'';
|
||||
return role==='subagent';
|
||||
}
|
||||
|
||||
// Delegated subagents without a project_id take their nearest ancestor's project;
|
||||
// every other row keeps its own. Memoized per render, so each lineage resolves once.
|
||||
function _sidebarProjectResolver(rowsById){
|
||||
const memo=new Map();
|
||||
return function projectIdFor(s){
|
||||
if(!s) return null;
|
||||
const path=[];
|
||||
const onPath=new Set();
|
||||
let cur=s, result=null;
|
||||
while(cur){
|
||||
const sid=cur.session_id;
|
||||
if(memo.has(sid)){ result=memo.get(sid); break; }
|
||||
if(cur.project_id||!_isDelegatedSubagentRow(cur)){ result=cur.project_id||null; if(sid) path.push(sid); break; }
|
||||
if(onPath.has(sid)) break;
|
||||
onPath.add(sid); path.push(sid);
|
||||
cur=rowsById?rowsById.get(cur.parent_session_id):null;
|
||||
}
|
||||
for(const sid of path) memo.set(sid,result);
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
function _sidebarRowsById(rows){
|
||||
const byId=new Map();
|
||||
for(const list of rows){
|
||||
if(!Array.isArray(list)) continue;
|
||||
for(const s of list) if(s&&s.session_id&&!byId.has(s.session_id)) byId.set(s.session_id,s);
|
||||
}
|
||||
return byId;
|
||||
}
|
||||
|
||||
// True when any row resolves to no project, using the filter's own ancestor map.
|
||||
function _sidebarHasUnprojectedRows(rows, projectIdFor){
|
||||
return rows.some(s=>!projectIdFor(s));
|
||||
}
|
||||
|
||||
function _partitionSidebarSessionRows(allMatched, activeSidForSidebar){
|
||||
const projectIdFor=_sidebarProjectResolver(_sidebarRowsById([allMatched, typeof _sidebarReferenceSessions!=='undefined'?_sidebarReferenceSessions:null]));
|
||||
let cliSessionCount=0;
|
||||
const webuiProfileFiltered=[];
|
||||
const cliProfileFiltered=[];
|
||||
@@ -7690,10 +7733,11 @@ function _partitionSidebarSessionRows(allMatched, activeSidForSidebar){
|
||||
const referenceRaw=isCli ? cliReferenceRaw : webuiReferenceRaw;
|
||||
const sessionsRaw=isCli ? cliSessionsRaw : webuiSessionsRaw;
|
||||
profileFiltered.push(s);
|
||||
const projectId=projectIdFor(s);
|
||||
if(_activeProject===NO_PROJECT_FILTER){
|
||||
if(s.project_id) continue;
|
||||
if(projectId) continue;
|
||||
} else if(_activeProject){
|
||||
if(s.project_id!==_activeProject) continue;
|
||||
if(projectId!==_activeProject) continue;
|
||||
}
|
||||
referenceRaw.push(s);
|
||||
if(s.archived){
|
||||
@@ -7717,6 +7761,7 @@ function _partitionSidebarSessionRows(allMatched, activeSidForSidebar){
|
||||
cliReferenceRaw,
|
||||
webuiSessionsRaw,
|
||||
cliSessionsRaw,
|
||||
projectIdFor,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7728,15 +7773,18 @@ function _partitionSidebarSessionRows(allMatched, activeSidForSidebar){
|
||||
// suppression context — silently hiding a visible child/fork whose archived
|
||||
// ancestor lives outside the current view. Scope the references to the same
|
||||
// project + source bucket as the render they feed before using them.
|
||||
function _scopedSidebarReferenceRows(isCli){
|
||||
// projectIdFor: the render's shared resolver; standalone callers get one over references + _allSessions.
|
||||
function _scopedSidebarReferenceRows(isCli, projectIdFor){
|
||||
if(typeof _sidebarReferenceSessions==='undefined'||!Array.isArray(_sidebarReferenceSessions)||!_sidebarReferenceSessions.length) return [];
|
||||
const resolve=projectIdFor||_sidebarProjectResolver(_sidebarRowsById([_sidebarReferenceSessions, typeof _allSessions!=='undefined'?_allSessions:null]));
|
||||
return _sidebarReferenceSessions.filter(s=>{
|
||||
if(!s) return false;
|
||||
// Source scope: only references in the same webui/cli bucket as this render.
|
||||
if(_isCliSession(s)!==!!isCli) return false;
|
||||
// Project scope: mirror _partitionSidebarSessionRows exactly.
|
||||
if(_activeProject===NO_PROJECT_FILTER){ if(s.project_id) return false; }
|
||||
else if(_activeProject){ if(s.project_id!==_activeProject) return false; }
|
||||
const projectId=resolve(s);
|
||||
if(_activeProject===NO_PROJECT_FILTER){ if(projectId) return false; }
|
||||
else if(_activeProject){ if(projectId!==_activeProject) return false; }
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -7842,19 +7890,20 @@ function renderSessionListFromCache(){
|
||||
cliReferenceRaw,
|
||||
webuiSessionsRaw,
|
||||
cliSessionsRaw,
|
||||
projectIdFor,
|
||||
}=_partitionSidebarSessionRows(allMatched, activeSidForSidebar);
|
||||
const referenceRaw=_sessionSourceFilter==='cli'?cliReferenceRaw:webuiReferenceRaw;
|
||||
const isCliView=_sessionSourceFilter==='cli';
|
||||
const sessions=_renderSidebarRowsFromRawSessions(sessionsRaw, [...referenceRaw, ..._scopedSidebarReferenceRows(isCliView)]);
|
||||
const sessions=_renderSidebarRowsFromRawSessions(sessionsRaw, [...referenceRaw, ..._scopedSidebarReferenceRows(isCliView, projectIdFor)]);
|
||||
// Server-provided source bucket counts are authoritative for the current
|
||||
// payload. When present, skip the expensive cross-bucket render/count pass;
|
||||
// null is a deliberate "not computed" sentinel consumed only by
|
||||
// _sessionSourceTabCount's fallback path below.
|
||||
const renderedWebuiSessionCount=_serverWebuiSessionCount===null
|
||||
? _renderSidebarRowsFromRawSessions(webuiSessionsRaw, [...webuiReferenceRaw, ..._scopedSidebarReferenceRows(false)]).length
|
||||
? _renderSidebarRowsFromRawSessions(webuiSessionsRaw, [...webuiReferenceRaw, ..._scopedSidebarReferenceRows(false, projectIdFor)]).length
|
||||
: null;
|
||||
const renderedCliSessionCount=_serverCliSessionCount===null
|
||||
? _renderSidebarRowsFromRawSessions(cliSessionsRaw, [...cliReferenceRaw, ..._scopedSidebarReferenceRows(true)]).length
|
||||
? _renderSidebarRowsFromRawSessions(cliSessionsRaw, [...cliReferenceRaw, ..._scopedSidebarReferenceRows(true, projectIdFor)]).length
|
||||
: null;
|
||||
const webuiSessionTabCount=_sessionSourceTabCount('webui', renderedWebuiSessionCount, renderedCliSessionCount);
|
||||
const cliSessionTabCount=_sessionSourceTabCount('cli', renderedWebuiSessionCount, renderedCliSessionCount);
|
||||
@@ -7916,7 +7965,7 @@ function renderSessionListFromCache(){
|
||||
}
|
||||
// Project filter bar — show when there are real projects OR there are
|
||||
// unassigned sessions (so the Unassigned chip has something to filter to).
|
||||
const hasUnprojected=profileFiltered.some(s=>!s.project_id);
|
||||
const hasUnprojected=_sidebarHasUnprojectedRows(profileFiltered, projectIdFor);
|
||||
if(_allProjects.length>0||hasUnprojected){
|
||||
const bar=document.createElement('div');
|
||||
bar.className='project-bar';
|
||||
|
||||
Reference in new issue
Block a user