fix(ai): append generated SQL without duplicates
This commit is contained in:
1 parent
143be57d41
commit
9491ab08df
5 files changed
+83
-12
No files matched your search
@@ -19,14 +19,23 @@ describe("AI Redis console routing", () => {
|
||||
});
|
||||
|
||||
it("keeps the existing SQL editor and execution behavior for non-Redis connections", () => {
|
||||
expect(aiAssistantSource).toContain('emit("replaceSql", code)');
|
||||
expect(aiAssistantSource).toContain('emit("appendSql", code)');
|
||||
expect(aiAssistantSource).toContain('emit("executeSql", code)');
|
||||
expect(aiAssistantSource).toContain('emit("tempRunSql", code)');
|
||||
expect(appSource).toContain("const tabId = ensureQueryTab();");
|
||||
expect(appSource).toContain("buildDeduplicatedAppendedEditorSql(currentSql, sql)");
|
||||
expect(appSource).toContain('buildAppendedEditorSql(activeTab.value?.sql || "", sql)');
|
||||
expect(appSource).toContain("const decision = classifyAiSqlExecution(sql, activeConnection.value);");
|
||||
});
|
||||
|
||||
it("deduplicates immediate-run editor writes without skipping execution", () => {
|
||||
const handler = appSource.match(/function onAiExecuteSql\(sql: string\) \{[\s\S]*?\n\}/)?.[0] ?? "";
|
||||
expect(handler).toContain("buildDeduplicatedAppendedEditorSql(currentSql, sql)");
|
||||
expect(handler).toContain("if (appendedSql !== currentSql) queryStore.updateSql(tabId, appendedSql);");
|
||||
expect(handler).toContain("runAiGeneratedSql(sql);");
|
||||
expect(handler).not.toContain("buildAppendedEditorSql(");
|
||||
});
|
||||
|
||||
it("uses the console safety path and rejects unavailable command input", () => {
|
||||
expect(classifyRedisCommandSafety("CONFIG SET requirepass secret")).toBe("blocked");
|
||||
expect(classifyRedisCommandSafety("FLUSHDB")).toBe("confirm");
|
||||
|
||||
@@ -17,3 +17,30 @@ export function buildAppendedEditorSql(currentEditorSql: string, newSql: string)
|
||||
|
||||
return `${currentEditorSql}${separator}${newSql}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append AI-generated SQL unless the exact text already exists as a standalone
|
||||
* editor block. AI appends use a blank line as their block separator, which
|
||||
* avoids treating a matching fragment inside a larger statement as a duplicate.
|
||||
*/
|
||||
export function buildDeduplicatedAppendedEditorSql(currentEditorSql: string, newSql: string): string {
|
||||
if (!newSql || containsStandaloneSqlBlock(currentEditorSql, newSql)) return currentEditorSql;
|
||||
return buildAppendedEditorSql(currentEditorSql, newSql);
|
||||
}
|
||||
|
||||
function containsStandaloneSqlBlock(editorSql: string, sql: string): boolean {
|
||||
let from = 0;
|
||||
while (from <= editorSql.length - sql.length) {
|
||||
const index = editorSql.indexOf(sql, from);
|
||||
if (index < 0) return false;
|
||||
|
||||
const before = editorSql.slice(0, index);
|
||||
const after = editorSql.slice(index + sql.length);
|
||||
const startsAtBlockBoundary = index === 0 || /(?:\r?\n){2}$/.test(before);
|
||||
const endsAtBlockBoundary = after.length === 0 || /^(?:\r?\n){2}/.test(after);
|
||||
if (startsAtBlockBoundary && endsAtBlockBoundary) return true;
|
||||
|
||||
from = index + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in new issue
Block a user