211 lines
5.7 KiB
Vue
211 lines
5.7 KiB
Vue
<template>
|
|
<el-tooltip :content="'导出 mcpconfig'" placement="top" effect="light">
|
|
<div class="setting-button" @click="toggleDialog">
|
|
<span class="iconfont icon-deploy">
|
|
</span>
|
|
</div>
|
|
|
|
</el-tooltip>
|
|
|
|
<el-dialog v-model="showDialog" width="800px">
|
|
|
|
<template #header>
|
|
<div>
|
|
<div class="export-file-input">
|
|
<span>{{ t('export-filename') }}</span>
|
|
<el-input
|
|
v-model="exportFileName"
|
|
style="max-width: 300px"
|
|
>
|
|
<template #append>.json</template>
|
|
</el-input>
|
|
<span class="how-to-use"
|
|
@click="gotoHowtoUse"
|
|
>
|
|
<span class="iconfont icon-info"></span>
|
|
<span>{{ t('how-to-use') }}</span>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<div class="tools-dialog-container">
|
|
<el-scrollbar height="400px" class="tools-list">
|
|
<div v-html="exportJson">
|
|
</div>
|
|
</el-scrollbar>
|
|
<!--
|
|
<el-scrollbar height="400px" class="tools-list">
|
|
<div v-html="exampleCode"></div>
|
|
</el-scrollbar> -->
|
|
</div>
|
|
|
|
<template #footer>
|
|
<el-button type="primary" @click="copyCode">{{ t('copy') }}</el-button>
|
|
<el-button type="primary" @click="exportCode">{{ t('export') }}</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, computed, inject, onMounted, watch } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import { type ChatStorage, type EnableToolItem, getToolSchema } from '../chat';
|
|
import { markdownToHtml } from '@/components/main-panel/chat/markdown/markdown';
|
|
import { llmManager, llms } from '@/views/setting/llm';
|
|
import { mcpClientAdapter } from '@/views/connect/core';
|
|
import { ElMessage } from 'element-plus';
|
|
import { useMessageBridge } from '@/api/message-bridge';
|
|
import { gotoWebsite } from '@/hook/util';
|
|
|
|
const { t, locale } = useI18n();
|
|
|
|
const showDialog = ref(false);
|
|
const exportJson = ref('');
|
|
const exportFileName = ref('mcpconfig');
|
|
|
|
// 修改 toggleDialog 方法
|
|
const toggleDialog = () => {
|
|
showDialog.value = true;
|
|
};
|
|
|
|
const generateExportData = computed(() => {
|
|
const currentLLM = llms[llmManager.currentModelIndex];
|
|
|
|
const mcpServers = {} as any;
|
|
for (const client of mcpClientAdapter.clients) {
|
|
|
|
const option = client.connectOption;
|
|
const type = option.connectionType;
|
|
|
|
if (type === 'STDIO') {
|
|
mcpServers[client.name] = {
|
|
command: option.command,
|
|
args: option.args,
|
|
cwd: option.cwd,
|
|
description: "",
|
|
}
|
|
} else if (type === 'SSE') {
|
|
mcpServers[client.name] = {
|
|
type: 'sse',
|
|
url: option.url,
|
|
description: "",
|
|
}
|
|
} else {
|
|
mcpServers[client.name] = {
|
|
type: 'streamable_http',
|
|
url: option.url,
|
|
description: "",
|
|
}
|
|
}
|
|
}
|
|
|
|
const mcpconfig = {
|
|
version: "0.0.1",
|
|
namespace: "openmcp",
|
|
mcpServers,
|
|
defaultLLM: {
|
|
baseURL: currentLLM.baseUrl,
|
|
apiToken: currentLLM.userToken,
|
|
model: currentLLM.userModel
|
|
}
|
|
};
|
|
|
|
return JSON.stringify(mcpconfig, null, 2);
|
|
});
|
|
|
|
const innerMarkdownHtml = (code: string) => {
|
|
const rawCode = markdownToHtml(code);
|
|
const doc = new DOMParser().parseFromString(rawCode, 'text/html');
|
|
const pres = doc.querySelectorAll('pre');
|
|
|
|
if (pres.length < 2) {
|
|
return '';
|
|
}
|
|
|
|
const inner = pres[1].outerHTML;
|
|
return inner;
|
|
}
|
|
|
|
const exampleCode = computed(() => {
|
|
return innerMarkdownHtml(
|
|
'```typescript\n' +
|
|
`import { OmAgent } from 'openmcp-sdk/service/sdk';
|
|
|
|
const agent = new OmAgent();
|
|
|
|
agent.loadMcpConfig('/path/to/${exportFileName.value}.json');
|
|
|
|
const prompt = await agent.getPrompt('hacknews', { topn: '5' });
|
|
const res = await agent.ainvoke({ messages: prompt });
|
|
|
|
console.log('⚙️ Agent Response', res);
|
|
` +
|
|
'\n```'
|
|
);
|
|
});
|
|
|
|
const copyCode = async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(generateExportData.value);
|
|
ElMessage.success(t('copy-success'));
|
|
} catch (error) {
|
|
ElMessage.error(t('copy-fail'));
|
|
}
|
|
}
|
|
|
|
const exportCode = async () => {
|
|
const bridge = useMessageBridge();
|
|
bridge.postMessage({
|
|
command: 'vscode/export-file',
|
|
data: {
|
|
filename: exportFileName.value,
|
|
content: generateExportData.value
|
|
}
|
|
})
|
|
}
|
|
|
|
const gotoHowtoUse = () => {
|
|
if (locale.value === 'zh') {
|
|
gotoWebsite('https://kirigaya.cn/openmcp/zh/sdk-tutorial/#%E4%BD%BF%E7%94%A8');
|
|
} else if (locale.value === 'ja') {
|
|
gotoWebsite('https://kirigaya.cn/openmcp/ja/sdk-tutorial/#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95');
|
|
} else {
|
|
gotoWebsite('https://kirigaya.cn/openmcp/sdk-tutorial/#usage');
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
exportJson.value = innerMarkdownHtml(
|
|
'```json\n' + generateExportData.value + '\n```'
|
|
);
|
|
});
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
|
|
.export-file-input {
|
|
display: flex;
|
|
gap: 10px;
|
|
align-items: center;
|
|
}
|
|
|
|
.tools-list {
|
|
border-radius: .5em;
|
|
border: 1px solid var(--main-color);
|
|
padding: 5px;
|
|
}
|
|
|
|
.how-to-use {
|
|
margin-left: 10px;
|
|
font-size: 15px;
|
|
cursor: pointer;
|
|
background-color: var(--main-color);
|
|
color: #1e1e1e;
|
|
padding: 3px 5px;
|
|
border-radius: .3em;
|
|
}
|
|
|
|
</style>
|