feat: 작업실 채팅 세션을 프로젝트별로 분리
기존엔 앱 전체 공용 세션(ws_main/랜덤 id) 하나를 써서 프로젝트를 바꿔도 옛 프로젝트의 대화가 그대로 남았다. sessionId를 'ws_'+projectId로 결정적 파생하도록 바꿔 프로젝트마다 독립된 대화를 갖고, 새로고침/재접속에도 같은 프로젝트의 대화를 이어받는다. ws_ 접두어는 유지(tool-scope 도구 개방 + 메인 사이드바 제외 근거). 프로젝트 전환/생성/삭제 시 채팅창을 해당 세션 기록으로 리셋(refreshChatForProject), 연속 전환 레이스는 시퀀스 가드로 처리. 앱세션 저장소(app-sessions.json) 의존 제거. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -381,6 +381,7 @@ function switchProject(id){
|
||||
clearStlSelection();
|
||||
refreshAllPanes();
|
||||
scheduleSave();
|
||||
refreshChatForProject();
|
||||
if(document.getElementById('pane-files').classList.contains('active'))loadFiles();
|
||||
}
|
||||
|
||||
@@ -394,6 +395,7 @@ function createProjectPrompt(){
|
||||
clearStlSelection();
|
||||
refreshAllPanes();
|
||||
scheduleSave();
|
||||
refreshChatForProject();
|
||||
if(document.getElementById('pane-files').classList.contains('active'))loadFiles();
|
||||
}
|
||||
|
||||
@@ -408,6 +410,7 @@ function deleteProjectPrompt(){
|
||||
clearStlSelection();
|
||||
refreshAllPanes();
|
||||
scheduleSave();
|
||||
refreshChatForProject();
|
||||
if(document.getElementById('pane-files').classList.contains('active'))loadFiles();
|
||||
}
|
||||
|
||||
@@ -1050,26 +1053,26 @@ function onNotesChange(){
|
||||
}
|
||||
|
||||
// ── 채팅 패널 ─────────────────────────────────────────────────────────────────
|
||||
// 세션ID를 "ws_"로 시작하게 만들어서 tool-scope.ts가 이 세션에서는 키워드 없이도
|
||||
// workshop_project 도구를 항상 열어주게 한다(doctor/lawyer 앱과 같은 패턴).
|
||||
const APP_KEY='ws';
|
||||
let _sessionId=null;
|
||||
function getSessionId(){return _sessionId||'ws_main';}
|
||||
async function initSessionId(){
|
||||
try{const r=await fetch('/api/user/app-sessions',{headers:authH()});if(r.ok){const d=await r.json();if(d[APP_KEY]){_sessionId=d[APP_KEY];return;}}}catch{}
|
||||
_sessionId='ws_'+Math.random().toString(36).slice(2,12);
|
||||
try{await fetch('/api/user/app-sessions',{method:'PUT',headers:authH({'Content-Type':'application/json'}),body:JSON.stringify({appKey:APP_KEY,sessionId:_sessionId})});}catch{}
|
||||
// 세션ID를 프로젝트별로 분리한다("ws_" 접두어는 유지 — tool-scope.ts가 이 세션에서는
|
||||
// 키워드 없이도 workshop_project 도구를 항상 열어주고, 메인 사이드바 목록에서도 걸러진다).
|
||||
// projectId 기반 결정적 파생이므로 앱세션 저장소(app-sessions.json) 없이도 새로고침/
|
||||
// 재접속 시 같은 프로젝트의 이전 대화를 그대로 이어받는다. 옛 앱 전용 세션(ws_main/랜덤id)의
|
||||
// 대화는 앱 전체 공용이던 터라 프로젝트 귀속이 불가 — 어느 프로젝트에도 더 안 보인다.
|
||||
function getSessionId(){
|
||||
const proj=currentProject();
|
||||
return 'ws_'+(proj?proj.id:'noproject');
|
||||
}
|
||||
|
||||
let _chatLoadSeq=0;
|
||||
async function loadHistory(){
|
||||
const sid=getSessionId();
|
||||
if(!sid||sid.endsWith('_main'))return;
|
||||
const seq=++_chatLoadSeq;
|
||||
try{
|
||||
const r=await fetch('/api/chat/sessions/'+encodeURIComponent(sid),{headers:authH()});
|
||||
if(!r.ok)return;
|
||||
const d=await r.json();
|
||||
const msgs=(d.history||[]).filter(m=>m.role==='user'||m.role==='assistant');
|
||||
if(!msgs.length)return;
|
||||
if(!msgs.length||seq!==_chatLoadSeq)return;
|
||||
for(const m of msgs.slice(-30)){
|
||||
if(m.role==='user')addMsg('user',escHtml(m.content||''));
|
||||
else addMsg('assistant',renderMd(m.content||''));
|
||||
@@ -1119,6 +1122,18 @@ function renderMd(text){
|
||||
return s;
|
||||
}
|
||||
|
||||
function chatGreeting(){
|
||||
return '🛠️ 작업실 채팅입니다. 현재 프로젝트: "'+(currentProject()?.name||'')+'". 부품 구매/상태 변경, 작업 완료 체크, 예산 확인, 새 프로젝트 생성 등을 물어보세요.';
|
||||
}
|
||||
|
||||
// 프로젝트 전환(수동/생성/삭제) 시 채팅창을 그 프로젝트의 세션 기록으로 리셋한다 —
|
||||
// 세션ID가 프로젝트별로 분리돼 있으므로 여기서 지우고 다시 당겨오는 것으로 충분하다.
|
||||
async function refreshChatForProject(){
|
||||
document.getElementById('chat-msgs').innerHTML='';
|
||||
await loadHistory();
|
||||
addMsg('system',chatGreeting());
|
||||
}
|
||||
|
||||
async function sendMessage(){
|
||||
const input=document.getElementById('chat-input');
|
||||
const msg=input.value.trim();
|
||||
@@ -1257,10 +1272,9 @@ document.addEventListener('click',(e)=>{
|
||||
if(!(await checkAuth()))return;
|
||||
{const tb=document.getElementById('theme-btn');if(tb)tb.textContent=document.documentElement.getAttribute('data-theme')==='light'?'☀️':'🌙';}
|
||||
await loadWorkshopData();
|
||||
await initSessionId();
|
||||
await loadHistory();
|
||||
loadModelPill();
|
||||
addMsg('system','🛠️ 작업실 채팅입니다. 현재 프로젝트: "'+(currentProject()?.name||'')+'". 부품 구매/상태 변경, 작업 완료 체크, 예산 확인, 새 프로젝트 생성 등을 물어보세요.');
|
||||
addMsg('system',chatGreeting());
|
||||
document.getElementById('chat-input').focus();
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user