增加引导页面
This commit is contained in:
parent
c1b06313d7
commit
96d029f906
8
renderer/package-lock.json
generated
8
renderer/package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"element-plus": "^2.9.7",
|
"element-plus": "^2.9.9",
|
||||||
"katex": "^0.16.21",
|
"katex": "^0.16.21",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
@ -6119,9 +6119,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/element-plus": {
|
"node_modules/element-plus": {
|
||||||
"version": "2.9.7",
|
"version": "2.9.9",
|
||||||
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.9.7.tgz",
|
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.9.9.tgz",
|
||||||
"integrity": "sha512-6vjZh5SXBncLhUwJGTVKS5oDljfgGMh6J4zVTeAZK3YdMUN76FgpvHkwwFXocpJpMbii6rDYU3sgie64FyPerQ==",
|
"integrity": "sha512-gN553+xr7ETkhJhH26YG0fERmd2BSCcQKslbtR8fats0Mc0yCtZOXr00bmoPOt5xGzhuRN1TWc9+f1pCaiA0/Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ctrl/tinycolor": "^3.4.1",
|
"@ctrl/tinycolor": "^3.4.1",
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.8.3",
|
"core-js": "^3.8.3",
|
||||||
"element-plus": "^2.9.7",
|
"element-plus": "^2.9.9",
|
||||||
"katex": "^0.16.21",
|
"katex": "^0.16.21",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-it": "^14.1.0",
|
"markdown-it": "^14.1.0",
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 54 KiB |
@ -204,6 +204,13 @@ a {
|
|||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.openmcp-image {
|
||||||
|
background-image: url('./images/openmcp.png');
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
|
||||||
.el-button:hover {
|
.el-button:hover {
|
||||||
color: var(--foreground) !important;
|
color: var(--foreground) !important;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
<div class="main">
|
<div class="main">
|
||||||
<Sidebar></Sidebar>
|
<Sidebar></Sidebar>
|
||||||
<MainPanel></MainPanel>
|
<MainPanel></MainPanel>
|
||||||
|
|
||||||
|
<Tour v-if="!userHasReadGuide"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -15,10 +17,12 @@ import MainPanel from '@/components/main-panel/index.vue';
|
|||||||
import { setDefaultCss } from './hook/css';
|
import { setDefaultCss } from './hook/css';
|
||||||
import { greenLog, pinkLog } from './views/setting/util';
|
import { greenLog, pinkLog } from './views/setting/util';
|
||||||
import { useMessageBridge } from './api/message-bridge';
|
import { useMessageBridge } from './api/message-bridge';
|
||||||
import { connectionArgs, connectionMethods, doConnect, loadEnvVar } from './views/connect/connection';
|
import { doConnect, loadEnvVar } from './views/connect/connection';
|
||||||
import { loadSetting } from './hook/setting';
|
import { getTour, loadSetting } from './hook/setting';
|
||||||
import { loadPanels } from './hook/panel';
|
import { loadPanels } from './hook/panel';
|
||||||
import { getPlatform } from './api/platform';
|
import { getPlatform } from './api/platform';
|
||||||
|
import Tour from '@/components/guide/tour.vue';
|
||||||
|
import { userHasReadGuide } from './components/guide/tour';
|
||||||
|
|
||||||
const bridge = useMessageBridge();
|
const bridge = useMessageBridge();
|
||||||
|
|
||||||
@ -28,7 +32,6 @@ bridge.addCommandListener('hello', data => {
|
|||||||
greenLog(`version: ${data.version}`);
|
greenLog(`version: ${data.version}`);
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -63,6 +66,9 @@ onMounted(async () => {
|
|||||||
// 设置环境变量
|
// 设置环境变量
|
||||||
loadEnvVar();
|
loadEnvVar();
|
||||||
|
|
||||||
|
// 获取引导状态
|
||||||
|
getTour();
|
||||||
|
|
||||||
// 尝试进行初始化连接
|
// 尝试进行初始化连接
|
||||||
await doConnect({
|
await doConnect({
|
||||||
namespace: platform,
|
namespace: platform,
|
||||||
|
25
renderer/src/components/guide/tour-title.vue
Normal file
25
renderer/src/components/guide/tour-title.vue
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tour-title">
|
||||||
|
<span class="openmcp-image tour-title-icon"></span>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.tour-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-title-icon {
|
||||||
|
height: 45px;
|
||||||
|
width: 45px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
3
renderer/src/components/guide/tour.ts
Normal file
3
renderer/src/components/guide/tour.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
export const userHasReadGuide = ref(true);
|
285
renderer/src/components/guide/tour.vue
Normal file
285
renderer/src/components/guide/tour.vue
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
<template>
|
||||||
|
<el-tour v-model="openTour">
|
||||||
|
<el-tour-step
|
||||||
|
:next-button-props="{ children: '开始' }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>介绍</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div style="display: flex; padding: 10px; padding-bottom: 20px;">
|
||||||
|
<div class="tour-common-text">
|
||||||
|
欢迎来到大模型与 mcp 的世界!
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
OpenMCP 将会助力你快速将任何奇思妙想开发成 mcp 服务器,通过接入大模型,让你的任何 idea 都可以快速落地。
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
倘若阁下是第一次使用 OpenMCP,请务必走完我们准备好的引导。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#connected-status-container"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>引导</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
这里会显示当前调试的 mcp 服务器的名称(缩写)和连接状态。只有当连接状态为「已连接」,调试工作才能开始。
|
||||||
|
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
OpenMCP 通过服务器名称对项目所的所有服务进行统一管理,请避免在同一个项目中使用相同的名称。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#sidebar-connect"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步', onClick: () => router.push('/connect') }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>连接</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
如果显示「未连接」或阁下想要更改连接参数或者连接方式,可以点击这里进入连接面板。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
:target="connectionSettingRef"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>连接</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
阁下可以在左侧面板选择与您心爱的 mcp 服务器进行连接的方式,并填入对应的连接参数。
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
对于 openmcp vscode/trae/cursor 插件端的用户,当您通过面板按钮进入 openmcp 的时候,默认就会选择 STDIO 作为连接方式,并根据你的上下文生成启动参数。
|
||||||
|
openmcp desktop 的用户可能就需要自己填写了。Anyway,这总比在你的好友电脑中植入 chrome 浏览器密码破解木马简单。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
:target="connectionLogRef"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
placement="left"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>连接</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
连接响应会在这个地方打印出来,如果出现绿色背景的信息,代表连接成功。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#sidebar-debug"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步', onClick: () => router.push('/debug') }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>调试</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
假设你已经成功连接了 mcp 服务器,那么点击调试按钮,你可以开始你的调试工作。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
:target="welcomeRef"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>调试</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
我们目前提供了四种主要调试选项,「资源」、「提词」、「工具」分别和 MCP 协议中的 resources、prompts、tools 对应。
|
||||||
|
|
||||||
|
而「交互测试」则允许你直接将写好的 mcp 服务器放入大模型中直接做全链路测试,从而更加获取更加真实的反馈和数据,进而改进的你的 mcp 服务器。
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
基于我们在 agent 和 rl 方向的最佳实践,我们后续还会推出更多的调试和数据集聚合制作选项,请期待吧!
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#sidebar-setting"
|
||||||
|
:prev-button-props="{ children: '上一步', onClick: () => router.push('/debug') }"
|
||||||
|
:next-button-props="{ children: '下一步', onClick: () => router.push('/setting') }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>设置</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
如果要进行交互测试,请不要忘记先配置你常用的大模型 API
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
:target="llmSettingRef"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>设置</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
OpenMCP 目前支持所有支持 openai 接口规范的大模型,比如 deepseek,openai,kimi 等等。
|
||||||
|
本地部署的 ollama 也正在支持。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#add-new-server-button"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>设置</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
如果需要添加自定义的大模型服务,请点击这里。比如火山云,阿里云,硅基流动等。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#test-llm-button"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>设置</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
填写完成连接签名后,点击这里来测试 大模型服务是否可以访问。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
target="#save-llm-button"
|
||||||
|
:prev-button-props="{ children: '上一步' }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>设置</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
最后请不要忘记点击保存按钮,保存你的设置。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
:prev-button-props="{ children: '上一步', onClick: () => router.push('/setting') }"
|
||||||
|
:next-button-props="{ children: '下一步' }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>🎉恭喜</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
🎉恭喜,我的朋友,现在的你已经是半个 mcp 专家了,请充好一杯咖啡,慢慢享用快乐的开发时间吧!
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
如果是插件用户,左侧面板的最下面「入门与帮助」有一些我们准备好的资料,希望能帮到阁下优雅地开发你的 mcp 服务器。
|
||||||
|
让我们一起把越来越多的 api 和 sdk 接入 大模型吧。
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
|
||||||
|
|
||||||
|
<el-tour-step
|
||||||
|
:prev-button-props="{ children: '上一步', onClick: () => router.push('/setting') }"
|
||||||
|
:next-button-props="{ children: '结束', onClick: () => finishTour() }"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<TourTitle>终章?</TourTitle>
|
||||||
|
</template>
|
||||||
|
<div class="tour-common-text">
|
||||||
|
<pre><code>(base) <span style="color: greenyellow">➜</span> <span style="color: #6AC2CF">.openmcp</span> <span style="color: #6BC34B">cat</span> <span style="color: #D357DB">KEY</span>
|
||||||
|
直面恐惧,创造未来
|
||||||
|
Face your fears, create the future
|
||||||
|
恐怖に直面し、未来を創り出</code></pre>
|
||||||
|
</div>
|
||||||
|
</el-tour-step>
|
||||||
|
</el-tour>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import TourTitle from './tour-title.vue';
|
||||||
|
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { welcomeRef } from '@/views/debug/welcome';
|
||||||
|
import { connectionLogRef, connectionSettingRef } from '@/views/connect/connection';
|
||||||
|
import { llmSettingRef } from '@/views/setting/api';
|
||||||
|
import { userHasReadGuide } from './tour';
|
||||||
|
import { setTour } from '@/hook/setting';
|
||||||
|
|
||||||
|
const openTour = ref(true);
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
function finishTour() {
|
||||||
|
openTour.value = false;
|
||||||
|
userHasReadGuide.value = true;
|
||||||
|
setTour();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.tour-common-text {
|
||||||
|
font-size: 1.0rem;
|
||||||
|
padding: 10px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour-warning {
|
||||||
|
display: flex;
|
||||||
|
background-color: rgba(230, 162, 60, 0.5);
|
||||||
|
border-radius: .5em;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="connected-status-container"
|
<div class="connected-status-container"
|
||||||
|
id="connected-status-container"
|
||||||
@click.stop="toggleConnectionPanel()"
|
@click.stop="toggleConnectionPanel()"
|
||||||
>
|
>
|
||||||
<span class="mcp-server-info">
|
<span class="mcp-server-info">
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="sidebar-item-container">
|
<div class="sidebar-item-container">
|
||||||
<div v-for="(item, index) of sidebarItems" :key="index">
|
<div v-for="(item, index) of sidebarItems" :key="index"
|
||||||
|
:id="`sidebar-${item.ident}`"
|
||||||
|
>
|
||||||
<el-tooltip :content="t(item.ident)" placement="right">
|
<el-tooltip :content="t(item.ident)" placement="right">
|
||||||
<div class="sidebar-option-item" :class="{ 'active': isActive(item.ident) }"
|
<div class="sidebar-option-item" :class="{ 'active': isActive(item.ident) }"
|
||||||
@click="gotoOption(item.ident)">
|
@click="gotoOption(item.ident)">
|
||||||
|
@ -15,7 +15,6 @@ export function setDefaultCss() {
|
|||||||
document.body.style.setProperty('--el-border-color-light', 'var(--sidebar)');
|
document.body.style.setProperty('--el-border-color-light', 'var(--sidebar)');
|
||||||
document.body.style.setProperty('--el-border-color-lighter', 'var(--sidebar)');
|
document.body.style.setProperty('--el-border-color-lighter', 'var(--sidebar)');
|
||||||
document.body.style.setProperty('--el-bg-color-overlay', 'var(--sidebar)');
|
document.body.style.setProperty('--el-bg-color-overlay', 'var(--sidebar)');
|
||||||
document.body.style.setProperty('--el-color-info-light-9', 'var(--main-color)');
|
|
||||||
document.body.style.setProperty('--el-color-info', 'var(--foreground)');
|
document.body.style.setProperty('--el-color-info', 'var(--foreground)');
|
||||||
document.body.style.setProperty('--el-color-info-light-8', 'var(--main-color)');
|
document.body.style.setProperty('--el-color-info-light-8', 'var(--main-color)');
|
||||||
document.body.style.setProperty('--el-fill-color-light', 'var(--sidebar-item-selected)');
|
document.body.style.setProperty('--el-fill-color-light', 'var(--sidebar-item-selected)');
|
||||||
|
@ -2,6 +2,7 @@ import { useMessageBridge } from "@/api/message-bridge";
|
|||||||
import { llmManager, llms } from "@/views/setting/llm";
|
import { llmManager, llms } from "@/views/setting/llm";
|
||||||
import { pinkLog } from "@/views/setting/util";
|
import { pinkLog } from "@/views/setting/util";
|
||||||
import I18n from '@/i18n/index';
|
import I18n from '@/i18n/index';
|
||||||
|
import { userHasReadGuide } from "@/components/guide/tour";
|
||||||
|
|
||||||
export async function loadSetting() {
|
export async function loadSetting() {
|
||||||
const bridge = useMessageBridge();
|
const bridge = useMessageBridge();
|
||||||
@ -24,6 +25,23 @@ export async function loadSetting() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getTour() {
|
||||||
|
const bridge = useMessageBridge();
|
||||||
|
const { code, msg } = await bridge.commandRequest('setting/get-tour');
|
||||||
|
|
||||||
|
if (code === 200) {
|
||||||
|
pinkLog('获取引导状态成功');
|
||||||
|
userHasReadGuide.value = msg.userHasReadGuide || false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setTour() {
|
||||||
|
const bridge = useMessageBridge();
|
||||||
|
const { code, msg } = await bridge.commandRequest('setting/set-tour', {
|
||||||
|
userHasReadGuide: userHasReadGuide.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function saveSetting(saveHandler?: () => void) {
|
export function saveSetting(saveHandler?: () => void) {
|
||||||
const bridge = useMessageBridge();
|
const bridge = useMessageBridge();
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="about-container" >
|
<div class="about-container" >
|
||||||
|
|
||||||
<span class="about-icon-container">
|
<span class="about-icon-container">
|
||||||
<span class="iconfont icon-openmcp"></span>
|
<div class="openmcp-image"></div>
|
||||||
<span>openmcp</span>
|
<span>openmcp</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@ -23,18 +22,13 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div style="display: inline-flex;">
|
<div style="display: inline-flex;">
|
||||||
<el-button
|
<el-button class="join-qq" type="primary"
|
||||||
class="join-qq"
|
@click="joinQQGroup('https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD')">
|
||||||
type="primary"
|
|
||||||
@click="joinQQGroup('https://qm.qq.com/cgi-bin/qm/qr?k=C6ZUTZvfqWoI12lWe7L93cWa1hUsuVT0&jump_from=webapi&authKey=McW6B1ogTPjPDrCyGttS890tMZGQ1KB3QLuG4aqVNRaYp4vlTSgf2c6dMcNjMuBD')"
|
|
||||||
>
|
|
||||||
<span class="iconfont icon-QQ"></span>
|
<span class="iconfont icon-QQ"></span>
|
||||||
加入 OpenMCP 技术群
|
加入 OpenMCP 技术群
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="success"
|
<el-button type="success" class="join-qq"
|
||||||
class="join-qq"
|
@click="gotoWebsite('https://marketplace.visualstudio.com/items?itemName=kirigaya.openmcp&ssr=false#review-details')">
|
||||||
@click="gotoWebsite('https://marketplace.visualstudio.com/items?itemName=kirigaya.openmcp&ssr=false#review-details')"
|
|
||||||
>
|
|
||||||
<span class="iconfont icon-star"></span>
|
<span class="iconfont icon-star"></span>
|
||||||
为 OpenMCP 撰写评价!
|
为 OpenMCP 撰写评价!
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -71,7 +65,7 @@ function gotoWebsite(url: string) {
|
|||||||
.about-icon-container {
|
.about-icon-container {
|
||||||
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.3);
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.3);
|
||||||
border-radius: .8em;
|
border-radius: .8em;
|
||||||
padding: 20px 50px;
|
padding: 20px 30px;
|
||||||
color: var(--main-color);
|
color: var(--main-color);
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -90,17 +84,24 @@ function gotoWebsite(url: string) {
|
|||||||
width: 150px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.about-container .openmcp-image {
|
||||||
|
width: 245px;
|
||||||
|
height: 205px;
|
||||||
|
}
|
||||||
|
|
||||||
.about-container>.qr-code {
|
.about-container>.qr-code {
|
||||||
height: 180px;
|
height: 180px;
|
||||||
border: 2px solid transparent; /* 设置边框宽度,但颜色透明 */
|
border: 2px solid transparent;
|
||||||
|
/* 设置边框宽度,但颜色透明 */
|
||||||
border-image: linear-gradient(to bottom right, #7DDCEB, #CB81DA);
|
border-image: linear-gradient(to bottom right, #7DDCEB, #CB81DA);
|
||||||
border-image-slice: 1; /* 确保渐变覆盖整个边框 */
|
border-image-slice: 1;
|
||||||
background: white; /* 可选:防止内容穿透 */
|
/* 确保渐变覆盖整个边框 */
|
||||||
|
background: white;
|
||||||
|
/* 可选:防止内容穿透 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.join-qq .iconfont {
|
.join-qq .iconfont {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -1,5 +1,5 @@
|
|||||||
import { useMessageBridge } from '@/api/message-bridge';
|
import { useMessageBridge } from '@/api/message-bridge';
|
||||||
import { reactive } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import { pinkLog } from '../setting/util';
|
import { pinkLog } from '../setting/util';
|
||||||
import { arrowMiddleware, ElMessage } from 'element-plus';
|
import { arrowMiddleware, ElMessage } from 'element-plus';
|
||||||
import { ILaunchSigature } from '@/hook/type';
|
import { ILaunchSigature } from '@/hook/type';
|
||||||
@ -19,6 +19,9 @@ export const connectionMethods = reactive({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const connectionSettingRef = ref<any>(null);
|
||||||
|
export const connectionLogRef = ref<any>(null);
|
||||||
|
|
||||||
export const connectionArgs = reactive({
|
export const connectionArgs = reactive({
|
||||||
commandString: '',
|
commandString: '',
|
||||||
cwd: '',
|
cwd: '',
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div class="connection-container">
|
<div class="connection-container">
|
||||||
<div class="connect-panel-container">
|
<div class="connect-panel-container"
|
||||||
|
:ref="el => connectionSettingRef = el"
|
||||||
|
>
|
||||||
<ConnectionMethod></ConnectionMethod>
|
<ConnectionMethod></ConnectionMethod>
|
||||||
<ConnectionArgs></ConnectionArgs>
|
<ConnectionArgs></ConnectionArgs>
|
||||||
<EnvVar></EnvVar>
|
<EnvVar></EnvVar>
|
||||||
@ -15,7 +17,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="connect-panel-container">
|
<div class="connect-panel-container"
|
||||||
|
:ref="el => connectionLogRef = el"
|
||||||
|
>
|
||||||
<ConnectionLog></ConnectionLog>
|
<ConnectionLog></ConnectionLog>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -29,7 +33,7 @@ import { useI18n } from 'vue-i18n';
|
|||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
import { connectionResult, doConnect } from './connection';
|
import { connectionLogRef, connectionResult, connectionSettingRef, doConnect } from './connection';
|
||||||
|
|
||||||
import ConnectionMethod from './connection-method.vue';
|
import ConnectionMethod from './connection-method.vue';
|
||||||
import ConnectionArgs from './connection-args.vue';
|
import ConnectionArgs from './connection-args.vue';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="height: 100%;">
|
<div style="height: 100%;" id="debug-container">
|
||||||
<Welcome v-show="!haveActiveTab"></Welcome>
|
<Welcome v-show="!haveActiveTab"></Welcome>
|
||||||
|
|
||||||
<!-- 如果存在激活标签页,则根据标签页进行渲染 -->
|
<!-- 如果存在激活标签页,则根据标签页进行渲染 -->
|
||||||
|
3
renderer/src/views/debug/welcome.ts
Normal file
3
renderer/src/views/debug/welcome.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
|
export const welcomeRef = ref<any>(null);
|
@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="debug-welcome">
|
<div class="debug-welcome">
|
||||||
<span>{{ t('choose-a-project-debug') }}</span>
|
<span>{{ t('choose-a-project-debug') }}</span>
|
||||||
<div class="welcome-container">
|
<div class="welcome-container"
|
||||||
|
:ref="el => welcomeRef = el"
|
||||||
|
>
|
||||||
<!-- TODO: 支持更多的 server -->
|
<!-- TODO: 支持更多的 server -->
|
||||||
<span
|
<span
|
||||||
class="debug-option"
|
class="debug-option"
|
||||||
@ -25,6 +27,7 @@ import { defineComponent, markRaw, computed } from 'vue';
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { connectionResult } from '../connect/connection';
|
import { connectionResult } from '../connect/connection';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { welcomeRef } from './welcome';
|
||||||
|
|
||||||
defineComponent({ name: 'welcome' });
|
defineComponent({ name: 'welcome' });
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@ import { TaskLoop } from '@/components/main-panel/chat/task-loop';
|
|||||||
import { llmManager } from './llm';
|
import { llmManager } from './llm';
|
||||||
import { reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
|
export const llmSettingRef = ref<any>(null);
|
||||||
|
|
||||||
export const simpleTestResult = reactive<{
|
export const simpleTestResult = reactive<{
|
||||||
done: boolean,
|
done: boolean,
|
||||||
start: boolean,
|
start: boolean,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="setting-section">
|
<div class="setting-section"
|
||||||
|
:ref="el => llmSettingRef = el"
|
||||||
|
>
|
||||||
<h2 class="api-title">
|
<h2 class="api-title">
|
||||||
{{ "API" }}
|
{{ "API" }}
|
||||||
</h2>
|
</h2>
|
||||||
@ -47,12 +49,15 @@
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="setting-save-container">
|
<div class="setting-save-container">
|
||||||
<el-button type="success" @click="addNewServer">
|
<el-button
|
||||||
|
id="add-new-server-button"
|
||||||
|
type="success" @click="addNewServer">
|
||||||
{{ t("add-new-server") }}
|
{{ t("add-new-server") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
id="test-llm-button"
|
||||||
@click="makeSimpleTalk"
|
@click="makeSimpleTalk"
|
||||||
:loading="simpleTestResult.start"
|
:loading="simpleTestResult.start"
|
||||||
>
|
>
|
||||||
@ -60,7 +65,11 @@
|
|||||||
{{ t('test') }}
|
{{ t('test') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button type="primary" @click="saveLlmSetting">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
id="save-llm-button"
|
||||||
|
@click="saveLlmSetting"
|
||||||
|
>
|
||||||
<span class="iconfont icon-save"></span>
|
<span class="iconfont icon-save"></span>
|
||||||
{{ t('save') }}
|
{{ t('save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
@ -110,7 +119,7 @@ import { pinkLog } from './util';
|
|||||||
|
|
||||||
import ConnectInterfaceOpenai from './connect-interface-openai.vue';
|
import ConnectInterfaceOpenai from './connect-interface-openai.vue';
|
||||||
import ConnectTest from './connect-test.vue';
|
import ConnectTest from './connect-test.vue';
|
||||||
import { makeSimpleTalk, simpleTestResult } from './api';
|
import { llmSettingRef, makeSimpleTalk, simpleTestResult } from './api';
|
||||||
|
|
||||||
defineComponent({ name: 'api' });
|
defineComponent({ name: 'api' });
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Controller, RequestClientType } from "../common";
|
import { Controller, RequestClientType } from "../common";
|
||||||
import { PostMessageble } from "../hook/adapter";
|
import { PostMessageble } from "../hook/adapter";
|
||||||
import { loadSetting, saveSetting } from "./setting.service";
|
import { getTour, loadSetting, saveSetting, setTour } from "./setting.service";
|
||||||
|
|
||||||
export class SettingController {
|
export class SettingController {
|
||||||
|
|
||||||
@ -17,6 +17,8 @@ export class SettingController {
|
|||||||
|
|
||||||
@Controller('setting/load')
|
@Controller('setting/load')
|
||||||
async loadSetting(client: RequestClientType, data: any, webview: PostMessageble) {
|
async loadSetting(client: RequestClientType, data: any, webview: PostMessageble) {
|
||||||
|
console.log('enter loading');
|
||||||
|
|
||||||
const config = loadSetting();
|
const config = loadSetting();
|
||||||
return {
|
return {
|
||||||
code: 200,
|
code: 200,
|
||||||
@ -24,4 +26,30 @@ export class SettingController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Controller('setting/set-tour')
|
||||||
|
async setTourController(client: RequestClientType, data: any, webview: PostMessageble) {
|
||||||
|
|
||||||
|
const { userHasReadGuide } = data;
|
||||||
|
|
||||||
|
setTour(userHasReadGuide);
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
msg: 'setTour success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller('setting/get-tour')
|
||||||
|
async getTourController(client: RequestClientType, data: any, webview: PostMessageble) {
|
||||||
|
console.log('enter');
|
||||||
|
|
||||||
|
const { userHasReadGuide } = getTour();
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: 200,
|
||||||
|
msg:{
|
||||||
|
userHasReadGuide
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -6,9 +6,6 @@ import { IConfig } from './setting.dto';
|
|||||||
import { llms } from '../hook/llm';
|
import { llms } from '../hook/llm';
|
||||||
|
|
||||||
function getConfigurationPath() {
|
function getConfigurationPath() {
|
||||||
// 如果是 vscode 插件下,则修改为 ~/.openmcp/config.json
|
|
||||||
if (VSCODE_WORKSPACE) {
|
|
||||||
// 在 VSCode 插件环境下
|
|
||||||
const homeDir = os.homedir();
|
const homeDir = os.homedir();
|
||||||
const configDir = path.join(homeDir, '.openmcp');
|
const configDir = path.join(homeDir, '.openmcp');
|
||||||
if (!fs.existsSync(configDir)) {
|
if (!fs.existsSync(configDir)) {
|
||||||
@ -16,8 +13,6 @@ function getConfigurationPath() {
|
|||||||
}
|
}
|
||||||
return path.join(configDir, 'setting.json');
|
return path.join(configDir, 'setting.json');
|
||||||
}
|
}
|
||||||
return 'setting.json';
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultLanguage() {
|
function getDefaultLanguage() {
|
||||||
if (process.env.VSCODE_PID) {
|
if (process.env.VSCODE_PID) {
|
||||||
@ -75,3 +70,29 @@ export function saveSetting(config: Partial<IConfig>): void {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTour() {
|
||||||
|
const configPath = getConfigurationPath();
|
||||||
|
const KEY = path.join(path.dirname(configPath), 'KEY');
|
||||||
|
console.log(KEY);
|
||||||
|
|
||||||
|
if (!fs.existsSync(KEY)) {
|
||||||
|
return {
|
||||||
|
userHasReadGuide: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
userHasReadGuide: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setTour(userHasReadGuide: boolean): void {
|
||||||
|
const configPath = getConfigurationPath();
|
||||||
|
const KEY = path.join(path.dirname(configPath), 'KEY');
|
||||||
|
if (userHasReadGuide) {
|
||||||
|
const key = `直面恐惧,创造未来
|
||||||
|
Face your fears, create the future
|
||||||
|
恐怖に直面し、未来を創り出す`;
|
||||||
|
fs.writeFileSync(KEY, key, 'utf-8');
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user