chore: version up to v2.80.30 and package vsix

This commit is contained in:
g1nation
2026-05-11 12:44:38 +09:00
parent 789680ccb1
commit 3c2b62c018
9 changed files with 678 additions and 4 deletions
+122
View File
@@ -515,6 +515,128 @@
color: var(--text-bright);
}
/* --- Agent Map Modal --- */
.map-agent-row {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
margin-bottom: 14px;
}
.map-agent-name {
font-size: 13px;
font-weight: 700;
color: var(--text-bright);
}
.map-section {
margin-bottom: 16px;
padding: 12px;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 10px;
}
.map-section-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 12px;
margin-bottom: 10px;
}
.map-section-title {
font-size: 12px;
font-weight: 800;
color: var(--text-bright);
margin-bottom: 4px;
}
.map-section-hint {
font-size: 10.5px;
color: var(--text-dim);
line-height: 1.4;
max-width: 360px;
}
.map-btn-group {
display: flex;
gap: 6px;
flex-shrink: 0;
}
.map-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 6px;
}
.map-list:empty::before {
content: '아직 연결된 항목이 없습니다.';
font-size: 11px;
color: var(--text-dim);
font-style: italic;
padding: 8px 4px;
display: block;
}
.map-item {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 10px;
background: var(--input-bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 11.5px;
color: var(--text-primary);
}
.map-item-icon {
flex-shrink: 0;
font-size: 13px;
}
.map-item-path {
flex: 1;
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;
font-size: 11px;
word-break: break-all;
color: var(--text-bright);
}
.map-item-meta {
font-size: 10px;
color: var(--text-dim);
}
.map-item-remove {
background: transparent;
border: 1px solid var(--border);
color: var(--text-dim);
border-radius: 4px;
padding: 2px 6px;
font-size: 11px;
cursor: pointer;
}
.map-item-remove:hover {
border-color: var(--error);
color: var(--error);
}
.map-footer {
display: flex;
gap: 8px;
align-items: center;
margin-top: 10px;
padding-top: 12px;
border-top: 1px solid var(--border);
}
.map-footer .send-btn {
min-width: 80px;
}
.map-status {
margin-top: 10px;
font-size: 11px;
min-height: 16px;
color: var(--text-dim);
}
.map-status.ok { color: var(--success); }
.map-status.error { color: var(--error); }
/* --- Physics & Micro-interactions --- */
button {
transition: all 0.15s cubic-bezier(0.4, 0, 0.2, 1);
+51
View File
@@ -82,6 +82,57 @@
<div id="historyList" style="flex:1; overflow-y:auto;"></div>
</div>
<div id="agentMapOverlay" class="history-overlay">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:14px;">
<div>
<h2 style="color:var(--text-bright); margin:0;">Agent Mapping</h2>
<p style="margin:4px 0 0; font-size:11px; color:var(--text-dim);">
선택한 에이전트에 <strong>지식 폴더</strong><strong>외부 스킬 폴더/파일</strong>을 연결합니다.
</p>
</div>
<button class="icon-btn" id="closeAgentMapBtn"></button>
</div>
<div class="map-agent-row">
<div class="field-label">Agent</div>
<div id="agentMapAgentName" class="map-agent-name">(선택된 에이전트가 없습니다)</div>
</div>
<div class="map-section">
<div class="map-section-head">
<div>
<div class="map-section-title">📚 Knowledge Folders</div>
<div class="map-section-hint">Brain 안에서 검색(RAG)에 사용할 폴더입니다. 폴더가 Brain 외부면 자동으로 제외됩니다.</div>
</div>
<button class="secondary-btn" id="addKnowledgeFolderBtn">+ 폴더 추가</button>
</div>
<ul id="knowledgeFolderList" class="map-list"></ul>
</div>
<div class="map-section">
<div class="map-section-head">
<div>
<div class="map-section-title">🛠 External Skills</div>
<div class="map-section-hint">.md 스킬 파일이 들어 있는 폴더 또는 개별 .md 파일을 연결하세요. 채팅 시 항상 함께 로드됩니다.</div>
</div>
<div class="map-btn-group">
<button class="secondary-btn" id="addSkillFolderBtn">+ 폴더 추가</button>
<button class="secondary-btn" id="addSkillFileBtn">+ 파일 추가</button>
</div>
</div>
<ul id="skillFolderList" class="map-list"></ul>
</div>
<div class="map-footer">
<button class="secondary-btn" id="editAgentMapJsonBtn" title="고급 사용자용: JSON으로 직접 편집">JSON 편집</button>
<div style="flex:1"></div>
<button class="secondary-btn" id="cancelAgentMapBtn">취소</button>
<button class="send-btn" id="saveAgentMapBtn">저장</button>
</div>
<div id="agentMapStatus" class="map-status"></div>
</div>
<div class="thinking-bar" id="thinkingBar"></div>
<div id="stepper" class="stepper-container">
+128 -1
View File
@@ -157,6 +157,72 @@
const agentPrompt = document.getElementById('agentPrompt');
const negativePrompt = document.getElementById('negativePrompt');
const updateAgentBtn = document.getElementById('updateAgentBtn');
const agentMapOverlay = document.getElementById('agentMapOverlay');
const closeAgentMapBtn = document.getElementById('closeAgentMapBtn');
const cancelAgentMapBtn = document.getElementById('cancelAgentMapBtn');
const saveAgentMapBtn = document.getElementById('saveAgentMapBtn');
const editAgentMapJsonBtn = document.getElementById('editAgentMapJsonBtn');
const addKnowledgeFolderBtn = document.getElementById('addKnowledgeFolderBtn');
const addSkillFolderBtn = document.getElementById('addSkillFolderBtn');
const addSkillFileBtn = document.getElementById('addSkillFileBtn');
const knowledgeFolderList = document.getElementById('knowledgeFolderList');
const skillFolderList = document.getElementById('skillFolderList');
const agentMapAgentName = document.getElementById('agentMapAgentName');
const agentMapStatus = document.getElementById('agentMapStatus');
let agentMapDraft = { agentPath: '', name: '', knowledgeFolders: [], skillFolders: [] };
function renderAgentMapLists() {
const renderList = (listEl, items, kind) => {
listEl.innerHTML = '';
items.forEach((p, idx) => {
const li = document.createElement('li');
li.className = 'map-item';
const icon = document.createElement('span');
icon.className = 'map-item-icon';
icon.textContent = kind === 'knowledge' ? '📁' : (p.endsWith('.md') || p.endsWith('.markdown') ? '📄' : '📁');
const pathEl = document.createElement('span');
pathEl.className = 'map-item-path';
pathEl.textContent = p;
pathEl.title = p;
const removeBtn = document.createElement('button');
removeBtn.className = 'map-item-remove';
removeBtn.textContent = '✕';
removeBtn.title = '연결 해제';
removeBtn.onclick = () => {
items.splice(idx, 1);
renderAgentMapLists();
};
li.appendChild(icon);
li.appendChild(pathEl);
li.appendChild(removeBtn);
listEl.appendChild(li);
});
};
renderList(knowledgeFolderList, agentMapDraft.knowledgeFolders, 'knowledge');
renderList(skillFolderList, agentMapDraft.skillFolders, 'skill');
}
function openAgentMapModal() {
if (!agentSel || agentSel.value === 'none' || !agentSel.value) {
showToast('에이전트를 먼저 선택하세요.');
return;
}
agentMapStatus.className = 'map-status';
agentMapStatus.textContent = '불러오는 중...';
agentMapDraft = { agentPath: agentSel.value, name: agentSel.options[agentSel.selectedIndex]?.text || '', knowledgeFolders: [], skillFolders: [] };
agentMapAgentName.textContent = agentMapDraft.name;
knowledgeFolderList.innerHTML = '';
skillFolderList.innerHTML = '';
agentMapOverlay.classList.add('visible');
vscode.postMessage({ type: 'getAgentMap', agentPath: agentSel.value });
}
function closeAgentMapModal() {
agentMapOverlay.classList.remove('visible');
agentMapStatus.textContent = '';
agentMapStatus.className = 'map-status';
}
let streamBody = null;
let internetEnabled = false;
@@ -387,6 +453,41 @@
}
vscode.postMessage({ type: 'getKnowledgeScope', agentPath: msg.selected });
break;
case 'agentMapData':
if (msg.value) {
agentMapDraft = {
agentPath: agentMapDraft.agentPath,
name: agentMapDraft.name,
knowledgeFolders: Array.isArray(msg.value.knowledgeFolders) ? msg.value.knowledgeFolders.slice() : [],
skillFolders: Array.isArray(msg.value.skillFolders) ? msg.value.skillFolders.slice() : [],
};
renderAgentMapLists();
agentMapStatus.textContent = msg.value.exists ? '' : '새 매핑입니다. 저장하면 생성됩니다.';
agentMapStatus.className = 'map-status';
}
break;
case 'pickedPath':
if (msg.value && msg.value.path && agentMapOverlay.classList.contains('visible')) {
const target = (msg.value.kind === 'knowledgeFolder')
? agentMapDraft.knowledgeFolders
: agentMapDraft.skillFolders;
if (!target.includes(msg.value.path)) {
target.push(msg.value.path);
renderAgentMapLists();
}
}
break;
case 'agentMapSaved':
if (msg.value && msg.value.ok) {
agentMapStatus.className = 'map-status ok';
agentMapStatus.textContent = '저장되었습니다.';
vscode.postMessage({ type: 'getKnowledgeScope', agentPath: agentMapDraft.agentPath });
setTimeout(closeAgentMapModal, 700);
} else {
agentMapStatus.className = 'map-status error';
agentMapStatus.textContent = '저장 실패: ' + (msg.value?.error || '알 수 없는 오류');
}
break;
case 'knowledgeScope':
if (knowledgeScopeSel) {
knowledgeScopeSel.innerHTML = '';
@@ -706,11 +807,37 @@
};
if (editKnowledgeMapBtn) {
editKnowledgeMapBtn.onclick = () => vscode.postMessage({ type: 'editKnowledgeMap' });
editKnowledgeMapBtn.onclick = () => openAgentMapModal();
}
if (reloadKnowledgeMapBtn) {
reloadKnowledgeMapBtn.onclick = () => vscode.postMessage({ type: 'getKnowledgeScope', agentPath: agentSel.value });
}
if (closeAgentMapBtn) closeAgentMapBtn.onclick = closeAgentMapModal;
if (cancelAgentMapBtn) cancelAgentMapBtn.onclick = closeAgentMapModal;
if (editAgentMapJsonBtn) {
editAgentMapJsonBtn.onclick = () => vscode.postMessage({ type: 'editKnowledgeMap' });
}
if (addKnowledgeFolderBtn) {
addKnowledgeFolderBtn.onclick = () => vscode.postMessage({ type: 'pickPath', kind: 'knowledgeFolder' });
}
if (addSkillFolderBtn) {
addSkillFolderBtn.onclick = () => vscode.postMessage({ type: 'pickPath', kind: 'skillFolder' });
}
if (addSkillFileBtn) {
addSkillFileBtn.onclick = () => vscode.postMessage({ type: 'pickPath', kind: 'skillFile' });
}
if (saveAgentMapBtn) {
saveAgentMapBtn.onclick = () => {
agentMapStatus.className = 'map-status';
agentMapStatus.textContent = '저장 중...';
vscode.postMessage({
type: 'saveAgentMap',
agentPath: agentMapDraft.agentPath,
knowledgeFolders: agentMapDraft.knowledgeFolders,
skillFolders: agentMapDraft.skillFolders,
});
};
}
editAgentBtn.onclick = () => {
if (agentSel.value === 'none') return;