Add context usage indicator to code editor session bar

세션 바에 현재 컨텍스트 토큰 추정치 / 모델 최대값 표시.
글자 수 ÷ 4 로 토큰 추정, 50% 이하 초록 / 50~80% 노랑 / 80%+ 빨강 색상 진행 바.
메시지 전송·응답 완료 시 즉시 업데이트.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kim
2026-06-06 14:33:54 +09:00
co-authored by Claude Sonnet 4.6
parent d612b32d2e
commit 1350ece55a
2 changed files with 93 additions and 27 deletions
+33
View File
@@ -2108,6 +2108,7 @@ async function codeAiSend() {
// 모델이 "기존 파일이 있다"는 맥락은 유지하되 매 턴 파일 전체를 반복하지 않음.
const historyEntry = currentFile ? `[파일: ${_clientBareFileName(currentFile.name)}] ${message}` : message;
codeAiHistory.push({ role: 'user', content: historyEntry });
try { updateSessionPanel(); } catch (_) {}
const thinkEl = codeAiAppend('thinking', '생각 중...');
@@ -2463,6 +2464,7 @@ async function codeAiSend() {
codeAiHistory.push({ role: 'assistant', content: reply || '(응답 없음)' });
_autoSaveChatSession();
if (activeProjectName) saveProjectSession(activeProjectName);
try { updateSessionPanel(); } catch (_) {}
thinkEl.classList.remove('streaming'); // Stop cursor animation
if (!reply) { thinkEl.textContent = '(응답 없음)'; }
else codeAiRenderMarkdown(thinkEl, reply);
@@ -3891,11 +3893,42 @@ function setCodeSbTab(tab) {
}
function _codeAiCtxMax() {
const m = (codeAiModel || '').toLowerCase();
if (!m || m.includes('claude')) return 200000;
// Common Ollama context windows
if (m.includes('llama3') || m.includes('llama-3') || m.includes('qwen')) return 128000;
if (m.includes('mistral') || m.includes('mixtral')) return 32000;
if (m.includes('gemma')) return 8192;
return 32000; // safe default for unknown local models
}
function updateSessionPanel() {
const barProj = document.getElementById('code-ai-session-bar-project');
const barCount = document.getElementById('code-ai-session-bar-count');
if (barProj) barProj.textContent = activeProjectName || '(전체)';
if (barCount) barCount.textContent = codeAiHistory.length ? `${codeAiHistory.length}개` : '';
// Context usage estimate
const ctxWrap = document.getElementById('code-ai-ctx-wrap');
const ctxLabel = document.getElementById('code-ai-ctx-label');
const ctxFill = document.getElementById('code-ai-ctx-fill');
if (ctxWrap && ctxLabel && ctxFill) {
const totalChars = codeAiHistory.reduce((s, m) => s + (m.content || '').length, 0);
if (totalChars === 0) {
ctxWrap.style.display = 'none';
} else {
const estTokens = Math.round(totalChars / 4);
const maxTokens = _codeAiCtxMax();
const pct = Math.min(100, Math.round(estTokens / maxTokens * 100));
const kStr = estTokens >= 1000 ? `~${(estTokens/1000).toFixed(1)}k` : `~${estTokens}`;
const maxKStr = maxTokens >= 1000 ? `${(maxTokens/1000).toFixed(0)}k` : `${maxTokens}`;
ctxLabel.textContent = `${kStr} / ${maxKStr}`;
ctxFill.style.width = pct + '%';
ctxFill.style.background = pct >= 80 ? '#ef4444' : pct >= 50 ? '#f59e0b' : '#22c55e';
ctxWrap.style.display = 'flex';
}
}
// 프로젝트 선택기 (항상 업데이트)
const sel = document.getElementById('csb-session-project-sel');
const projRow = document.getElementById('csb-session-project-row');