From 2f41c2318fc5cde5f8407cb4df5d60644968b58c Mon Sep 17 00:00:00 2001 From: Hexqi Date: Fri, 13 Feb 2026 18:49:02 +0800 Subject: [PATCH 01/35] fix: chat issue (#1770) --- packages/plugins/robot/src/Main.vue | 4 +-- .../robot/src/components/chat/RobotChat.vue | 3 +- .../src/composables/core/useConversation.ts | 4 ++- .../src/composables/core/useMessageStream.ts | 1 + .../src/composables/features/useToolCalls.ts | 9 ++++- .../plugins/robot/src/composables/useChat.ts | 36 ++++++++++++++----- .../plugins/robot/src/utils/chat.utils.ts | 3 +- 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/packages/plugins/robot/src/Main.vue b/packages/plugins/robot/src/Main.vue index a4dfbe0466..4eeba186b8 100644 --- a/packages/plugins/robot/src/Main.vue +++ b/packages/plugins/robot/src/Main.vue @@ -18,7 +18,7 @@ v-model:fullscreen="fullscreen" v-model:show="robotVisible" v-model:input="inputMessage" - :status="messageState.status" + :status="chatStatus" :prompt-items="promptItems" :bubble-renderers="bubbleRenderers" :allowFiles="isVisualModel && robotSettingState.chatMode === ChatMode.Agent" @@ -147,9 +147,9 @@ const showTeleport = ref(false) const showSetting = ref(false) const { + chatStatus, inputMessage, messages, - messageState, changeChatMode, abortRequest, initChatClient, diff --git a/packages/plugins/robot/src/components/chat/RobotChat.vue b/packages/plugins/robot/src/components/chat/RobotChat.vue index e24c375bdd..155e2f3198 100644 --- a/packages/plugins/robot/src/components/chat/RobotChat.vue +++ b/packages/plugins/robot/src/components/chat/RobotChat.vue @@ -36,8 +36,7 @@ :placeholder="GeneratingStatus.includes(props.status) ? '正在思考中...' : '请输入您的问题'" :clearable="true" :loading="GeneratingStatus.includes(props.status)" - :showWordLimit="true" - :maxLength="4000" + :showWordLimit="false" @submit="handleSendMessage" @cancel="handleAbortRequest" :allowFiles="selectedAttachments.length < 1 && props.allowFiles" diff --git a/packages/plugins/robot/src/composables/core/useConversation.ts b/packages/plugins/robot/src/composables/core/useConversation.ts index 7c0da5e7e4..ae2d70869d 100644 --- a/packages/plugins/robot/src/composables/core/useConversation.ts +++ b/packages/plugins/robot/src/composables/core/useConversation.ts @@ -11,6 +11,7 @@ export interface ConversationAdapterOptions { statusManager: { isProcessing: () => boolean setProcessing: () => void + resetProcessing: () => void } } @@ -43,7 +44,8 @@ export function useConversationAdapter(options: ConversationAdapterOptions) { const contextMessages = toRaw(messages.value.slice(0, -1)) await onFinishRequest(finishReason ?? 'unknown', messages.value, contextMessages, messageState) const lastMessage = messages.value.at(-1) - if (lastMessage) { + if (lastMessage && finishReason === 'stop' && !lastMessage.tool_calls && statusManager.isProcessing()) { + statusManager.resetProcessing() await onMessageProcessed(finishReason ?? 'unknown', lastMessage.content ?? '', messages.value, {}) } } diff --git a/packages/plugins/robot/src/composables/core/useMessageStream.ts b/packages/plugins/robot/src/composables/core/useMessageStream.ts index bbf2bd3665..3699da0853 100644 --- a/packages/plugins/robot/src/composables/core/useMessageStream.ts +++ b/packages/plugins/robot/src/composables/core/useMessageStream.ts @@ -29,6 +29,7 @@ const handleDeltaReasoning = (choice: ChatCompletionStreamResponseChoice, lastMe }) } lastMessage.renderContent.at(-1)!.content += choice.delta.reasoning_content + lastMessage.reasoning_content = (lastMessage.reasoning_content || '') + choice.delta.reasoning_content } } diff --git a/packages/plugins/robot/src/composables/features/useToolCalls.ts b/packages/plugins/robot/src/composables/features/useToolCalls.ts index 7f0ff9d9cd..191ec4a0a2 100644 --- a/packages/plugins/robot/src/composables/features/useToolCalls.ts +++ b/packages/plugins/robot/src/composables/features/useToolCalls.ts @@ -74,6 +74,11 @@ export interface ToolCallHandlerConfig { onDone: (finishReason: string, messages: any[], contextMessages: any[], messageState: any) => Promise } getMessageState: () => any + statusManager?: { + isProcessing: () => boolean + setProcessing: () => void + resetProcessing: () => void + } } /** @@ -81,7 +86,7 @@ export interface ToolCallHandlerConfig { * 使用工厂函数模式,将所有依赖通过配置注入 */ export function createToolCallHandler(config: ToolCallHandlerConfig) { - const { client, getAbortController, formatMessages, hooks, streamHandlers, getMessageState } = config + const { client, getAbortController, formatMessages, hooks, streamHandlers, getMessageState, statusManager } = config return async (tool_calls: ResponseToolCall[], messages: any[], contextMessages: RobotMessage[]) => { const hasToolCall = tool_calls?.length > 0 @@ -118,6 +123,8 @@ export function createToolCallHandler(config: ToolCallHandlerConfig) { delete currentMessage.tool_calls + statusManager?.setProcessing() + // 使用工具调用结果继续对话 await client.chatStream( { messages: toolMessages as any, options: { signal: abortController.signal } }, diff --git a/packages/plugins/robot/src/composables/useChat.ts b/packages/plugins/robot/src/composables/useChat.ts index 1772d968d1..9ba4c505a1 100644 --- a/packages/plugins/robot/src/composables/useChat.ts +++ b/packages/plugins/robot/src/composables/useChat.ts @@ -1,4 +1,4 @@ -import { nextTick } from 'vue' +import { nextTick, ref } from 'vue' import { GeneratingStatus, STATUS, type ChatMessage, type MessageState } from '@opentiny/tiny-robot-kit' import { formatMessages, removeLoading } from '../utils' import { getClientConfig as getConfig, updateClientConfig as updateConfig, client } from '../services/aiClient' @@ -39,7 +39,7 @@ enum CHAT_STATUS { FINISHED = 'finished' // 本轮对话结束 } -let chatStatus: CHAT_STATUS = CHAT_STATUS.PROCESSING +const chatStatus = ref(CHAT_STATUS.FINISHED) const abortControllerMap: Record = {} @@ -52,9 +52,9 @@ const handleStreamData = createStreamDataHandler({ onStreamTools }, statusManager: { - isStreaming: () => chatStatus === CHAT_STATUS.STREAMING, + isStreaming: () => chatStatus.value === CHAT_STATUS.STREAMING, setStreaming: () => { - chatStatus = CHAT_STATUS.STREAMING + chatStatus.value = CHAT_STATUS.STREAMING } } }) @@ -110,11 +110,15 @@ const handleFinishRequest = async ( if (finishReason === 'aborted' || messageState?.status === STATUS.ABORTED) { messageState.status = STATUS.ABORTED + } else if (finishReason === 'stop' && !lastMessage.tool_calls) { + messageState.status = STATUS.FINISHED + chatStatus.value = CHAT_STATUS.FINISHED + await onMessageProcessed(finishReason, lastMessage.content ?? '', messages.value, {}) } } const handleRequestError = async (error: Error, messages: ChatMessage[], messageState: MessageState) => { - chatStatus = CHAT_STATUS.FINISHED + chatStatus.value = CHAT_STATUS.FINISHED delete abortControllerMap.main await onRequestEnd('error', messages.at(-1).content, messages, { error }) // 本次请求结束 messageState.status = STATUS.ERROR @@ -140,12 +144,15 @@ const { if (GeneratingStatus.includes(messageManager.messageState.status)) { messageManager.messageState.status = STATUS.FINISHED } - chatStatus = CHAT_STATUS.FINISHED + chatStatus.value = CHAT_STATUS.FINISHED }, statusManager: { - isProcessing: () => chatStatus === CHAT_STATUS.PROCESSING, + isProcessing: () => chatStatus.value === CHAT_STATUS.PROCESSING, setProcessing: () => { - chatStatus = CHAT_STATUS.PROCESSING + chatStatus.value = CHAT_STATUS.PROCESSING + }, + resetProcessing: () => { + chatStatus.value = CHAT_STATUS.FINISHED } } }) @@ -168,7 +175,16 @@ const handleToolCall = createToolCallHandler({ onError: handleRequestError, onDone: handleFinishRequest }, - getMessageState: () => messageManager.messageState + getMessageState: () => messageManager.messageState, + statusManager: { + isProcessing: () => chatStatus.value === CHAT_STATUS.PROCESSING, + setProcessing: () => { + chatStatus.value = CHAT_STATUS.PROCESSING + }, + resetProcessing: () => { + chatStatus.value = CHAT_STATUS.FINISHED + } + } }) // 包装 conversation 方法,添加业务特定逻辑 @@ -235,6 +251,7 @@ const abortRequest = () => { for (const key of Object.keys(abortControllerMap)) { delete abortControllerMap[key] } + chatStatus.value = CHAT_STATUS.FINISHED onRequestEnd('aborted', messageManager.messages.value.at(-1)?.content as string, messageManager.messages.value) } @@ -254,6 +271,7 @@ const changeChatMode = (chatMode: string) => { export default function () { return { + chatStatus, initChatClient, updateConfig, ...messageManager, diff --git a/packages/plugins/robot/src/utils/chat.utils.ts b/packages/plugins/robot/src/utils/chat.utils.ts index ddc0bb865b..557641dd79 100644 --- a/packages/plugins/robot/src/utils/chat.utils.ts +++ b/packages/plugins/robot/src/utils/chat.utils.ts @@ -11,7 +11,8 @@ export const formatMessages = (messages: LLMMessage[]) => { role: message.role, content: message.content, ...(message.tool_calls ? { tool_calls: message.tool_calls } : {}), - ...(message.tool_call_id ? { tool_call_id: message.tool_call_id } : {}) + ...(message.tool_call_id ? { tool_call_id: message.tool_call_id } : {}), + ...(message.reasoning_content ? { reasoning_content: message.reasoning_content } : {}) })) } From 19f6fa1b3e1c35fed124df35c14f08a3c6d0ba62 Mon Sep 17 00:00:00 2001 From: lichunn <46984087+lichunn@users.noreply.github.com> Date: Fri, 13 Feb 2026 20:33:00 +0800 Subject: [PATCH 02/35] =?UTF-8?q?fix=EF=BC=9Aappcenter=20my=20app=20id=20i?= =?UTF-8?q?ssue=20(#1771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/workspace/application-center/src/Main.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/workspace/application-center/src/Main.vue b/packages/workspace/application-center/src/Main.vue index d05f73f3b0..6f0fd97bfb 100644 --- a/packages/workspace/application-center/src/Main.vue +++ b/packages/workspace/application-center/src/Main.vue @@ -95,6 +95,7 @@ import { reactive, ref, onMounted } from 'vue' import { Button, Select, Pager, Grid, GridColumn, Divider, Search, Modal, Notify } from '@opentiny/vue' import { iconSearch } from '@opentiny/vue-icon' import { SearchEmpty } from '@opentiny/tiny-engine-common' +import { getMetaApi, META_SERVICE } from '@opentiny/tiny-engine-meta-register' import AppDialog from './AppDialog.vue' import { fetchApplicationList, createApplication, updateApplication, deleteApplication } from './js/http' @@ -113,6 +114,7 @@ export default { }, setup() { + const { getUserInfo } = getMetaApi(META_SERVICE.GlobalService) const appList = ref([]) const appFilterOptions = [ @@ -165,11 +167,12 @@ export default { }) const getApplicationList = () => { + const info = getUserInfo() const params = { currentPage: state.currentPage, pageSize: state.pageSize, name: state.appSearchKey, - createdBy: state.appFilter === 'all' ? '' : '1' + createdBy: state.appFilter === 'all' ? '' : info.id } if (state.orderBy === 'last_updated_time') { params.orderBy = state.orderBy From cd231d8991eadfc9457cda41390199ba4681860a Mon Sep 17 00:00:00 2001 From: lichunn <46984087+lichunn@users.noreply.github.com> Date: Fri, 13 Feb 2026 20:33:36 +0800 Subject: [PATCH 03/35] =?UTF-8?q?fix=EF=BC=9ACreate=20duplicate=20model=20?= =?UTF-8?q?error=20(#1772)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ModelSetting.vue | 139 ++++++++++++------ 1 file changed, 91 insertions(+), 48 deletions(-) diff --git a/packages/plugins/model-manager/src/components/ModelSetting.vue b/packages/plugins/model-manager/src/components/ModelSetting.vue index 73cad708a3..a4f78a423b 100644 --- a/packages/plugins/model-manager/src/components/ModelSetting.vue +++ b/packages/plugins/model-manager/src/components/ModelSetting.vue @@ -134,71 +134,114 @@ export default { field.options.splice(index, 1) } + const isSaving = ref(false) + // 保存模型时一并保存version字段 const saveModel = async () => { // 从子组件获取最新的数据 const latestModelData = modelBasicFormRef.value?.getLocalValue() - modelBasicFormRef.value.validate().then(async (valid) => { - if (valid) { - const newModel = { - description: latestModelData.description, - modelUrl: latestModelData.modelUrl, - nameCn: latestModelData.nameCn, - nameEn: latestModelData.nameEn, - version: latestModelData.version, - id: latestModelData.id, - parameters: latestModelData.parameters.filter((item) => !!item.prop) - } - let isModelRefRelative = true - let propertyName = '' - if (newModel.parameters?.length > 0) { - newModel.parameters.forEach((item) => { - if (item.type === 'Enum') { - item.options = JSON.stringify(item.options) - } - if (item.type === 'ModelRef') { - item.isModel = true - delete item.options - item.defaultValue = item.defaultValue || null - isModelRefRelative = !!item.defaultValue - propertyName = item.prop - } - }) - } - if (!isModelRefRelative) { + modelBasicFormRef.value + .validate() + .then(async (valid) => { + if (valid) { + isSaving.value = true // 设置保存标志 + + // 深拷贝一份数据用于保存 + const newModel = { + description: latestModelData.description, + modelUrl: latestModelData.modelUrl, + nameCn: latestModelData.nameCn, + nameEn: latestModelData.nameEn, + version: latestModelData.version, + id: latestModelData.id, + parameters: JSON.parse(JSON.stringify(latestModelData.parameters.filter((item) => !!item.prop))) + } + + let isModelRefRelative = true + let propertyName = '' + + if (newModel.parameters?.length > 0) { + newModel.parameters.forEach((item) => { + if (item.type === 'Enum') { + // 保存时序列化为字符串 + item.options = JSON.stringify(item.options || []) + } + if (item.type === 'ModelRef') { + item.isModel = true + delete item.options + item.defaultValue = item.defaultValue || null + isModelRefRelative = !!item.defaultValue + propertyName = item.prop + } + }) + } + + if (!isModelRefRelative) { + Notify({ + type: 'error', + message: `字段${propertyName}未关联模型引用` + }) + isSaving.value = false + return + } + + if (latestModelData.id === null) { + delete newModel.id + await createModel(newModel) + } else { + await updateModel(newModel.id, newModel) + } + + emit('editCallback') Notify({ - type: 'error', - message: `字段${propertyName}未关联模型引用` + type: 'success', + message: '保存成功' }) - return - } - if (latestModelData.id === null) { - delete newModel.id - await createModel(newModel) - } else { - await updateModel(newModel.id, newModel) + + // 关闭面板 + closeModelSettingPanel() + selectedModel.value = null + isSaving.value = false } - emit('editCallback') - Notify({ - type: 'success', - message: '保存成功' - }) - selectedModel.value = null - } - }) + }) + .catch(() => { + isSaving.value = false + }) } const deleteModel = () => { - $emit('deleteCallback', selectedModel) + emit('deleteCallback', selectedModel.value) closeModelSettingPanel() } + // 监听 props 变化,同步到本地(当选择不同模型时) watch( () => props.model, (newModel) => { - selectedModel.value = newModel + if (!isSaving.value && newModel) { + // 只在非保存过程中处理 + // 深拷贝避免修改props + const modelCopy = JSON.parse(JSON.stringify(newModel)) + + // 加载时反序列化枚举字段 + if (modelCopy.parameters) { + modelCopy.parameters.forEach((param) => { + if (param.type === 'Enum' && typeof param.options === 'string') { + try { + param.options = JSON.parse(param.options) + } catch (e) { + param.options = [{ value: '', label: '' }] + } + } + }) + } + + selectedModel.value = modelCopy + } else { + selectedModel.value = newModel + } }, - { deep: true } + { deep: true, immediate: true } ) return { isShow, From fcb15b07535a2ca6fd867bf8ba5493e0089fe902 Mon Sep 17 00:00:00 2001 From: lichunn <46984087+lichunn@users.noreply.github.com> Date: Fri, 13 Feb 2026 20:34:32 +0800 Subject: [PATCH 04/35] =?UTF-8?q?fix=EF=BC=9ALogin=20module=20UI=20optimiz?= =?UTF-8?q?ation=20(#1769)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../design-core/src/login/ForgotPassword.vue | 38 +++++++++++++++++-- packages/design-core/src/login/Index.vue | 38 +++++++++++++++---- packages/design-core/src/login/Login.vue | 22 +++++------ packages/design-core/src/login/Register.vue | 20 +++++++--- .../design-core/src/login/RegisterSuccess.vue | 26 ++++--------- 5 files changed, 98 insertions(+), 46 deletions(-) diff --git a/packages/design-core/src/login/ForgotPassword.vue b/packages/design-core/src/login/ForgotPassword.vue index c3f8bfbbc9..29159986dd 100644 --- a/packages/design-core/src/login/ForgotPassword.vue +++ b/packages/design-core/src/login/ForgotPassword.vue @@ -52,14 +52,17 @@ - 提交 + 提交 +
+ +
diff --git a/packages/plugins/resource/src/ResourceSetting.vue b/packages/plugins/resource/src/ResourceSetting.vue index a9f73da52e..1c6d776209 100644 --- a/packages/plugins/resource/src/ResourceSetting.vue +++ b/packages/plugins/resource/src/ResourceSetting.vue @@ -1,5 +1,11 @@