chore: version up to v2.80.30 and package vsix
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user