support self-check
This commit is contained in:
parent
dcabd47a20
commit
25f74b8f1e
@ -4,7 +4,7 @@
|
|||||||
<div class="left">
|
<div class="left">
|
||||||
<h2>
|
<h2>
|
||||||
<span class="iconfont icon-chat"></span>
|
<span class="iconfont icon-chat"></span>
|
||||||
提示词模块
|
{{ t('prompt-module') }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<PromptTemplates :tab-id="props.tabId"></PromptTemplates>
|
<PromptTemplates :tab-id="props.tabId"></PromptTemplates>
|
||||||
@ -24,6 +24,9 @@ import { defineProps } from 'vue';
|
|||||||
import PromptTemplates from './prompt-templates.vue';
|
import PromptTemplates from './prompt-templates.vue';
|
||||||
import PromptReader from './prompt-reader.vue';
|
import PromptReader from './prompt-reader.vue';
|
||||||
import PromptLogger from './prompt-logger.vue';
|
import PromptLogger from './prompt-logger.vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
tabId: {
|
tabId: {
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
<template>
|
||||||
|
<div class="diagram-item-record" v-if="props.dataView && props.dataView.tool">
|
||||||
|
<div class="item-header">
|
||||||
|
<span class="item-title">{{ props.dataView.tool.name }}</span>
|
||||||
|
<span class="item-status" :class="props.dataView.status">{{ props.dataView.status }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="item-desc">{{ props.dataView.tool.description }}</div>
|
||||||
|
<div class="item-schema">
|
||||||
|
<span class="item-label">Input Schema:</span>
|
||||||
|
<pre class="item-json">{{ formatJson(props.dataView.tool.inputSchema) }}</pre>
|
||||||
|
</div>
|
||||||
|
<div v-if="props.dataView.result !== undefined" class="item-result">
|
||||||
|
<span class="item-label">Result:</span>
|
||||||
|
<pre class="item-json">{{ formatJson(props.dataView.result) }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="diagram-item-record">
|
||||||
|
<div class="item-header">
|
||||||
|
<span class="item-title">No Tool Selected</span>
|
||||||
|
</div>
|
||||||
|
<div class="item-desc">Please select a tool to view its details.</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { PropType } from 'vue';
|
||||||
|
import type { NodeDataView } from './diagram';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataView: {
|
||||||
|
type: Object as PropType<NodeDataView | undefined | null>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function formatJson(obj: any) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(obj, null, 2)
|
||||||
|
} catch {
|
||||||
|
return String(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.diagram-item-record {
|
||||||
|
padding: 14px 18px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0,0,0,0.04);
|
||||||
|
font-size: 15px;
|
||||||
|
color: #222;
|
||||||
|
max-width: 420px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 17px;
|
||||||
|
color: var(--main-color, #409EFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-status {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-left: 8px;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
.item-status.running { color: #2196f3; }
|
||||||
|
.item-status.success { color: #43a047; }
|
||||||
|
.item-status.error { color: #e53935; }
|
||||||
|
.item-status.waiting { color: #aaa; }
|
||||||
|
.item-status.default { color: #888; }
|
||||||
|
|
||||||
|
.item-desc {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-label {
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 4px;
|
||||||
|
color: var(--main-color, #409EFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-json {
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: var(--code-font-family, monospace);
|
||||||
|
margin: 2px 0 8px 0;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-result {
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,10 +1,14 @@
|
|||||||
import type { ElkNode } from 'elkjs/lib/elk-api';
|
import type { ElkNode } from 'elkjs/lib/elk-api';
|
||||||
import { TaskLoop } from '../chat/core/task-loop';
|
import { TaskLoop } from '../../chat/core/task-loop';
|
||||||
import type { Reactive } from 'vue';
|
import type { Reactive } from 'vue';
|
||||||
import type { ChatStorage } from '../chat/chat-box/chat';
|
import type { ChatStorage } from '../../chat/chat-box/chat';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import type { ToolItem } from '@/hook/type';
|
import type { ToolItem } from '@/hook/type';
|
||||||
|
|
||||||
|
import I18n from '@/i18n';
|
||||||
|
|
||||||
|
const { t } = I18n.global;
|
||||||
|
|
||||||
export interface Edge {
|
export interface Edge {
|
||||||
id: string;
|
id: string;
|
||||||
sources: string[];
|
sources: string[];
|
||||||
@ -50,11 +54,11 @@ export function invalidConnectionDetector(state: DiagramState, d: Node): CanConn
|
|||||||
const to = d.id;
|
const to = d.id;
|
||||||
|
|
||||||
if (!from) {
|
if (!from) {
|
||||||
return { canConnect: false, reason: '未选择起始节点' };
|
return { canConnect: false, reason: t('not-select-begin-node') };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from === to) {
|
if (from === to) {
|
||||||
return { canConnect: false, reason: '不能连接到自身' };
|
return { canConnect: false, reason: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
// 建立邻接表
|
// 建立邻接表
|
||||||
@ -84,11 +88,11 @@ export function invalidConnectionDetector(state: DiagramState, d: Node): CanConn
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasPath(to, from, new Set())) {
|
if (hasPath(to, from, new Set())) {
|
||||||
return { canConnect: false, reason: '连接会形成环路' };
|
return { canConnect: false, reason: t('can-make-loop') };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasPath(from, to, new Set())) {
|
if (hasPath(from, to, new Set())) {
|
||||||
return { canConnect: false, reason: '这是一个重复的连接' };
|
return { canConnect: false, reason: t('this-is-repeat-connection') };
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -196,13 +200,13 @@ export async function makeNodeTest(
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
// ElMessage.error('AI 生成的 JSON 解析错误');
|
// ElMessage.error('AI 生成的 JSON 解析错误');
|
||||||
dataView.status = 'error';
|
dataView.status = 'error';
|
||||||
dataView.result = 'AI 生成的 JSON 解析错误';
|
dataView.result = t('ai-gen-error-json');
|
||||||
context.render();
|
context.render();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ElMessage.error('AI 调用了未知的工具');
|
// ElMessage.error('AI 调用了未知的工具');
|
||||||
dataView.status = 'error';
|
dataView.status = 'error';
|
||||||
dataView.result = 'AI 调用了未知的工具 ' + toolCall.function?.name;
|
dataView.result = t('ai-invoke-unknown-tool') + ' ' + toolCall.function?.name;
|
||||||
context.render();
|
context.render();
|
||||||
}
|
}
|
||||||
loop.abort();
|
loop.abort();
|
@ -2,16 +2,19 @@
|
|||||||
<div style="display: flex; align-items: center; gap: 16px;">
|
<div style="display: flex; align-items: center; gap: 16px;">
|
||||||
<div ref="svgContainer" class="diagram-container"></div>
|
<div ref="svgContainer" class="diagram-container"></div>
|
||||||
|
|
||||||
<!-- <template v-for="(node, index) in state.nodes" :key="node.id + '-popup'">
|
<template v-for="(node, index) in state.nodes" :key="node.id + '-popup'">
|
||||||
|
<transition name="collapse-from-top" mode="out-in">
|
||||||
<div
|
<div
|
||||||
v-if="state.hoverNodeId === node.id"
|
v-show="state.hoverNodeId === node.id && state.dataView.get(node.id)?.status !== 'waiting'"
|
||||||
|
@mouseenter="setHoverItem(node.id)"
|
||||||
|
@mouseleave="clearHoverItem()"
|
||||||
:style="getNodePopupStyle(node)"
|
:style="getNodePopupStyle(node)"
|
||||||
class="node-popup"
|
class="node-popup"
|
||||||
>
|
>
|
||||||
<div>节点:{{ node.labels?.[0]?.text || node.id }}</div>
|
<DiagramItemRecord :data-view="state.dataView.get(node.id)"/>
|
||||||
<div>宽: {{ node.width }}, 高: {{ node.height }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template> -->
|
</transition>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -23,6 +26,12 @@ import { mcpClientAdapter } from '@/views/connect/core';
|
|||||||
import { invalidConnectionDetector, type Edge, type Node, type NodeDataView } from './diagram';
|
import { invalidConnectionDetector, type Edge, type Node, type NodeDataView } from './diagram';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
|
|
||||||
|
import DiagramItemRecord from './diagram-item-record.vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const svgContainer = ref<HTMLDivElement | null>(null);
|
const svgContainer = ref<HTMLDivElement | null>(null);
|
||||||
let prevNodes: any[] = [];
|
let prevNodes: any[] = [];
|
||||||
let prevEdges: any[] = [];
|
let prevEdges: any[] = [];
|
||||||
@ -37,6 +46,27 @@ const state = reactive({
|
|||||||
dataView: new Map<string, NodeDataView>
|
dataView: new Map<string, NodeDataView>
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let cancelHoverHandler: NodeJS.Timeout | undefined = undefined;
|
||||||
|
|
||||||
|
const setHoverItem = (id: string) => {
|
||||||
|
if (cancelHoverHandler) {
|
||||||
|
clearTimeout(cancelHoverHandler);
|
||||||
|
}
|
||||||
|
state.hoverNodeId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearHoverItem = () => {
|
||||||
|
cancelHoverHandler = setTimeout(() => {
|
||||||
|
if (cancelHoverHandler) {
|
||||||
|
clearTimeout(cancelHoverHandler);
|
||||||
|
}
|
||||||
|
if (state.hoverNodeId) {
|
||||||
|
state.hoverNodeId = null;
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
};
|
||||||
|
|
||||||
const getAllTools = async () => {
|
const getAllTools = async () => {
|
||||||
const items = [];
|
const items = [];
|
||||||
for (const client of mcpClientAdapter.clients) {
|
for (const client of mcpClientAdapter.clients) {
|
||||||
@ -287,12 +317,12 @@ function renderSvg() {
|
|||||||
} else {
|
} else {
|
||||||
state.selectedNodeId = d.id;
|
state.selectedNodeId = d.id;
|
||||||
renderSvg();
|
renderSvg();
|
||||||
context.setCaption('选择另一个节点以定义测试拓扑');
|
context.setCaption(t('select-node-define-test-tomo'));
|
||||||
}
|
}
|
||||||
state.draggingNodeId = null;
|
state.draggingNodeId = null;
|
||||||
})
|
})
|
||||||
.on('mouseover', function (event, d) {
|
.on('mouseover', function (event, d) {
|
||||||
state.hoverNodeId = d.id;
|
setHoverItem(d.id);
|
||||||
d3.select(this).select('rect')
|
d3.select(this).select('rect')
|
||||||
.transition()
|
.transition()
|
||||||
.duration(200)
|
.duration(200)
|
||||||
@ -300,7 +330,7 @@ function renderSvg() {
|
|||||||
.attr('stroke-width', 2);
|
.attr('stroke-width', 2);
|
||||||
})
|
})
|
||||||
.on('mouseout', function (event, d) {
|
.on('mouseout', function (event, d) {
|
||||||
state.hoverNodeId = null;
|
clearHoverItem();
|
||||||
if (state.selectedNodeId === d.id) return;
|
if (state.selectedNodeId === d.id) return;
|
||||||
d3.select(this).select('rect')
|
d3.select(this).select('rect')
|
||||||
.transition()
|
.transition()
|
||||||
@ -436,7 +466,7 @@ function renderSvg() {
|
|||||||
.attr('stroke', 'var(--main-color)')
|
.attr('stroke', 'var(--main-color)')
|
||||||
.attr('stroke-width', 4.5);
|
.attr('stroke-width', 4.5);
|
||||||
|
|
||||||
context.setCaption('点击边以删除');
|
context.setCaption(t('click-edge-to-delete'));
|
||||||
|
|
||||||
})
|
})
|
||||||
.on('mouseout', function () {
|
.on('mouseout', function () {
|
||||||
@ -500,10 +530,8 @@ onMounted(() => {
|
|||||||
function getNodePopupStyle(node: any): any {
|
function getNodePopupStyle(node: any): any {
|
||||||
// 节点的 svg 坐标转为容器内绝对定位
|
// 节点的 svg 坐标转为容器内绝对定位
|
||||||
// 注意:这里假设 offsetX、node.x、node.y 已经是最新的
|
// 注意:这里假设 offsetX、node.x、node.y 已经是最新的
|
||||||
console.log(node);
|
const left = (node.x || 0) + (node.width || 160) + 120; // 节点右侧
|
||||||
|
const top = (node.y || 0) + 30;
|
||||||
const left = (node.x || 0) + (node.width || 160) - 120; // 节点右侧
|
|
||||||
const top = (node.y || 0) + 30; // 节点顶部对齐
|
|
||||||
return {
|
return {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: `${left}px`,
|
left: `${left}px`,
|
@ -17,7 +17,12 @@
|
|||||||
placeholder="请输入 prompt" />
|
placeholder="请输入 prompt" />
|
||||||
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
<div style="display: flex; align-items: center; margin-bottom: 8px;">
|
||||||
<el-switch v-model="enableXmlWrapper" style="margin-right: 8px;" />
|
<el-switch v-model="enableXmlWrapper" style="margin-right: 8px;" />
|
||||||
<span style="opacity: 0.7;">enableXmlWrapper</span>
|
<span
|
||||||
|
:style="{
|
||||||
|
opacity: enableXmlWrapper? 1 : 0.7,
|
||||||
|
color: enableXmlWrapper ? 'var(--main-color)' : undefined
|
||||||
|
}"
|
||||||
|
>XML</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: right;">
|
<div style="text-align: right;">
|
||||||
<el-button size="small" @click="testFormVisible = false">{{ t("cancel") }}</el-button>
|
<el-button size="small" @click="testFormVisible = false">{{ t("cancel") }}</el-button>
|
||||||
@ -44,6 +49,9 @@ import { nextTick, provide, ref } from 'vue';
|
|||||||
import Diagram from './diagram.vue';
|
import Diagram from './diagram.vue';
|
||||||
import { makeNodeTest, topoSortParallel, type DiagramContext, type DiagramState } from './diagram';
|
import { makeNodeTest, topoSortParallel, type DiagramContext, type DiagramState } from './diagram';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import { tabs } from '../../panel';
|
||||||
|
import type { ToolStorage } from '../tools';
|
||||||
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
const showDiagram = ref(true);
|
const showDiagram = ref(true);
|
||||||
@ -52,6 +60,21 @@ const { t } = useI18n();
|
|||||||
const caption = ref('');
|
const caption = ref('');
|
||||||
const showCaption = ref(false);
|
const showCaption = ref(false);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
tabId: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const tab = tabs.content[props.tabId];
|
||||||
|
const tabStorage = tab.storage as ToolStorage;
|
||||||
|
|
||||||
|
if (!tabStorage.formData) {
|
||||||
|
tabStorage.formData = {};
|
||||||
|
}
|
||||||
|
|
||||||
function setCaption(text: string) {
|
function setCaption(text: string) {
|
||||||
caption.value = text;
|
caption.value = text;
|
||||||
if (caption.value) {
|
if (caption.value) {
|
@ -1,11 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-scrollbar height="100%">
|
<el-scrollbar height="100%">
|
||||||
<AutoDetector />
|
<AutoDetector :tab-id="props.tabId" />
|
||||||
<div class="tool-module">
|
<div class="tool-module">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<h2>
|
<h2>
|
||||||
<span class="iconfont icon-tool"></span>
|
<span class="iconfont icon-tool"></span>
|
||||||
工具模块
|
{{ t('tool-module') }}
|
||||||
</h2>
|
</h2>
|
||||||
<ToolList :tab-id="props.tabId"></ToolList>
|
<ToolList :tab-id="props.tabId"></ToolList>
|
||||||
|
|
||||||
@ -25,7 +25,10 @@ import { defineProps } from 'vue';
|
|||||||
import ToolList from './tool-list.vue';
|
import ToolList from './tool-list.vue';
|
||||||
import ToolExecutor from './tool-executor.vue';
|
import ToolExecutor from './tool-executor.vue';
|
||||||
import ToolLogger from './tool-logger.vue';
|
import ToolLogger from './tool-logger.vue';
|
||||||
import AutoDetector from './auto-detector.vue';
|
import AutoDetector from './auto-detector/index.vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
tabId: {
|
tabId: {
|
||||||
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "كيفية الاستخدام؟",
|
"how-to-use": "كيفية الاستخدام؟",
|
||||||
"is-required": "هو حقل مطلوب",
|
"is-required": "هو حقل مطلوب",
|
||||||
"edit-ai-mook-prompt": "تحرير إشارات AI Mook",
|
"edit-ai-mook-prompt": "تحرير إشارات AI Mook",
|
||||||
"start-auto-detect": "بدء عملية الفحص الذاتي"
|
"start-auto-detect": "بدء عملية الفحص الذاتي",
|
||||||
|
"tool-module": "وحدة الأدوات",
|
||||||
|
"prompt-module": "وحدة المطالبات",
|
||||||
|
"not-select-begin-node": "لم يتم تحديد عقدة البداية",
|
||||||
|
"can-make-loop": "سيؤدي الاتصال إلى تكوين حلقة",
|
||||||
|
"this-is-repeat-connection": "هذا رابط مكرر",
|
||||||
|
"ai-gen-error-json": "خطأ في تحليل JSON الذي تم إنشاؤه بواسطة الذكاء الاصطناعي",
|
||||||
|
"ai-invoke-unknown-tool": "استدعت الذكاء الاصطناعي أداة غير معروفة",
|
||||||
|
"click-edge-to-delete": "انقر على الحافة للحذف",
|
||||||
|
"select-node-define-test-tomo": "اختر عقدة أخرى لتحديد طوبولوجيا الاختبار"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "Wie benutzt man?",
|
"how-to-use": "Wie benutzt man?",
|
||||||
"is-required": "ist ein Pflichtfeld",
|
"is-required": "ist ein Pflichtfeld",
|
||||||
"edit-ai-mook-prompt": "AI Mook-Prompts bearbeiten",
|
"edit-ai-mook-prompt": "AI Mook-Prompts bearbeiten",
|
||||||
"start-auto-detect": "Selbsttest starten"
|
"start-auto-detect": "Selbsttest starten",
|
||||||
|
"tool-module": "Werkzeugmodul",
|
||||||
|
"prompt-module": "Aufforderungsmodul",
|
||||||
|
"not-select-begin-node": "Kein Startknoten ausgewählt",
|
||||||
|
"can-make-loop": "Die Verbindung wird eine Schleife bilden",
|
||||||
|
"this-is-repeat-connection": "Dies ist ein doppelter Link",
|
||||||
|
"ai-gen-error-json": "Fehler beim Parsen von KI-generiertem JSON",
|
||||||
|
"ai-invoke-unknown-tool": "KI hat ein unbekanntes Tool aufgerufen",
|
||||||
|
"click-edge-to-delete": "Klicken Sie auf die Kante, um sie zu löschen",
|
||||||
|
"select-node-define-test-tomo": "Wählen Sie einen anderen Knoten aus, um die Testtopologie zu definieren"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "How to use?",
|
"how-to-use": "How to use?",
|
||||||
"is-required": "is a required field",
|
"is-required": "is a required field",
|
||||||
"edit-ai-mook-prompt": "Edit AI Mook prompts",
|
"edit-ai-mook-prompt": "Edit AI Mook prompts",
|
||||||
"start-auto-detect": "Start self-check"
|
"start-auto-detect": "Start self-check",
|
||||||
|
"tool-module": "Tool module",
|
||||||
|
"prompt-module": "Prompt Module",
|
||||||
|
"not-select-begin-node": "No starting node selected",
|
||||||
|
"can-make-loop": "The connection will form a loop",
|
||||||
|
"this-is-repeat-connection": "This is a duplicate link",
|
||||||
|
"ai-gen-error-json": "AI-generated JSON parsing error",
|
||||||
|
"ai-invoke-unknown-tool": "AI called an unknown tool",
|
||||||
|
"click-edge-to-delete": "Click the edge to delete",
|
||||||
|
"select-node-define-test-tomo": "Select another node to define the test topology"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "Comment utiliser ?",
|
"how-to-use": "Comment utiliser ?",
|
||||||
"is-required": "est un champ obligatoire",
|
"is-required": "est un champ obligatoire",
|
||||||
"edit-ai-mook-prompt": "Modifier les invites AI Mook",
|
"edit-ai-mook-prompt": "Modifier les invites AI Mook",
|
||||||
"start-auto-detect": "Démarrer l'autovérification"
|
"start-auto-detect": "Démarrer l'autovérification",
|
||||||
|
"tool-module": "Module d'outils",
|
||||||
|
"prompt-module": "Module d'invite",
|
||||||
|
"not-select-begin-node": "Aucun nœud de départ sélectionné",
|
||||||
|
"can-make-loop": "La connexion formera une boucle",
|
||||||
|
"this-is-repeat-connection": "Ceci est un lien en double",
|
||||||
|
"ai-gen-error-json": "Erreur d'analyse JSON générée par IA",
|
||||||
|
"ai-invoke-unknown-tool": "L'IA a appelé un outil inconnu",
|
||||||
|
"click-edge-to-delete": "Cliquez sur le bord pour supprimer",
|
||||||
|
"select-node-define-test-tomo": "Sélectionnez un autre nœud pour définir la topologie de test"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "使用方法",
|
"how-to-use": "使用方法",
|
||||||
"is-required": "は必須フィールドです",
|
"is-required": "は必須フィールドです",
|
||||||
"edit-ai-mook-prompt": "AI Mookプロンプトを編集",
|
"edit-ai-mook-prompt": "AI Mookプロンプトを編集",
|
||||||
"start-auto-detect": "自己診断を開始"
|
"start-auto-detect": "自己診断を開始",
|
||||||
|
"tool-module": "ツールモジュール",
|
||||||
|
"prompt-module": "プロンプトモジュール",
|
||||||
|
"not-select-begin-node": "開始ノードが選択されていません",
|
||||||
|
"can-make-loop": "接続によりループが形成されます",
|
||||||
|
"this-is-repeat-connection": "これは重複したリンクです",
|
||||||
|
"ai-gen-error-json": "AI生成JSONの解析エラー",
|
||||||
|
"ai-invoke-unknown-tool": "AIが未知のツールを呼び出しました",
|
||||||
|
"click-edge-to-delete": "クリックして削除",
|
||||||
|
"select-node-define-test-tomo": "テストトポロジを定義するために別のノードを選択してください"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "사용 방법?",
|
"how-to-use": "사용 방법?",
|
||||||
"is-required": "는 필수 필드입니다",
|
"is-required": "는 필수 필드입니다",
|
||||||
"edit-ai-mook-prompt": "AI Mook 프롬프트 편집",
|
"edit-ai-mook-prompt": "AI Mook 프롬프트 편집",
|
||||||
"start-auto-detect": "자체 점검 시작"
|
"start-auto-detect": "자체 점검 시작",
|
||||||
|
"tool-module": "도구 모듈",
|
||||||
|
"prompt-module": "프롬프트 모듈",
|
||||||
|
"not-select-begin-node": "시작 노드가 선택되지 않았습니다",
|
||||||
|
"can-make-loop": "연결이 루프를 형성합니다",
|
||||||
|
"this-is-repeat-connection": "이것은 중복된 링크입니다",
|
||||||
|
"ai-gen-error-json": "AI 생성 JSON 구문 분석 오류",
|
||||||
|
"ai-invoke-unknown-tool": "AI가 알 수 없는 도구를 호출했습니다",
|
||||||
|
"click-edge-to-delete": "가장자리를 클릭하여 삭제",
|
||||||
|
"select-node-define-test-tomo": "테스트 토폴로지를 정의하려면 다른 노드를 선택하세요"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "Как использовать?",
|
"how-to-use": "Как использовать?",
|
||||||
"is-required": "является обязательным полем",
|
"is-required": "является обязательным полем",
|
||||||
"edit-ai-mook-prompt": "Редактировать подсказки AI Mook",
|
"edit-ai-mook-prompt": "Редактировать подсказки AI Mook",
|
||||||
"start-auto-detect": "Запустить самопроверку"
|
"start-auto-detect": "Запустить самопроверку",
|
||||||
|
"tool-module": "Модуль инструментов",
|
||||||
|
"prompt-module": "Модуль подсказок",
|
||||||
|
"not-select-begin-node": "Начальный узел не выбран",
|
||||||
|
"can-make-loop": "Соединение образует петлю",
|
||||||
|
"this-is-repeat-connection": "Это повторяющаяся ссылка",
|
||||||
|
"ai-gen-error-json": "Ошибка разбора JSON, созданного ИИ",
|
||||||
|
"ai-invoke-unknown-tool": "ИИ вызвал неизвестный инструмент",
|
||||||
|
"click-edge-to-delete": "Нажмите на край, чтобы удалить",
|
||||||
|
"select-node-define-test-tomo": "Выберите другой узел для определения тестовой топологии"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "如何使用?",
|
"how-to-use": "如何使用?",
|
||||||
"is-required": "是必填字段",
|
"is-required": "是必填字段",
|
||||||
"edit-ai-mook-prompt": "编辑 AI Mook 提示词",
|
"edit-ai-mook-prompt": "编辑 AI Mook 提示词",
|
||||||
"start-auto-detect": "开启自检程序"
|
"start-auto-detect": "开启自检程序",
|
||||||
|
"tool-module": "工具模块",
|
||||||
|
"prompt-module": "提示词模块",
|
||||||
|
"not-select-begin-node": "未选择起始节点",
|
||||||
|
"can-make-loop": "连接会形成环路",
|
||||||
|
"this-is-repeat-connection": "这是一个重复的连接",
|
||||||
|
"ai-gen-error-json": "AI 生成的 JSON 解析错误",
|
||||||
|
"ai-invoke-unknown-tool": "AI 调用了未知的工具",
|
||||||
|
"click-edge-to-delete": "点击边以删除",
|
||||||
|
"select-node-define-test-tomo": "选择另一个节点以定义测试拓扑"
|
||||||
}
|
}
|
@ -185,5 +185,14 @@
|
|||||||
"how-to-use": "如何使用?",
|
"how-to-use": "如何使用?",
|
||||||
"is-required": "是必填欄位",
|
"is-required": "是必填欄位",
|
||||||
"edit-ai-mook-prompt": "編輯AI Mook提示詞",
|
"edit-ai-mook-prompt": "編輯AI Mook提示詞",
|
||||||
"start-auto-detect": "開啟自檢程序"
|
"start-auto-detect": "開啟自檢程序",
|
||||||
|
"tool-module": "工具模組",
|
||||||
|
"prompt-module": "提示詞模組",
|
||||||
|
"not-select-begin-node": "未選擇起始節點",
|
||||||
|
"can-make-loop": "連接會形成環路",
|
||||||
|
"this-is-repeat-connection": "這是一個重複的連結",
|
||||||
|
"ai-gen-error-json": "AI 生成的 JSON 解析錯誤",
|
||||||
|
"ai-invoke-unknown-tool": "AI調用了未知的工具",
|
||||||
|
"click-edge-to-delete": "點擊邊緣以刪除",
|
||||||
|
"select-node-define-test-tomo": "選擇另一個節點以定義測試拓撲"
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user