diff --git a/apps/desktop/src/App.vue b/apps/desktop/src/App.vue index e688d2acd8..4e7a9be443 100644 --- a/apps/desktop/src/App.vue +++ b/apps/desktop/src/App.vue @@ -102,7 +102,7 @@ import { createTabSwitcherKeyboardController } from "@/lib/tabs/tabSwitcherKeybo import { formatShortcutDisplay } from "@/lib/editor/shortcutDisplay"; import { supportsSqlFileExecution } from "@/lib/database/databaseCapabilities"; import { classifyAiSqlExecution } from "@/lib/ai/aiSqlExecutionPolicy"; -import { buildAppendedEditorSql } from "@/lib/ai/aiSqlAppend"; +import { buildAppendedEditorSql, buildDeduplicatedAppendedEditorSql } from "@/lib/ai/aiSqlAppend"; import { assessProductionSql } from "@/lib/database/productionSafety"; import { normalizeSqlExecutionTarget, sqlExecutionTargetCapabilities } from "@/lib/database/sqlExecutionTargetCapabilities"; import { executeWithProductionSqlGuard } from "@/lib/database/productionExecutionGuard"; @@ -2241,10 +2241,12 @@ function routeAiRedisCommand(command: string, execute: boolean): boolean { return true; } -function onAiReplaceSql(sql: string) { +function onAiAppendSql(sql: string) { if (routeAiRedisCommand(sql, false)) return; const tabId = ensureQueryTab(); - queryStore.updateSql(tabId, sql); + const currentSql = queryStore.tabs.find((tab) => tab.id === tabId)?.sql ?? ""; + const appendedSql = buildDeduplicatedAppendedEditorSql(currentSql, sql); + if (appendedSql !== currentSql) queryStore.updateSql(tabId, appendedSql); } function runAiGeneratedSql(sql: string) { @@ -2255,7 +2257,9 @@ function runAiGeneratedSql(sql: string) { function onAiExecuteSql(sql: string) { if (routeAiRedisCommand(sql, true)) return; const tabId = ensureQueryTab(); - queryStore.updateSql(tabId, buildAppendedEditorSql(activeTab.value?.sql || "", sql)); + const currentSql = queryStore.tabs.find((tab) => tab.id === tabId)?.sql ?? ""; + const appendedSql = buildDeduplicatedAppendedEditorSql(currentSql, sql); + if (appendedSql !== currentSql) queryStore.updateSql(tabId, appendedSql); runAiGeneratedSql(sql); } @@ -3225,7 +3229,7 @@ onUnmounted(() => { :tab="activeTab" :connection="activeConnection" :maximized="isAiPanelMaximized" - @replace-sql="onAiReplaceSql" + @append-sql="onAiAppendSql" @execute-sql="onAiExecuteSql" @temp-run-sql="onAiTempRunSql" @request-auto-execute-sql="onAiRequestAutoExecuteSql" diff --git a/apps/desktop/src/components/editor/AiAssistant.vue b/apps/desktop/src/components/editor/AiAssistant.vue index b2c055c9d8..31586cf773 100644 --- a/apps/desktop/src/components/editor/AiAssistant.vue +++ b/apps/desktop/src/components/editor/AiAssistant.vue @@ -24,6 +24,7 @@ import { GitBranch, HelpCircle, History, + ArrowDownToLine, Loader2, Maximize2, MessageSquarePlus, @@ -31,7 +32,6 @@ import { Pencil, Plus, RefreshCw, - Replace, Server, ShieldCheck, Table2, @@ -242,7 +242,7 @@ const props = defineProps<{ }>(); const emit = defineEmits<{ - replaceSql: [sql: string]; + appendSql: [sql: string]; executeSql: [sql: string]; tempRunSql: [sql: string]; requestAutoExecuteSql: [sql: string]; @@ -1197,7 +1197,7 @@ function sendProposalReply(positive: boolean) { const isWriteConfirmation = isActionableWriteProposalMessage(target); if (positive && productionContext.value.active && (target.kind === "writeSqlConfirmation" || looksLikeWriteSqlProposal(target.content))) { const sql = extractFirstSqlCodeBlock(target.content); - if (sql) emit("replaceSql", sql); + if (sql) emit("appendSql", sql); toast(t("production.aiReviewRequired"), 5000); return; } @@ -3477,7 +3477,7 @@ function applySql(code: string) { emit("insertRedisCommand", code); return; } - emit("replaceSql", code); + emit("appendSql", code); } function executeSql(code: string) { @@ -4604,7 +4604,7 @@ async function openExternalUrl(url: string) {