@@ -1644,9 +1644,10 @@ function renderChat(){
16441644 <div class="rail-title">会话库</div>
16451645 <input id="sessionSearch" placeholder="搜索会话" value="${ esc ( chatSessionFilter . q ) } " oninput="chatSessionFilter.q=this.value;renderSessionList()" aria-label="搜索会话"/>
16461646 <div class="session-filter" role="tablist" aria-label="会话状态">
1647- <button class="${ chatSessionFilter . status === 'active' ?'active' :'' } " onclick="setSessionFilter('active',this)">活跃</button>
1648- <button class="${ chatSessionFilter . status === 'archived' ?'active' :'' } " onclick="setSessionFilter('archived',this)">归档</button>
1649- <button class="${ chatSessionFilter . status === 'all' ?'active' :'' } " onclick="setSessionFilter('all',this)">全部</button>
1647+ <button data-status="active" class="${ chatSessionFilter . status === 'active' ?'active' :'' } " onclick="setSessionFilter('active',this)">活跃</button>
1648+ <button data-status="project" class="${ chatSessionFilter . status === 'project' ?'active' :'' } " onclick="setSessionFilter('project',this)">项目</button>
1649+ <button data-status="archived" class="${ chatSessionFilter . status === 'archived' ?'active' :'' } " onclick="setSessionFilter('archived',this)">归档</button>
1650+ <button data-status="all" class="${ chatSessionFilter . status === 'all' ?'active' :'' } " onclick="setSessionFilter('all',this)">全部</button>
16501651 </div>
16511652 </div>
16521653 <div id="chatSessionList">${ inlineLoading ( '正在读取会话' ) } </div>
@@ -1890,6 +1891,7 @@ function syncContextPackPanel(){
18901891 const panel = document . getElementById ( 'contextPackPanel' ) ;
18911892 if ( panel ) panel . outerHTML = renderContextPackPanel ( ) ;
18921893 syncChatContextBar ( ) ;
1894+ renderSessionList ( ) ;
18931895}
18941896function persistContextPack ( opts = { } ) {
18951897 contextPack = normalizeContextPack ( contextPack ) ;
@@ -2520,22 +2522,26 @@ function selectedChatContext(){
25202522}
25212523function setSessionFilter ( status , btn ) {
25222524 chatSessionFilter . status = status ;
2523- document . querySelectorAll ( '.session-filter button' ) . forEach ( b => b . classList . toggle ( 'active' , b === btn || b . textContent . includes ( status === 'active' ? '活跃' : status === 'archived' ? '归档' : '全部' ) ) ) ;
2525+ document . querySelectorAll ( '.session-filter button' ) . forEach ( b => b . classList . toggle ( 'active' , b === btn || b . dataset . status === status ) ) ;
25242526 renderSessionList ( ) ;
25252527}
25262528function sessionMatches ( s ) {
25272529 const status = chatSessionFilter . status || 'active' ;
25282530 const q = ( chatSessionFilter . q || '' ) . trim ( ) . toLowerCase ( ) ;
2529- const okStatus = status === 'all' || ( s . status || 'active' ) === status ;
2530- const haystack = [ s . title , s . id , s . agent_id , s . status ] . filter ( Boolean ) . join ( ' ' ) . toLowerCase ( ) ;
2531+ const pack = normalizeContextPack ( contextPack ) ;
2532+ const okStatus = status === 'all'
2533+ || ( status === 'project' ? Boolean ( pack . sessionId && s . id === pack . sessionId ) : ( s . status || 'active' ) === status ) ;
2534+ const haystack = [ s . title , s . id , s . agent_id , s . status , pack . sessionId === s . id ?'project context pack' :'' ] . filter ( Boolean ) . join ( ' ' ) . toLowerCase ( ) ;
25312535 return okStatus && ( ! q || haystack . includes ( q ) ) ;
25322536}
25332537function sessionCard ( s ) {
25342538 const archived = ( s . status || 'active' ) === 'archived' ;
2535- return `<article class="session-item ${ s . id === activeSessionId ?'active' :'' } ${ archived ?'archived' :'' } ">
2536- <button class="session-open" onclick="loadChatSession('${ jsArg ( s . id ) } ')"><b>${ esc ( sessionTitle ( s ) ) } </b><span>${ esc ( timeText ( s . updated_at ) ) } · ${ esc ( s . agent_id || 'auto' ) } </span></button>
2539+ const linked = normalizeContextPack ( contextPack ) . sessionId === s . id ;
2540+ return `<article class="session-item ${ s . id === activeSessionId ?'active' :'' } ${ archived ?'archived' :'' } ${ linked ?'linked' :'' } ">
2541+ <button class="session-open" onclick="loadChatSession('${ jsArg ( s . id ) } ')"><b>${ esc ( sessionTitle ( s ) ) } </b><span>${ esc ( timeText ( s . updated_at ) ) } · ${ esc ( s . agent_id || 'auto' ) } ${ linked ?' · 工作包' :'' } </span></button>
25372542 <div class="session-actions">
25382543 <button title="重命名会话" onclick="renameChatSession('${ jsArg ( s . id ) } ',this)">改名</button>
2544+ <button title="${ linked ?'已绑定到工作包' :'绑定到当前工作包' } " onclick="bindSessionToContextPack('${ jsArg ( s . id ) } ',this)" ${ linked ?'disabled' :'' } >${ linked ?'已绑定' :'绑定' } </button>
25392545 <button title="${ archived ?'恢复会话' :'归档会话' } " onclick="toggleChatSessionArchive('${ jsArg ( s . id ) } ',${ archived } ,this)">${ archived ?'恢复' :'归档' } </button>
25402546 </div>
25412547 </article>` ;
@@ -2544,7 +2550,10 @@ function renderSessionList(){
25442550 const box = document . getElementById ( 'chatSessionList' ) ;
25452551 if ( ! box ) return ;
25462552 const filtered = chatSessions . filter ( sessionMatches ) ;
2547- box . innerHTML = filtered . length ?filtered . slice ( 0 , 40 ) . map ( sessionCard ) . join ( '' ) :emptyState ( '暂无匹配会话' , '调整搜索或切换活跃/归档状态。' ) ;
2553+ const empty = chatSessionFilter . status === 'project'
2554+ ? emptyState ( '暂无项目会话' , '在任一会话卡片点击“绑定”,或加载含来源会话的工作包预设。' )
2555+ : emptyState ( '暂无匹配会话' , '调整搜索或切换活跃/归档状态。' ) ;
2556+ box . innerHTML = filtered . length ?filtered . slice ( 0 , 40 ) . map ( sessionCard ) . join ( '' ) :empty ;
25482557}
25492558async function refreshChatSessions ( ) {
25502559 chatSessions = await api ( '/api/sessions' ) . catch ( ( ) => [ ] ) ;
@@ -2598,6 +2607,17 @@ async function toggleChatSessionArchive(id,isArchived,btn){
25982607 toast ( '会话状态更新失败:' + e . message ) ;
25992608 }
26002609}
2610+ function bindSessionToContextPack ( id , btn ) {
2611+ if ( ! id ) return ;
2612+ setBusy ( btn , true ) ;
2613+ try {
2614+ contextPack . sessionId = id ;
2615+ contextPack . updatedAt = new Date ( ) . toISOString ( ) ;
2616+ persistContextPack ( { toast :'会话已绑定到当前工作包' } ) ;
2617+ } finally {
2618+ setBusy ( btn , false ) ;
2619+ }
2620+ }
26012621function startNewChat ( ) {
26022622 activeSessionId = '' ;
26032623 activeChatMessages = [ ] ;
0 commit comments