diff --git a/src/extension.ts b/src/extension.ts index a891e16..47dabab 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1008,40 +1008,29 @@ class SidebarChatProvider implements vscode.WebviewViewProvider { if (!this._view) { return; } const brainDir = _getBrainDir(); - const isSynced = fs.existsSync(brainDir); - const { secondBrainRepo } = getConfig(); - const statusLabel = this._brainEnabled ? '🟒 ON' : 'πŸ”΄ OFF'; + const brainFiles = fs.existsSync(brainDir) ? this._findBrainFiles(brainDir) : []; + const fileCount = brainFiles.length; - const items: any[] = []; + const items: any[] = [ + { label: `πŸ“‚ λ‚΄ 지식 파일 보기 (${fileCount}개)`, description: fileCount > 0 ? 'λ‚΄κ°€ λ„£μ–΄λ‘” 지식 λͺ©λ‘ 확인' : '아직 지식이 μ—†μŠ΅λ‹ˆλ‹€', action: 'listFiles' }, + { label: 'πŸ“ λ‚΄ λ‡Œ 폴더 λ³€κ²½ν•˜κΈ°', description: `ν˜„μž¬: ${brainDir}`, action: 'changeFolder' }, + { label: 'πŸ”„ 지식 μƒˆλ‘œκ³ μΉ¨', description: '폴더 λ‚΄μš©μ„ λ‹€μ‹œ μ½μ–΄μ˜΅λ‹ˆλ‹€', action: 'resync' }, + ]; - // 항상 κ·Έλž˜ν”„ λ·°λ₯Ό λ³Ό 수 μžˆλ„λ‘ 메뉴 μ΅œμƒλ‹¨μ— μΆ”κ°€! - items.push({ label: '🌌 지식 ꡬ쑰(Topology) μ‹œκ°ν™” 보기', description: 'ν˜„μž¬ μ›Œν¬μŠ€νŽ˜μ΄μŠ€μ˜ μ—°κ²° 지식 맡을 μ—½λ‹ˆλ‹€.', action: 'viewGraph' }); - - if (!isSynced && !secondBrainRepo) { - // 아직 ν•œ λ²ˆλ„ μ—°λ™ν•œ 적 μ—†μŒ - items.push({ label: 'πŸ”— κΉƒν—ˆλΈŒ μ—°κ²°ν•˜κΈ°', description: '지식 μ €μž₯μ†Œ GitHub URL μž…λ ₯', action: 'sync' }); - } else { - const brainFiles = fs.existsSync(brainDir) ? this._findBrainFiles(brainDir) : []; - items.push( - { label: `🧠 지식 λͺ¨λ“œ: ${statusLabel}`, description: '지식 기반 μ½”λ”© ON/OFF μ „ν™˜', action: 'toggle' }, - { label: `πŸ“‚ λ‚΄ λ‘λ‡Œ 파일 λͺ©λ‘ (${brainFiles.length}개)`, description: 'μ£Όμž…λœ 지식 파일 확인', action: 'listFiles' }, - { label: 'πŸ”„ 지식 μƒˆλ‘œκ³ μΉ¨', description: `ν˜„μž¬: ${secondBrainRepo?.split('/').pop() || 'μ—†μŒ'}`, action: 'resync' }, - { label: 'πŸ”— λ‹€λ₯Έ κΉƒν—ˆλΈŒλ‘œ λ³€κ²½', description: 'μƒˆλ‘œμš΄ 지식 μ €μž₯μ†Œ URL μž…λ ₯', action: 'change' }, - { label: 'πŸ”Œ 브레인 팩 μ—°κ²° ν•΄μ œ', description: 'λ‚΄ 컴퓨터에 μž„μ‹œ λ³΅μ‚¬λœ μ§€μ‹λ§Œ λΉ„μ›λ‹ˆλ‹€ (원본 κΉƒν—ˆλΈŒ μ•ˆμ „)', action: 'disconnect' } - ); - } - - const pick = await vscode.window.showQuickPick(items, { placeHolder: '🧠 Second Brain 관리' }); + const pick = await vscode.window.showQuickPick(items, { placeHolder: '🧠 λ‚΄ 지식 관리' }); if (!pick) return; switch (pick.action) { - case 'viewGraph': - vscode.commands.executeCommand('connect-ai-lab.showBrainNetwork'); - break; case 'listFiles': { - const brainFiles = fs.existsSync(brainDir) ? this._findBrainFiles(brainDir) : []; - if (brainFiles.length === 0) { - vscode.window.showInformationMessage('πŸ“‚ λ‘λ‡Œμ— μ €μž₯된 파일이 μ—†μŠ΅λ‹ˆλ‹€. μ›Ήμ‚¬μ΄νŠΈμ—μ„œ Brain Pack을 μ£Όμž…ν•˜μ„Έμš”!'); + if (fileCount === 0) { + const action = await vscode.window.showInformationMessage( + 'πŸ“‚ 아직 지식이 μ—†μŠ΅λ‹ˆλ‹€. λ‡Œ 폴더에 .md νŒŒμΌμ„ λ„£μ–΄μ£Όμ„Έμš”!', + 'πŸ“ λ‡Œ 폴더 μ—΄κΈ°' + ); + if (action === 'πŸ“ λ‡Œ 폴더 μ—΄κΈ°') { + if (!fs.existsSync(brainDir)) fs.mkdirSync(brainDir, { recursive: true }); + vscode.commands.executeCommand('revealFileInOS', vscode.Uri.file(brainDir)); + } } else { const fileItems = brainFiles.slice(0, 50).map(f => { const rel = path.relative(brainDir, f); @@ -1050,7 +1039,7 @@ class SidebarChatProvider implements vscode.WebviewViewProvider { return { label: `πŸ“„ ${rel}`, description: title, filePath: f }; }); const selected = await vscode.window.showQuickPick(fileItems, { - placeHolder: `πŸ“‚ λ‚΄ λ‘λ‡Œ 파일 (총 ${brainFiles.length}개)` + placeHolder: `πŸ“‚ λ‚΄ 지식 파일 (총 ${fileCount}개) β€” ν΄λ¦­ν•˜λ©΄ λ‚΄μš©μ„ λ³Ό 수 μžˆμ–΄μš”` }); if (selected) { const doc = await vscode.workspace.openTextDocument(selected.filePath); @@ -1059,41 +1048,33 @@ class SidebarChatProvider implements vscode.WebviewViewProvider { } break; } - case 'sync': - await this._syncSecondBrain(); - break; - case 'toggle': - this._brainEnabled = !this._brainEnabled; - this._ctx.globalState.update('brainEnabled', this._brainEnabled); - const state = this._brainEnabled ? '🟒 ON β€” 지식 기반 μ½”λ”© ν™œμ„±ν™”!' : 'πŸ”΄ OFF β€” 일반 λͺ¨λ“œ'; - vscode.window.showInformationMessage(`🧠 Second Brain: ${state}`); - this._view.webview.postMessage({ type: 'response', value: `🧠 **지식 λͺ¨λ“œ ${this._brainEnabled ? 'ON' : 'OFF'}** β€” ${this._brainEnabled ? 'μ΄μ œλΆ€ν„° νšŒμ›λ‹˜μ˜ 지식을 λ°”νƒ•μœΌλ‘œ λͺ¨λ“  닡변을 μƒμ„±ν•©λ‹ˆλ‹€.' : '일반 AI λͺ¨λ“œλ‘œ μ „ν™˜λ˜μ—ˆμŠ΅λ‹ˆλ‹€.'}` }); - break; - case 'resync': - await this._syncSecondBrain(); - break; - case 'change': - // κΈ°μ‘΄ URL을 μ§€μš°κ³  μƒˆλ‘œ μž…λ ₯λ°›κΈ° - const newUrl = await vscode.window.showInputBox({ - prompt: '🧠 μƒˆλ‘œμš΄ 지식 μ €μž₯μ†Œ κΉƒν—ˆλΈŒ URL을 μž…λ ₯ν•˜μ„Έμš”', - placeHolder: '예: https://github.com/μ‚¬μš©μž/μƒˆμ €μž₯μ†Œ', - value: secondBrainRepo + case 'changeFolder': { + const folders = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: '이 폴더λ₯Ό λ‚΄ λ‡Œλ‘œ μ‚¬μš©ν•˜κΈ°', + title: 'πŸ“ AIμ—κ²Œ μ½ν˜€μ€„ 지식(.md 파일)이 λ“€μ–΄μžˆλŠ” 폴더λ₯Ό μ„ νƒν•˜μ„Έμš”' }); - if (!newUrl) return; - await vscode.workspace.getConfiguration('connectAiLab').update('secondBrainRepo', newUrl, vscode.ConfigurationTarget.Global); - vscode.window.showInformationMessage('βœ… μƒˆλ‘œμš΄ κΉƒν—ˆλΈŒ μ£Όμ†Œκ°€ μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 동기화λ₯Ό μ‹œμž‘ν•©λ‹ˆλ‹€!'); - await this._syncSecondBrain(); - break; - case 'disconnect': - const confirm = await vscode.window.showWarningMessage('κΉƒν—ˆλΈŒ μžλ™ μ—°λ™λ§Œ ν•΄μ œν•©λ‹ˆλ‹€. (기쑴에 λ‹€μš΄λ‘œλ“œ/μ£Όμž…λœ 지식은 λ‘œμ»¬μ— μ•ˆμ „ν•˜κ²Œ λ³΄μ‘΄λ©λ‹ˆλ‹€.)', 'μ—°κ²° ν•΄μ œ', 'μ·¨μ†Œ'); - if (confirm === 'μ—°κ²° ν•΄μ œ') { - await vscode.workspace.getConfiguration('connectAiLab').update('secondBrainRepo', '', vscode.ConfigurationTarget.Global); - this._brainEnabled = false; - this._ctx.globalState.update('brainEnabled', false); - vscode.window.showInformationMessage('βœ… κΉƒν—ˆλΈŒ 연동이 ν•΄μ œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 둜컬 μ˜€ν”„λΌμΈ λͺ¨λ“œλ‘œ λ³΄ν˜Έλ©λ‹ˆλ‹€.'); - this._view.webview.postMessage({ type: 'response', value: `❌ **κΉƒν—ˆλΈŒ 연동 ν•΄μ œ** β€” 기쑴의 μ˜€ν”„λΌμΈ 지식은 μœ μ§€λ©λ‹ˆλ‹€.` }); + if (folders && folders.length > 0) { + const selectedPath = folders[0].fsPath; + await vscode.workspace.getConfiguration('connectAiLab').update('localBrainPath', selectedPath, vscode.ConfigurationTarget.Global); + this._brainEnabled = true; + this._ctx.globalState.update('brainEnabled', true); + const newFiles = this._findBrainFiles(selectedPath); + vscode.window.showInformationMessage(`βœ… λ‡Œ 폴더가 λ³€κ²½λ˜μ—ˆμŠ΅λ‹ˆλ‹€! (${newFiles.length}개 지식 파일 발견)`); + this._view.webview.postMessage({ type: 'response', value: `🧠 **λ‡Œ 폴더 μ—°κ²° μ™„λ£Œ!**\nπŸ“ ${selectedPath}\nπŸ“„ ${newFiles.length}개의 지식 νŒŒμΌμ„ 읽어듀이고 μžˆμŠ΅λ‹ˆλ‹€.` }); } break; + } + case 'resync': { + this._brainEnabled = true; + this._ctx.globalState.update('brainEnabled', true); + const refreshedFiles = this._findBrainFiles(brainDir); + vscode.window.showInformationMessage(`πŸ”„ 지식 μƒˆλ‘œκ³ μΉ¨ μ™„λ£Œ! (${refreshedFiles.length}개 파일)`); + this._view.webview.postMessage({ type: 'response', value: `πŸ”„ **지식 μƒˆλ‘œκ³ μΉ¨ μ™„λ£Œ!** ${refreshedFiles.length}개 파일이 μ—°κ²°λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.\n\n지식 λͺ¨λ“œκ°€ ON λ˜μ—ˆμŠ΅λ‹ˆλ‹€.` }); + break; + } } }