From 122853d0893941594b2e145874f040b1dd9bb7d9 Mon Sep 17 00:00:00 2001 From: Abeautifulsnow Date: Mon, 27 Jul 2026 12:33:06 +0800 Subject: [PATCH] fix(ai): reset action when reselecting active mode --- .../src/components/editor/AiAssistant.vue | 256 ++++++++++-------- apps/desktop/src/i18n/locales/en.ts | 2 +- apps/desktop/src/i18n/locales/es.ts | 2 +- apps/desktop/src/i18n/locales/it.ts | 2 +- apps/desktop/src/i18n/locales/ja.ts | 2 +- apps/desktop/src/i18n/locales/pt-BR.ts | 2 +- apps/desktop/src/i18n/locales/zh-CN.ts | 2 +- apps/desktop/src/i18n/locales/zh-TW.ts | 2 +- .../aiAssistantComposerLayout.test.ts | 55 ++++ .../aiAssistantModePersistence.test.ts | 34 +++ 10 files changed, 245 insertions(+), 114 deletions(-) create mode 100644 packages/app-tests/aiAssistantComposerLayout.test.ts create mode 100644 packages/app-tests/aiAssistantModePersistence.test.ts diff --git a/apps/desktop/src/components/editor/AiAssistant.vue b/apps/desktop/src/components/editor/AiAssistant.vue index 6df18596e7..17c1998524 100644 --- a/apps/desktop/src/components/editor/AiAssistant.vue +++ b/apps/desktop/src/components/editor/AiAssistant.vue @@ -40,7 +40,6 @@ import { import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; -import LightDropdown from "@/components/ui/LightDropdown.vue"; import { ScrollArea } from "@/components/ui/scroll-area"; import { useTheme } from "@/composables/useTheme"; import { useSettingsStore, AI_PROVIDER_PRESETS, normalizeAiConfig } from "@/stores/settingsStore"; @@ -147,12 +146,13 @@ const messages = ref([]); const isGenerating = ref(false); const scrollRef = ref | null>(null); const activeAction = ref("general"); -const assistantMode = ref<"ask" | "agent">("ask"); +const assistantMode = ref("ask"); const currentSessionId = ref(""); const conversationId = ref(""); const conversations = ref([]); const showConversationList = ref(false); const showTemplateSelector = ref(false); +const modeActionOpen = ref(false); // Prompt template selection (panel-session scope) const activeTemplateIds = ref([]); @@ -213,6 +213,12 @@ const templateSelectorLabel = computed(() => { if (count === 1) return name; return `${name} +${count - 1}`; }); +const templateSelectorTriggerLabel = computed(() => { + if (activeTemplates.value.length === 0) { + return t("ai.templateSelectorLabel", { label: templateSelectorLabel.value }); + } + return templateSelectorLabel.value; +}); const promptTextareaRef = ref(null); const shouldAutoScroll = ref(true); const userPausedAutoScroll = ref(false); @@ -588,28 +594,6 @@ function sendProposalReply(positive: boolean) { } const activePlaceholder = computed(() => `${t(`ai.placeholders.${activeAction.value}`)} ${t("ai.tableMentionPlaceholderHint")}`); -const activeModeHint = computed(() => t(`ai.modeHints.${assistantMode.value}`)); -const assistantModeItems = computed(() => [ - { - value: "ask", - label: t("ai.modes.ask"), - title: t("ai.modeHints.ask"), - icon: MessageSquarePlus, - }, - { - value: "agent", - label: t("ai.modes.agent"), - title: t("ai.modeHints.agent"), - icon: Bot, - }, -]); -const actionMenuItems = computed(() => - actionButtons.value.map((button) => ({ - value: button.action, - label: t(button.key), - icon: button.icon, - })), -); const aiCodeAppearance = computed(() => (isDark.value ? "dark" : "light")); const showActionButtons = computed(() => { @@ -617,6 +601,30 @@ const showActionButtons = computed(() => { return !isVectorDbType(props.connection.db_type); }); +const modeIcon = computed(() => (assistantMode.value === "agent" ? Bot : MessageSquarePlus)); +const modeLabel = computed(() => t(`ai.modes.${assistantMode.value}`)); +const selectedActionButton = computed(() => actionButtons.value.find((b) => b.action === activeAction.value)); +const modeActionTriggerLabel = computed(() => { + const modePart = `${modeLabel.value}`; + if (!showActionButtons.value || !selectedActionButton.value) return modePart; + return `${modePart} · ${t(selectedActionButton.value.key)}`; +}); + +function switchModeActionTab(mode: "ask" | "agent") { + activeAction.value = resolveDefaultAction(mode); + if (assistantMode.value !== mode) { + // Set the mode after the action so the tab label and picker stay aligned. + assistantMode.value = mode; + } +} + +function selectModeActionItem(action: AiAction) { + // Vector databases only support generation; keep this constraint at the selection boundary. + if (!showActionButtons.value) return; + selectAction(action); + modeActionOpen.value = false; +} + const { databaseOptions: allDbOptions, loadDatabaseOptions } = useDatabaseOptions(); const dbOptions = computed(() => { @@ -1713,6 +1721,9 @@ async function deleteConversation(id: string) { function startNewChat() { clearMessages(); showConversationList.value = false; + // A fresh conversation always starts from the safe, non-executing default. + assistantMode.value = "ask"; + activeAction.value = resolveDefaultAction("ask"); } onMounted(async () => { @@ -2088,54 +2099,95 @@ async function openExternalUrl(url: string) {
-
- - - -