From 125107857800bf4d29ae8a652f5c78a1403d5f27 Mon Sep 17 00:00:00 2001 From: lichunn <269031597@qq.com> Date: Fri, 19 Sep 2025 17:25:31 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=E6=B7=BB=E5=8A=A0=E8=A1=A5=E5=85=A8?= =?UTF-8?q?=E5=B0=8F=E6=A8=A1=E5=9E=8B=E4=BB=A5=E5=8F=8Arobot=E5=85=83?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai-plugin-configuration.md | 2 +- packages/plugins/robot/index.ts | 4 +- packages/plugins/robot/src/Main.vue | 59 +++++----- .../plugins/robot/src/RobotSettingPopover.vue | 36 +----- .../plugins/robot/src/RobotTypeSelect.vue | 5 +- packages/plugins/robot/src/js/index.ts | 11 ++ .../src/js/{robotSetting.ts => useRobot.ts} | 105 ++++++++++++------ packages/register/src/hooks.ts | 10 +- packages/register/src/types.ts | 2 + 9 files changed, 130 insertions(+), 104 deletions(-) create mode 100644 packages/plugins/robot/src/js/index.ts rename packages/plugins/robot/src/js/{robotSetting.ts => useRobot.ts} (58%) diff --git a/docs/extension-capabilities-tutorial/ai-plugin-configuration.md b/docs/extension-capabilities-tutorial/ai-plugin-configuration.md index 9c4c508ba8..90b91e934d 100644 --- a/docs/extension-capabilities-tutorial/ai-plugin-configuration.md +++ b/docs/extension-capabilities-tutorial/ai-plugin-configuration.md @@ -16,7 +16,7 @@ ### 前端代码改动 -在`tiny-engine/packages/plugins/robot/src/js/robotSetting.js`文件改动如下 +在`tiny-engine/packages/plugins/robot/src/js/useRobot.ts`文件改动如下 ![](./imgs/ai-image23.png) diff --git a/packages/plugins/robot/index.ts b/packages/plugins/robot/index.ts index 25336f8c83..ef4fba0da0 100644 --- a/packages/plugins/robot/index.ts +++ b/packages/plugins/robot/index.ts @@ -14,8 +14,10 @@ import entry from './src/Main.vue' import metaData from './meta' import './src/styles/vars.less' import '@opentiny/tiny-robot/dist/style.css' +import { RobotService } from './src/js/index' export default { ...metaData, - entry + entry, + metas: [RobotService] } diff --git a/packages/plugins/robot/src/Main.vue b/packages/plugins/robot/src/Main.vue index 16deb1dbee..df2ad51612 100644 --- a/packages/plugins/robot/src/Main.vue +++ b/packages/plugins/robot/src/Main.vue @@ -25,7 +25,7 @@ > @@ -73,7 +73,9 @@ :clearable="true" :showWordLimit="true" :allowFiles=" - singleAttachmentItems.length < 1 && VISUAL_MODEL.includes(selectedModel.model) && aiType === BUILD_TYPE + singleAttachmentItems.length < 1 && + VISUAL_MODEL.includes(robotSettingState.selectedModel.model) && + aiType === BUILD_TYPE " uploadTooltip="支持上传1张图片" @submit="sendContent(inputContent, false)" @@ -122,7 +124,7 @@ import { type Component } from 'vue' import { Notify, Loading, TinyPopover, TinyDialogBox } from '@opentiny/vue' -import { useCanvas, useModal, getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register' +import { useRobot, useCanvas, useModal, getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register' import { ToolbarBase } from '@opentiny/tiny-engine-common' import { TrContainer, @@ -138,17 +140,6 @@ import { IconNewSession } from '@opentiny/tiny-robot-svgs' import SchemaRenderer from '@opentiny/tiny-schema-renderer' import { utils } from '@opentiny/tiny-engine-utils' import RobotSettingPopover from './RobotSettingPopover.vue' -import { - getBlockContent, - initBlockList, - getAIModelOptions, - defaultSelectedModel, - isValidFastJsonPatch, - VISUAL_MODEL, - TALK_TYPE, - MCP_TYPE, - BUILD_TYPE -} from './js/robotSetting' import { PROMPTS } from './js/prompts' import * as jsonpatch from 'fast-json-patch' import { chatStream, checkComponentNameExists } from './js/utils' @@ -190,6 +181,17 @@ export default { }, emits: ['close-chat'], setup() { + const { + getBlockContent, + initBlockList, + getAIModelOptions, + isValidFastJsonPatch, + VISUAL_MODEL, + TALK_TYPE, + MCP_TYPE, + BUILD_TYPE, + robotSettingState + } = useRobot() const { pageState, importSchema, setSaved } = useCanvas() const AIModelOptions = getAIModelOptions() const robotVisible = ref(false) @@ -201,7 +203,6 @@ export default { const connectedFailed = ref(false) const inputContent = ref('') const inProcesing = ref(false) - const selectedModel = ref(defaultSelectedModel) const { confirm } = useModal() const showPopover = ref(false) const searchContent = ref('') @@ -226,7 +227,7 @@ export default { ? JSON.stringify(sessionProcess) : JSON.stringify({ foundationModel: { - ...selectedModel.value + ...robotSettingState.selectedModel }, messages: [], displayMessages: [], // 专门用来进行展示的消息,非原始消息,仅作为展示但是不作为请求的发送 @@ -357,9 +358,9 @@ export default { requestLoading.value = true await scrollContent() await sendMcpRequest(messages.value, { - model: selectedModel.value.model, + model: robotSettingState.selectedModel.model, headers: { - Authorization: `Bearer ${selectedModel.value.apiKey || import.meta.env.VITE_API_TOKEN}` + Authorization: `Bearer ${robotSettingState.selectedModel.apiKey || import.meta.env.VITE_API_TOKEN}` } }) } catch (error) { @@ -451,7 +452,7 @@ export default { } }, { - Authorization: `Bearer ${selectedModel.value.apiKey || import.meta.env.VITE_API_TOKEN}` + Authorization: `Bearer ${robotSettingState.selectedModel.apiKey || import.meta.env.VITE_API_TOKEN}` } ) } @@ -557,7 +558,7 @@ export default { // 根据localstorage初始化AI大模型 const initCurrentModel = (aiSession) => { - selectedModel.value = { + robotSettingState.selectedModel = { ...JSON.parse(aiSession)?.foundationModel } aiType.value = JSON.parse(aiSession)?.aiType @@ -607,17 +608,19 @@ export default { } const changeModel = (model) => { - if (selectedModel.value.baseUrl !== model.baseUrl || selectedModel.value !== model.model) { + if ( + robotSettingState.selectedModel.baseUrl !== model.baseUrl || + robotSettingState.selectedModel !== model.model + ) { confirm({ title: '切换AI大模型', message: '切换AI大模型将导致当前会话被清空,重新开启新会话,是否继续?', exec() { - selectedModel.value = { + robotSettingState.selectedModel = { label: model.label || model.model, activeName: model.activeName, baseUrl: model.baseUrl, model: model.model, - maxTokens: model.maxTokens, apiKey: model.apiKey } singleAttachmentItems.value = [] @@ -627,11 +630,11 @@ export default { }) } if ( - selectedModel.value.apiKey !== model.apiKey && - selectedModel.value.baseUrl === model.baseUrl && - selectedModel.value.model === model.model + robotSettingState.selectedModel.apiKey !== model.apiKey && + robotSettingState.selectedModel.baseUrl === model.baseUrl && + robotSettingState.selectedModel.model === model.model ) { - selectedModel.value.apiKey = model.apiKey + robotSettingState.selectedModel.apiKey = model.apiKey changeApiKey() } } @@ -796,7 +799,7 @@ export default { inputContent, connectedFailed, AIModelOptions, - selectedModel, + robotSettingState, showPopover, fullscreen, welcomeIcon, diff --git a/packages/plugins/robot/src/RobotSettingPopover.vue b/packages/plugins/robot/src/RobotSettingPopover.vue index bcb3ec32cd..210ab36970 100644 --- a/packages/plugins/robot/src/RobotSettingPopover.vue +++ b/packages/plugins/robot/src/RobotSettingPopover.vue @@ -17,7 +17,6 @@ v-model="state.existFormData.model" :options="state.modelOptions" placeholder="请选择" - @change="changeModel" > @@ -59,19 +58,6 @@ - - - - @@ -97,7 +83,7 @@ import { TinyTabItem, TinyAlert } from '@opentiny/vue' -import { EXISTING_MODELS, CUSTOMIZE, getAIModelOptions } from './js/robotSetting' +import { useRobot } from '@opentiny/tiny-engine-meta-register' export default { components: { @@ -118,12 +104,11 @@ export default { } }, setup(props, { emit }) { + const { EXISTING_MODELS, CUSTOMIZE, getAIModelOptions } = useRobot() const robotSettingExistForm = ref(null) const robotSettingCustomizeForm = ref(null) const apiKeyTip = 'API Key 是用于身份验证和权限控制的密钥,允许开发者通过API访问云服务商提供的大模型(如通义千问、deepseek等)。' - const maxTokensTip = - '上下文长度表示模型单次响应中最多生成的token数量(包括输入和输出的总和)。若该项不设置,默认为64K。' const AIModelOptions = getAIModelOptions() const state = reactive({ @@ -133,13 +118,11 @@ export default { label: '', baseUrl: '', model: '', - maxTokens: null, apiKey: '' }, customizeFormData: { baseUrl: '', model: '', - maxTokens: null, apiKey: '' } }) @@ -160,13 +143,6 @@ export default { state.modelOptions = options?.model state.existFormData.label = options?.label state.existFormData.model = state.modelOptions[0]?.value - state.existFormData.maxTokens = state.modelOptions[0]?.maxTokens - } - - const changeModel = () => { - state.existFormData.maxTokens = state.modelOptions.find( - (option) => option.value === state.existFormData.model - )?.maxTokens } const confirm = () => { @@ -178,9 +154,6 @@ export default { } else { formData = { ...state.customizeFormData } form = robotSettingCustomizeForm - if (!formData.maxTokens) { - formData.maxTokens = 64000 - } } form.value.validate((valid) => { @@ -201,7 +174,6 @@ export default { const data = { baseUrl: initModel.baseUrl, model: initModel.model, - maxTokens: initModel.maxTokens, apiKey: initModel.apiKey } state.activeName = initModel.activeName @@ -232,9 +204,7 @@ export default { confirm, closePanel, changeBaseUrl, - changeModel, - apiKeyTip, - maxTokensTip + apiKeyTip } } } diff --git a/packages/plugins/robot/src/RobotTypeSelect.vue b/packages/plugins/robot/src/RobotTypeSelect.vue index 579e1f58c5..2ae2778448 100644 --- a/packages/plugins/robot/src/RobotTypeSelect.vue +++ b/packages/plugins/robot/src/RobotTypeSelect.vue @@ -45,7 +45,7 @@ import { reactive, watch } from 'vue' import type { Component } from 'vue' import { Tabs, TabItem, Tooltip } from '@opentiny/vue' -import { TALK_TYPE, MCP_TYPE, BUILD_TYPE } from './js/robotSetting' +import { useRobot } from '@opentiny/tiny-engine-meta-register' export default { components: { @@ -56,11 +56,12 @@ export default { props: { aiType: { type: String, - default: TALK_TYPE + default: 'talk' } }, emits: ['typeChange'], setup(props, { emit }) { + const { TALK_TYPE, MCP_TYPE, BUILD_TYPE } = useRobot() const state = reactive({ activeNameTabs: props.aiType || TALK_TYPE }) diff --git a/packages/plugins/robot/src/js/index.ts b/packages/plugins/robot/src/js/index.ts new file mode 100644 index 0000000000..a17eb974d9 --- /dev/null +++ b/packages/plugins/robot/src/js/index.ts @@ -0,0 +1,11 @@ +import { HOOK_NAME } from '@opentiny/tiny-engine-meta-register' +import useRobot from './useRobot' + +export const RobotService = { + id: 'engine.service.robot', + type: 'MetaService', + apis: useRobot(), + composable: { + name: HOOK_NAME.useRobot + } +} diff --git a/packages/plugins/robot/src/js/robotSetting.ts b/packages/plugins/robot/src/js/useRobot.ts similarity index 58% rename from packages/plugins/robot/src/js/robotSetting.ts rename to packages/plugins/robot/src/js/useRobot.ts index 242588bd0d..e0c0f0df8f 100644 --- a/packages/plugins/robot/src/js/robotSetting.ts +++ b/packages/plugins/robot/src/js/useRobot.ts @@ -10,65 +10,75 @@ * */ -/* metaService: engine.plugins.robot.js-robotSetting */ +/* metaService: engine.plugins.robot.useRobot */ import { reactive } from 'vue' import { getOptions, getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register' import meta from '../../meta' -export const EXISTING_MODELS = 'existingModels' -export const CUSTOMIZE = 'customize' -export const VISUAL_MODEL = ['qwen-vl-max', 'qwen-vl-plus'] -export const TALK_TYPE = 'talk' -export const MCP_TYPE = 'mcp' -export const BUILD_TYPE = 'build' +const EXISTING_MODELS = 'existingModels' +const CUSTOMIZE = 'customize' +const VISUAL_MODEL = ['qwen-vl-max', 'qwen-vl-plus'] +const TALK_TYPE = 'talk' +const MCP_TYPE = 'mcp' +const BUILD_TYPE = 'build' -export const AIModelOptions = [ +const AIModelOptions = [ { label: '阿里云百炼', value: 'https://dashscope.aliyuncs.com/compatible-mode/v1', model: [ - { label: 'qwen-vl-max', value: 'qwen-vl-max', maxTokens: 32000 }, - { label: 'qwen-vl-plus', value: 'qwen-vl-plus', maxTokens: 32000 }, - { label: 'qwen-plus', value: 'qwen-plus', maxTokens: 131072 }, - { label: 'qwen-max', value: 'qwen-max', maxTokens: 32768 }, - { label: 'qwen-turbo', value: 'qwen-turbo', maxTokens: 1000000 }, - { label: 'qwen-long', value: 'qwen-long', maxTokens: 1000000 }, - { label: 'deepseek-r1', value: 'deepseek-r1', maxTokens: 65792 }, - { label: 'deepseek-v3', value: 'deepseek-v3', maxTokens: 65792 } + { label: 'qwen-vl-max', value: 'qwen-vl-max' }, + { label: 'qwen-vl-plus', value: 'qwen-vl-plus' }, + { label: 'qwen-plus', value: 'qwen-plus' }, + { label: 'qwen-max', value: 'qwen-max' }, + { label: 'qwen-turbo', value: 'qwen-turbo' }, + { label: 'qwen-long', value: 'qwen-long' }, + { label: 'qwen2.5-14b-instruct', value: 'qwen2.5-14b-instruct' }, + { label: 'qwen2.5-7b-instruct', value: 'qwen2.5-7b-instruct' }, + { label: 'qwen2.5-coder-7b-instruct', value: 'qwen2.5-coder-7b-instruct' }, + { label: 'qwen2.5-omni', value: 'qwen2.5-omni' }, + { label: 'qwen3-14b', value: 'qwen3-14b' }, + { label: 'qwen3-8b', value: 'qwen3-8b' }, + { label: 'deepseek-r1', value: 'deepseek-r1' }, + { label: 'deepseek-v3', value: 'deepseek-v3' } ] }, { label: 'DeepSeek', value: 'https://api.deepseek.com/v1', model: [ - { label: 'deepseek-chat', value: 'deepseek-chat', maxTokens: 64000 }, - { label: 'deepseek-reasoner', value: 'deepseek-reasoner', maxTokens: 64000 } + { label: 'deepseek-chat', value: 'deepseek-chat' }, + { label: 'deepseek-reasoner', value: 'deepseek-reasoner' }, + { label: 'deepseek-r1-distill-qwen-1.5b', value: 'deepseek-r1-distill-qwen-1.5b' }, + { label: 'deepseek-r1-distill-qwen-32b', value: 'deepseek-r1-distill-qwen-32b' } ] }, { label: '月之暗面', value: 'https://api.moonshot.cn/v1', model: [ - { label: 'moonshot-v1-8k', value: 'moonshot-v1-8k', maxTokens: 8192 }, - { label: 'moonshot-v1-32k', value: 'moonshot-v1-32k', maxTokens: 32768 }, - { label: 'moonshot-v1-128k', value: 'moonshot-v1-128k', maxTokens: 131072 } + { label: 'moonshot-v1-8k', value: 'moonshot-v1-8k' }, + { label: 'moonshot-v1-32k', value: 'moonshot-v1-32k' }, + { label: 'moonshot-v1-128k', value: 'moonshot-v1-128k' } ] } ] -export const getAIModelOptions = () => { +const getAIModelOptions = () => { const aiRobotOptions = getOptions(meta.id)?.customCompatibleAIModels || [] return aiRobotOptions.length ? aiRobotOptions : AIModelOptions } -export const defaultSelectedModel = { - label: getAIModelOptions()[0].label, - activeName: EXISTING_MODELS, - baseUrl: getAIModelOptions()[0].value, - model: getAIModelOptions()[0].model[0].value, - maxTokens: getAIModelOptions()[0].model[0].maxTokens, - apiKey: '' -} +const robotSettingState = reactive({ + selectedModel: { + label: getAIModelOptions()[0].label, + activeName: EXISTING_MODELS, + baseUrl: getAIModelOptions()[0].value, + model: getAIModelOptions()[0].model[0].value, + maxTokens: getAIModelOptions()[0].model[0].maxTokens, + apiKey: '' + } +}) // 这里存放的是aichat的响应式数据 const state = reactive({ @@ -76,13 +86,13 @@ const state = reactive({ blockContent: '' }) -export const getBlocks = () => state.blockList || [] +const getBlocks = () => state.blockList || [] -export const setBlocks = (blocks) => { +const setBlocks = (blocks) => { state.blockList = blocks } -export const getBlockContent = () => state.blockContent || '' +const getBlockContent = () => state.blockContent || '' const transformBlockNameToElement = (label) => { const elementName = label.replace(/[A-Z]/g, (letter, index) => { @@ -106,7 +116,7 @@ const setBlockContent = (list = getBlocks()) => { } } -export const initBlockList = async () => { +const initBlockList = async () => { if (state.blockList?.length) { return } @@ -121,7 +131,7 @@ export const initBlockList = async () => { } } -export const isValidOperation = (operation) => { +const isValidOperation = (operation) => { const allowedOps = ['add', 'remove', 'replace', 'move', 'copy', 'test', '_get'] if (typeof operation !== 'object' || operation === null) { @@ -155,7 +165,7 @@ export const isValidOperation = (operation) => { return true } -export const isValidFastJsonPatch = (patch) => { +const isValidFastJsonPatch = (patch) => { if (Array.isArray(patch)) { return patch.every(isValidOperation) } else if (typeof patch === 'object' && patch !== null) { @@ -163,3 +173,26 @@ export const isValidFastJsonPatch = (patch) => { } return false } + +export default () => { + return { + EXISTING_MODELS, + CUSTOMIZE, + VISUAL_MODEL, + TALK_TYPE, + MCP_TYPE, + BUILD_TYPE, + AIModelOptions, + getAIModelOptions, + robotSettingState, + state, + getBlocks, + setBlocks, + getBlockContent, + transformBlockNameToElement, + setBlockContent, + initBlockList, + isValidOperation, + isValidFastJsonPatch + } +} diff --git a/packages/register/src/hooks.ts b/packages/register/src/hooks.ts index 837c9ce00b..cb1ca1d709 100644 --- a/packages/register/src/hooks.ts +++ b/packages/register/src/hooks.ts @@ -15,7 +15,8 @@ import type { UsePropertyApi, UseResourceApi, UseSaveLocalApi, - UseTranslateApi + UseTranslateApi, + UseRobotApi } from './types' export const HOOK_NAME = { @@ -38,7 +39,8 @@ export const HOOK_NAME = { useNotify: 'notify', useCustom: 'custom', useMaterial: 'material', - useStyle: 'style' + useStyle: 'style', + useRobot: 'robot' } as const type HookName = typeof HOOK_NAME[keyof typeof HOOK_NAME] @@ -63,7 +65,8 @@ const hooksState = { [HOOK_NAME.useModal]: {}, [HOOK_NAME.useMaterial]: {}, [HOOK_NAME.useStyle]: {}, - [HOOK_NAME.useCustom]: {} // 自定义 + [HOOK_NAME.useCustom]: {}, + [HOOK_NAME.useRobot]: {} // 自定义 } const getHook = (hookName: HookName, args: any[]) => { @@ -91,6 +94,7 @@ export const useEnv = (...args: any[]): ImportMetaEnv => getHook(HOOK_NAME.useEn export const useModal = (...args: any[]): UseModalApi => getHook(HOOK_NAME.useModal, args) export const useNotify = (...args: NotifyParams): NotifyResult => getHook(HOOK_NAME.useNotify, args) export const useMaterial = (...args: any[]): UseMaterialApi => getHook(HOOK_NAME.useMaterial, args) +export const useRobot = (...args: any[]): UseRobotApi => getHook(HOOK_NAME.useRobot, args) export const useStyle = (...args: any[]) => getHook(HOOK_NAME.useStyle, args) export const useCustom = (...args: any[]) => getHook(HOOK_NAME.useCustom, args) diff --git a/packages/register/src/types.ts b/packages/register/src/types.ts index e47b3dc657..dd4d376349 100644 --- a/packages/register/src/types.ts +++ b/packages/register/src/types.ts @@ -11,6 +11,7 @@ import type { BreadcrumbService } from '@opentiny/tiny-engine-toolbar-breadcrumb import type { SaveLocalService } from '@opentiny/tiny-engine-toolbar-generate-code' import type { HistoryService } from '@opentiny/tiny-engine-toolbar-redoundo' import type { Modal, Notify } from '@opentiny/tiny-engine-common' +import type { RobotService } from '@opentiny/tiny-engine-plugin-robot' export type UseCanvasApi = ReturnType export type UseLayoutApi = typeof LayoutService['apis'] @@ -23,6 +24,7 @@ export type UseTranslateApi = typeof TranslateService['apis'] export type UseMaterialApi = typeof MaterialService['apis'] export type UseResourceApi = typeof ResourceService['apis'] export type UsePageApi = typeof PageService['apis'] +export type UseRobotApi = typeof RobotService['apis'] // setting export type UsePropertiesApi = typeof PropertiesService['apis'] From cd2ed150e463d680d9368004206a1068a4422bfb Mon Sep 17 00:00:00 2001 From: lichunn <269031597@qq.com> Date: Mon, 22 Sep 2025 19:36:30 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:AI=E6=A8=A1=E5=9E=8B=E8=AE=BE=E7=BD=AE?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=A1=A5=E5=85=A8=E5=B0=8F=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E9=80=89=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/advanced-features/new-ai-plugin-usage.md | 4 +- packages/plugins/robot/src/Main.vue | 2 +- .../plugins/robot/src/RobotSettingPopover.vue | 48 ++++++++++++++----- packages/plugins/robot/src/js/useRobot.ts | 14 +++--- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/docs/advanced-features/new-ai-plugin-usage.md b/docs/advanced-features/new-ai-plugin-usage.md index 94d57a4875..e4dafb2c2f 100644 --- a/docs/advanced-features/new-ai-plugin-usage.md +++ b/docs/advanced-features/new-ai-plugin-usage.md @@ -65,8 +65,8 @@ MCP工具管理面板允许用户: label: 'DeepSeek', value: 'https://api.deepseek.com/v1', model: [ - { label: 'deepseek-chat', value: 'deepseek-chat', maxTokens: 64000 }, - { label: 'deepseek-reasoner', value: 'deepseek-reasoner', maxTokens: 64000 } + { label: 'deepseek-chat', value: 'deepseek-chat'}, + { label: 'deepseek-reasoner', value: 'deepseek-reasoner'} ] } ] diff --git a/packages/plugins/robot/src/Main.vue b/packages/plugins/robot/src/Main.vue index ae46816b36..b40e8b4c3f 100644 --- a/packages/plugins/robot/src/Main.vue +++ b/packages/plugins/robot/src/Main.vue @@ -25,7 +25,6 @@ > @@ -635,6 +634,7 @@ export default { activeName: model.activeName, baseUrl: model.baseUrl, model: model.model, + completeModel: model.completeModel, apiKey: model.apiKey } singleAttachmentItems.value = [] diff --git a/packages/plugins/robot/src/RobotSettingPopover.vue b/packages/plugins/robot/src/RobotSettingPopover.vue index 210ab36970..9ed429618c 100644 --- a/packages/plugins/robot/src/RobotSettingPopover.vue +++ b/packages/plugins/robot/src/RobotSettingPopover.vue @@ -19,6 +19,13 @@ placeholder="请选择" > + + + @@ -193,9 +189,7 @@ export default { getAIModelOptions, isValidFastJsonPatch, VISUAL_MODEL, - TALK_TYPE, - MCP_TYPE, - BUILD_TYPE, + AI_MODES, robotSettingState } = useRobot() const { pageState, importSchema, setSaved } = useCanvas() @@ -217,7 +211,7 @@ export default { const singleAttachmentItems = ref([]) const imageUrl = ref('') const MESSAGE_TIP = '已生成新的页面效果。' - const aiType = ref(TALK_TYPE) + const aiType = ref(AI_MODES['Chat']) const chatContainerRef = ref(null) const showTeleport = ref(false) const { deepClone, string2Obj, reactiveObj2String: obj2String } = utils @@ -267,7 +261,7 @@ export default { const sendProcess = { ...sessionProcess } const firstMessage = sendProcess.messages[0] let firstContent = firstMessage.content - if (aiType.value === BUILD_TYPE) { + if (aiType.value === AI_MODES['Builder']) { firstContent = firstMessage.content.map((item) => { if (item.type === 'text') { item.text = `[指令] ${PROMPTS}\n[知识] ${searchContent.value}\n[当前schema] ${JSON.stringify( @@ -277,7 +271,7 @@ export default { return item }) } - if (useMcpServer().isToolsEnabled && aiType.value === TALK_TYPE) { + if (useMcpServer().isToolsEnabled && aiType.value === AI_MODES['Chat']) { firstContent = `${getBlockContent()}\n${codeRules}\n${firstMessage.content[0]?.text || ''}` } @@ -320,7 +314,7 @@ export default { // 处理响应 const handleResponse = ({ id, chatMessage }: { id: string; chatMessage: any }, currentJson) => { try { - if (aiType.value === BUILD_TYPE) { + if (aiType.value === AI_MODES['Builder']) { const regex = /```json([\s\S]*?)```/ const match = chatMessage?.content.match(regex) @@ -344,7 +338,7 @@ export default { inProcesing.value = false connectedFailed.value = false } - if (aiType.value === TALK_TYPE) { + if (aiType.value === AI_MODES['Chat']) { sessionProcess.messages.push(getAiRespMessage(chatMessage?.content)) sessionProcess.displayMessages.push(getAiRespMessage(chatMessage?.content)) messages.value[messages.value.length - 1].content = chatMessage?.content @@ -360,7 +354,7 @@ export default { // 发送流式请求 const sendStreamRequest = async () => { const requestData = getSendSeesionProcess() - if (useMcpServer().isToolsEnabled && aiType.value === TALK_TYPE) { + if (useMcpServer().isToolsEnabled && aiType.value === AI_MODES['Chat']) { try { requestLoading.value = true await scrollContent() @@ -506,7 +500,7 @@ export default { text } ] - if (singleAttachmentItems.value.length > 0 && aiType.value === BUILD_TYPE) { + if (singleAttachmentItems.value.length > 0 && aiType.value === AI_MODES['Builder']) { content.push({ type: 'image_url', image_url: { @@ -536,7 +530,7 @@ export default { if (chatWindowOpened.value === false) { await resizeChatWindow() } - if (!sessionProcess?.messages?.length && aiType.value !== TALK_TYPE) { + if (!sessionProcess?.messages?.length && aiType.value !== AI_MODES['Chat']) { sessionProcess?.messages.push({ role: 'system', content: [ @@ -552,7 +546,7 @@ export default { messages.value.push(message) sessionProcess?.messages.push(getSessionMessage(realContent)) sessionProcess?.displayMessages.push(message) - if (aiType.value === BUILD_TYPE && (!searchContent.value || !sessionProcess.messages?.length)) { + if (aiType.value === AI_MODES['Builder'] && (!searchContent.value || !sessionProcess.messages?.length)) { await search(realContent) } @@ -574,7 +568,7 @@ export default { robotSettingState.selectedModel = { ...JSON.parse(aiSession)?.foundationModel } - aiType.value = JSON.parse(aiSession)?.aiType + aiType.value = JSON.parse(aiSession)?.aiType || aiType.value } const initChat = () => { @@ -802,6 +796,12 @@ export default { } }) + const isVisualModel = () => { + const platform = AIModelOptions.find((option) => option.value === robotSettingState.selectedModel.baseUrl) + const modelAbility = platform.model.find((item) => item.value === robotSettingState.selectedModel.model) + return modelAbility?.ability?.includes('visual') || false + } + return { chatContainerRef, robotVisible, @@ -824,9 +824,7 @@ export default { MarkdownRenderer, requestLoading, aiType, - TALK_TYPE, - MCP_TYPE, - BUILD_TYPE, + AI_MODES, showTeleport, sendContent, endContent, @@ -841,6 +839,7 @@ export default { handleSingleFileRemove, handleSingleFileRetry, typeChange, + isVisualModel, contentRenderers, mcpDrawerPosition } diff --git a/packages/plugins/robot/src/RobotSettingPopover.vue b/packages/plugins/robot/src/RobotSettingPopover.vue index 9ed429618c..a7ab36b61d 100644 --- a/packages/plugins/robot/src/RobotSettingPopover.vue +++ b/packages/plugins/robot/src/RobotSettingPopover.vue @@ -3,7 +3,13 @@
设置
- + @@ -122,7 +128,6 @@ export default { const state = reactive({ activeName: EXISTING_MODELS, modelOptions: [], - completeModelOptions: [], existFormData: { label: '', baseUrl: '', @@ -143,6 +148,10 @@ export default { apiKey: [{ required: true, message: '必填', trigger: 'blur' }] } + const existFormRules = { + apiKey: [{ required: true, message: '必填', trigger: 'blur' }] + } + const closePanel = () => { emit('close') } @@ -151,10 +160,9 @@ export default { state.existFormData.apiKey = '' const options = AIModelOptions.find((option) => option.value === state.existFormData.baseUrl) state.modelOptions = options?.model - state.completeModelOptions = options?.completeModel || [] state.existFormData.label = options?.label state.existFormData.model = state.modelOptions[0]?.value || '' - state.existFormData.completeModel = state.completeModelOptions[0]?.value || '' + state.existFormData.completeModel = state.modelOptions[0]?.value || '' } const confirm = () => { @@ -207,7 +215,6 @@ export default { } const options = AIModelOptions.find((option) => option.value === state.existFormData.baseUrl) state.modelOptions = options?.model - state.completeModelOptions = options?.completeModel || [] } if (state.activeName === CUSTOMIZE) { state.customizeFormData = { ...data } @@ -227,6 +234,7 @@ export default { robotSettingCustomizeForm, state, customizeFormRules, + existFormRules, confirm, closePanel, changeBaseUrl, diff --git a/packages/plugins/robot/src/RobotTypeSelect.vue b/packages/plugins/robot/src/RobotTypeSelect.vue index 2ae2778448..58b711c682 100644 --- a/packages/plugins/robot/src/RobotTypeSelect.vue +++ b/packages/plugins/robot/src/RobotTypeSelect.vue @@ -1,7 +1,7 @@