@@ -17,6 +17,7 @@ let sessionSearchCache = {};
1717let answerDraftCache = { } ;
1818let activeSessionId = '' ;
1919let activeChatMessages = [ ] ;
20+ let temporaryChat = false ;
2021let chatCanvasDraft = '' ;
2122let chatCanvasVersions = [ ] ;
2223let chatCanvasVersionIndex = - 1 ;
@@ -1666,7 +1667,7 @@ function renderChat(){
16661667 ${ renderContextPackPanel ( ) }
16671668 </aside>
16681669 <section class="chat-stage">
1669- <div class="chat-stage-head"><div><span>Data Agent</span><b id="chatSessionTitle">新对话</b></div><div class="chat-stage-actions"><div class="tool-strip" id="toolMode"><button class="active" data-mode="auto" onclick="setToolMode('auto',this)">自动</button><button data-mode="analysis" onclick="setToolMode('analysis',this)">分析</button><button data-mode="sql" onclick="setToolMode('sql',this)">SQL</button><button data-mode="codex" onclick="setToolMode('codex',this)">Codex</button></div><div class="brief-strip" aria-label="会话 Brief 操作"><button onclick="writeChatBriefToCanvas(this)">生成 Brief</button><button onclick="copyChatBrief(this)">复制 Brief</button><button onclick="downloadChatBriefMarkdown(this)">下载 Brief</button></div></div></div>
1670+ <div class="chat-stage-head"><div><span>Data Agent</span><b id="chatSessionTitle">${ temporaryChat ? '临时对话' : ' 新对话' } </b></div><div class="chat-stage-actions"><div class="tool-strip" id="toolMode"><button class="active" data-mode="auto" onclick="setToolMode('auto',this)">自动</button><button data-mode="analysis" onclick="setToolMode('analysis',this)">分析</button><button data-mode="sql" onclick="setToolMode('sql',this)">SQL</button><button data-mode="codex" onclick="setToolMode('codex',this)">Codex</button></div><div class="session-mode-strip" aria-label="会话保存模式"><button id="temporaryChatButton" class=" ${ temporaryChat ? 'active' : '' } " aria-pressed=" ${ temporaryChat } " onclick="toggleTemporaryChat()">临时对话 </button></div><div class="brief-strip" aria-label="会话 Brief 操作"><button onclick="writeChatBriefToCanvas(this)">生成 Brief</button><button onclick="copyChatBrief(this)">复制 Brief</button><button onclick="downloadChatBriefMarkdown(this)">下载 Brief</button></div></div></div>
16701671 <div id="chatMessages" class="chat-thread">${ chatEmptyState ( ) } </div>
16711672 <div class="composer-card">
16721673 <div id="chatContextBar">${ renderChatContextBar ( ) } </div>
@@ -1696,6 +1697,7 @@ function renderChat(){
16961697 </div>` ;
16971698 const router = agents . find ( a => a . id === 'agent_router' ) ; if ( router ) document . getElementById ( 'chatAgent' ) . value = router . id ;
16981699 syncChatContextBar ( ) ;
1700+ syncTemporaryChatControls ( ) ;
16991701 syncChatBriefControls ( ) ;
17001702 refreshChatSessions ( ) . catch ( ( ) => { document . getElementById ( 'chatSessionList' ) . innerHTML = emptyState ( '会话读取失败' , '仍可直接开始新对话。' ) } ) ;
17011703}
@@ -1734,12 +1736,28 @@ function renderChatContextBar(){
17341736 ${ chatContextChip ( '工具' , toolLabels [ ctx . toolMode ] || ctx . toolMode , '会话模式' ) }
17351737 ${ chatContextChip ( '证据' , depthLabels [ ctx . evidenceDepth ] || ctx . evidenceDepth , 'Trace' ) }
17361738 ${ chatContextChip ( '工作包' , contextPackSummaryLabel ( ) , contextPackSummaryDetail ( ) , contextPackHasContent ( ) ?'accent' :'' ) }
1739+ ${ chatContextChip ( '历史' , temporaryChat ?'临时对话' :'保存会话' , temporaryChat ?'不写入会话库 · 保留 Trace' :'可恢复 · 可搜索' , temporaryChat ?'accent' :'' ) }
17371740 </div>` ;
17381741}
17391742function syncChatContextBar ( ) {
17401743 const box = document . getElementById ( 'chatContextBar' ) ;
17411744 if ( box ) box . innerHTML = renderChatContextBar ( ) ;
17421745}
1746+ function syncTemporaryChatControls ( ) {
1747+ const button = document . getElementById ( 'temporaryChatButton' ) ;
1748+ if ( button ) {
1749+ button . classList . toggle ( 'active' , temporaryChat ) ;
1750+ button . setAttribute ( 'aria-pressed' , String ( temporaryChat ) ) ;
1751+ button . title = temporaryChat ?'临时对话不会写入会话库或消息历史,Trace 和审计仍会保留。' :'开启临时对话' ;
1752+ }
1753+ const title = document . getElementById ( 'chatSessionTitle' ) ;
1754+ if ( title && ! activeSessionId && temporaryChat ) title . innerText = '临时对话' ;
1755+ }
1756+ function toggleTemporaryChat ( ) {
1757+ temporaryChat = ! temporaryChat ;
1758+ startNewChat ( { preserveTemporary :true } ) ;
1759+ toast ( temporaryChat ?'临时对话已开启:不会写入会话库,Trace 和审计仍保留' :'临时对话已关闭:后续提问会保存为会话' ) ;
1760+ }
17431761function composerContextItems ( ) {
17441762 const q = ( composerContextFilterState . q || '' ) . trim ( ) . toLowerCase ( ) ;
17451763 const type = composerContextFilterState . type || 'all' ;
@@ -2744,7 +2762,8 @@ function selectedChatContext(){
27442762 const base = {
27452763 dataset_id :document . getElementById ( 'chatDataset' ) ?. value || null ,
27462764 tool_mode :document . querySelector ( '#toolMode button.active' ) ?. dataset . mode || 'auto' ,
2747- evidence_depth :document . getElementById ( 'traceDepth' ) ?. value || 'standard'
2765+ evidence_depth :document . getElementById ( 'traceDepth' ) ?. value || 'standard' ,
2766+ temporary_chat :temporaryChat
27482767 } ;
27492768 if ( contextPackHasContent ( ) ) base . context_pack = contextPackPayload ( ) ;
27502769 return base ;
@@ -2947,17 +2966,20 @@ function bindSessionToContextPack(id,btn){
29472966 setBusy ( btn , false ) ;
29482967 }
29492968}
2950- function startNewChat ( ) {
2969+ function startNewChat ( opts = { } ) {
2970+ if ( ! opts . preserveTemporary ) temporaryChat = false ;
29512971 activeSessionId = '' ;
29522972 activeChatMessages = [ ] ;
29532973 currentTrace = null ;
29542974 chatCanvasDraft = '' ;
29552975 chatCanvasVersions = [ ] ;
29562976 chatCanvasVersionIndex = - 1 ;
2957- const title = document . getElementById ( 'chatSessionTitle' ) ; if ( title ) title . innerText = '新对话' ;
2977+ const title = document . getElementById ( 'chatSessionTitle' ) ; if ( title ) title . innerText = temporaryChat ? '临时对话' : '新对话' ;
29582978 const box = document . getElementById ( 'chatMessages' ) ; if ( box ) box . innerHTML = chatEmptyState ( ) ;
29592979 const trace = document . getElementById ( 'traceBox' ) ; if ( trace ) trace . innerHTML = emptyState ( '暂无 Trace' , '发送问题后会显示执行状态、SQL、工具调用与步骤输出。' ) ;
29602980 setChatCanvasDraft ( '' , 'Canvas 已清空' , { record :false } ) ;
2981+ syncTemporaryChatControls ( ) ;
2982+ syncChatContextBar ( ) ;
29612983 syncChatBriefControls ( ) ;
29622984 renderSessionList ( ) ;
29632985 requestAnimationFrame ( ( ) => document . getElementById ( 'chatInput' ) ?. focus ( ) ) ;
@@ -2971,9 +2993,11 @@ async function loadChatSession(id){
29712993 try {
29722994 const session = await api ( '/api/sessions/' + id ) ;
29732995 sessionSearchCache [ session . id ] = buildSessionSearchIndex ( session ) ;
2996+ temporaryChat = false ;
29742997 activeSessionId = session . id ;
29752998 const title = document . getElementById ( 'chatSessionTitle' ) ; if ( title ) title . innerText = session . title || session . id ;
29762999 const agentSelect = document . getElementById ( 'chatAgent' ) ; if ( agentSelect && session . agent_id ) agentSelect . value = session . agent_id ;
3000+ syncTemporaryChatControls ( ) ;
29773001 syncChatContextBar ( ) ;
29783002 const messages = session . messages || [ ] ;
29793003 activeChatMessages = messages ;
@@ -3205,6 +3229,7 @@ function stopChatGeneration(btn){
32053229async function sendChat ( btn ) {
32063230 if ( chatSending ) { stopChatGeneration ( ) ; return ; }
32073231 const input = document . getElementById ( 'chatInput' ) ; const msg = input . value . trim ( ) ; if ( ! msg ) return ; const agent_id = document . getElementById ( 'chatAgent' ) . value ;
3232+ const isTemporary = temporaryChat ;
32083233 chatSending = true ;
32093234 chatAbortController = new AbortController ( ) ;
32103235 const sendButton = document . getElementById ( 'chatSendButton' ) || document . querySelector ( '#page-chat .composer-row button' ) ;
@@ -3219,17 +3244,18 @@ async function sendChat(btn){
32193244 const pendingId = 'pending-' + Date . now ( ) ;
32203245 box . innerHTML += `<div id="${ pendingId } " class="message assistant pending-message">${ inlineLoading ( 'Agent 正在路由和生成答案' ) } </div>` ;
32213246 try {
3222- const data = await api ( '/api/chat/query' , { method :'POST' , signal :chatAbortController . signal , body :JSON . stringify ( { message :msg , agent_id, session_id :activeSessionId || null , context :selectedChatContext ( ) } ) } ) ; const r = data . result || { } ;
3223- activeSessionId = data . session_id || activeSessionId ;
3224- const title = document . getElementById ( 'chatSessionTitle' ) ; if ( title ) title . innerText = sessionTitle ( { title :msg } ) ;
3247+ const data = await api ( '/api/chat/query' , { method :'POST' , signal :chatAbortController . signal , body :JSON . stringify ( { message :msg , agent_id, session_id :isTemporary ? null : ( activeSessionId || null ) , context :selectedChatContext ( ) } ) } ) ; const r = data . result || { } ;
3248+ activeSessionId = isTemporary ? '' : ( data . session_id || activeSessionId ) ;
3249+ const title = document . getElementById ( 'chatSessionTitle' ) ; if ( title ) title . innerText = isTemporary ? '临时对话' : sessionTitle ( { title :msg } ) ;
32253250 document . getElementById ( pendingId ) ?. remove ( ) ;
3226- box . innerHTML += `<div class="message assistant rich-message">${ resultHtml ( r , { session_id :activeSessionId , trace_id :data . trace_id , question :msg } ) } </div>` ;
3251+ box . innerHTML += `<div class="message assistant rich-message">${ resultHtml ( r , { session_id :isTemporary ? '' : activeSessionId , trace_id :data . trace_id , question :msg } ) } </div>` ;
32273252 activeChatMessages . push ( { role :'assistant' , content :JSON . stringify ( r ) , content_type :'agent_result' , created_at :new Date ( ) . toISOString ( ) } ) ;
3228- if ( activeSessionId ) sessionSearchCache [ activeSessionId ] = buildSessionSearchIndex ( { messages :activeChatMessages } ) ;
3253+ if ( ! isTemporary && activeSessionId ) sessionSearchCache [ activeSessionId ] = buildSessionSearchIndex ( { messages :activeChatMessages } ) ;
32293254 syncChatBriefControls ( ) ;
32303255 await openTrace ( data . trace_id ) ;
32313256 if ( ! chatCanvasValue ( ) . trim ( ) ) setChatCanvasDraft ( chatCanvasTemplate ( 'report' ) , '已根据本轮回答生成报告要点' ) ;
3232- await refreshChatSessions ( ) ;
3257+ if ( isTemporary ) renderSessionList ( ) ;
3258+ else await refreshChatSessions ( ) ;
32333259 } catch ( e ) {
32343260 const stopped = e ?. name === 'AbortError' ;
32353261 const banner = stopped
0 commit comments