Add customization of prompts for MCP tools
This commit is contained in:
parent
aa4f8d5342
commit
1256d64498
87
main.ts
87
main.ts
|
|
@ -14,12 +14,20 @@ import 'src/css/styles.css';
|
|||
|
||||
import { LLM_DEFAULTS } from 'src/constants';
|
||||
|
||||
export interface MCPToolState {
|
||||
name: string;
|
||||
originalDescription: string;
|
||||
customDescription: string;
|
||||
}
|
||||
|
||||
export interface MCPServerConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
command: string;
|
||||
args: string;
|
||||
envString: string;
|
||||
serverInstruction?: string;
|
||||
fetchedTools?: MCPToolState[];
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Settings ---------------------------------------------------------------
|
||||
|
|
@ -707,6 +715,20 @@ class SampleSettingTab extends PluginSettingTab {
|
|||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(serverDiv)
|
||||
.setName('Общая инструкция для сервера (Над-инструкция)')
|
||||
.setDesc('Эти инструкции будут добавлены в системный промпт при использовании графа.')
|
||||
.addTextArea(t => {
|
||||
t.inputEl.style.width = '100%';
|
||||
t.inputEl.style.height = '60px';
|
||||
t.setValue(server.serverInstruction || '').onChange(async v => {
|
||||
server.serverInstruction = v;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
this.createFetchedTools(server, serverDiv);
|
||||
});
|
||||
|
||||
new Setting(container).addButton(b => b.setButtonText('➕ Добавить MCP сервер').setCta().onClick(async () => {
|
||||
|
|
@ -716,6 +738,71 @@ class SampleSettingTab extends PluginSettingTab {
|
|||
}));
|
||||
}
|
||||
|
||||
createFetchedTools(server: MCPServerConfig, serverDiv: HTMLDivElement) {
|
||||
const toolsContainer = serverDiv.createDiv({ cls: 'mcp-tools-container', attr: { style: 'margin-top: 15px; border-top: 1px solid var(--background-modifier-border); padding-top: 10px;' } });
|
||||
|
||||
const fetchBtn = toolsContainer.createEl('button', { text: '🔄 Подгрузить/Обновить инструменты' });
|
||||
fetchBtn.style.marginBottom = '10px';
|
||||
|
||||
fetchBtn.onclick = async () => {
|
||||
fetchBtn.textContent = '⏳ Подгрузка...';
|
||||
fetchBtn.disabled = true;
|
||||
try {
|
||||
const response = await fetch(`${this.plugin.settings.apiBaseUrl}/mcp/fetch`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(server)
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error("Ошибка HTTP: " + response.status);
|
||||
|
||||
const remoteTools: {name: string, description: string}[] = await response.json();
|
||||
|
||||
// Логика синхронизации: оставляем кастомные описания, удаляем пропавшие, добавляем новые
|
||||
if (!server.fetchedTools) server.fetchedTools = [];
|
||||
const existingMap = new Map(server.fetchedTools.map(t => [t.name, t]));
|
||||
|
||||
server.fetchedTools = remoteTools.map(rt => {
|
||||
if (existingMap.has(rt.name)) {
|
||||
const existing = existingMap.get(rt.name)!;
|
||||
return { ...existing, originalDescription: rt.description }; // обновляем оригинальное описание на всякий случай
|
||||
}
|
||||
return { name: rt.name, originalDescription: rt.description, customDescription: '' };
|
||||
});
|
||||
|
||||
await this.plugin.saveSettings();
|
||||
new Notice(`Загружено инструментов: ${remoteTools.length}`);
|
||||
this.display(); // Перерисовываем UI
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
new Notice('Ошибка подгрузки инструментов: ' + e);
|
||||
} finally {
|
||||
fetchBtn.textContent = '🔄 Подгрузить/Обновить инструменты';
|
||||
fetchBtn.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Отрисовка списка тулов
|
||||
if (server.fetchedTools && server.fetchedTools.length > 0) {
|
||||
server.fetchedTools.forEach((tool, tIndex) => {
|
||||
const toolDiv = toolsContainer.createDiv({ attr: { style: 'margin-bottom: 10px; padding: 10px; background: var(--background-primary); border-radius: 6px;' } });
|
||||
toolDiv.createEl('div', { text: `🛠 ${tool.name}`, attr: { style: 'font-weight: bold; margin-bottom: 5px;' } });
|
||||
toolDiv.createEl('div', { text: tool.originalDescription, attr: { style: 'font-size: 0.85em; color: var(--text-muted); margin-bottom: 8px;' } });
|
||||
|
||||
new Setting(toolDiv)
|
||||
.setName('Кастомное описание (Override)')
|
||||
.setDesc('Оставьте пустым, чтобы использовать оригинальное.')
|
||||
.addTextArea(t => {
|
||||
t.inputEl.style.width = '100%';
|
||||
t.setValue(tool.customDescription).onChange(async v => {
|
||||
tool.customDescription = v;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderVoiceSettings(container: HTMLElement) {
|
||||
container.createEl('h3', { text: 'Транскрибация Vosk' });
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user