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) {