89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import { strict as assert } from "node:assert";
|
|
import test from "node:test";
|
|
import type { AiContext } from "../src/lib/ai.ts";
|
|
|
|
class MemoryStorage {
|
|
private values = new Map<string, string>();
|
|
|
|
getItem(key: string): string | null {
|
|
return this.values.get(key) ?? null;
|
|
}
|
|
|
|
setItem(key: string, value: string) {
|
|
this.values.set(key, value);
|
|
}
|
|
|
|
removeItem(key: string) {
|
|
this.values.delete(key);
|
|
}
|
|
|
|
clear() {
|
|
this.values.clear();
|
|
}
|
|
}
|
|
|
|
Object.defineProperty(globalThis, "localStorage", {
|
|
value: new MemoryStorage(),
|
|
configurable: true,
|
|
});
|
|
|
|
const { buildSystemPrompt } = await import("../src/lib/ai.ts");
|
|
|
|
function context(overrides: Partial<AiContext> = {}): AiContext {
|
|
return {
|
|
connectionName: "prod-analytics",
|
|
databaseType: "postgres",
|
|
database: "app",
|
|
currentSql: "",
|
|
tables: [
|
|
{
|
|
schema: "public",
|
|
name: "orders",
|
|
tableType: "TABLE",
|
|
columns: [
|
|
{ name: "id", data_type: "uuid", is_nullable: false, is_primary_key: true },
|
|
{ name: "user_id", data_type: "uuid", is_nullable: false },
|
|
{ name: "total", data_type: "numeric", is_nullable: false },
|
|
],
|
|
indexes: [{ name: "idx_orders_user_id", columns: ["user_id"], is_unique: false, is_primary: false }],
|
|
foreignKeys: [{ column: "user_id", ref_table: "users", ref_column: "id" }],
|
|
},
|
|
],
|
|
truncated: false,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test("agent mode prompt makes the first SQL block the executable recommendation", () => {
|
|
const prompt = buildSystemPrompt("generate", context(), "agent");
|
|
|
|
assert.match(prompt, /Agent 模式/);
|
|
assert.match(prompt, /第一个 ```sql 代码块只能包含最终推荐执行的 SQL/);
|
|
assert.match(prompt, /不要把解释性 SQL、备选 SQL、危险 SQL 放在第一个代码块/);
|
|
});
|
|
|
|
test("ask mode prompt forbids auto-execution assumptions", () => {
|
|
const prompt = buildSystemPrompt("generate", context(), "ask");
|
|
|
|
assert.match(prompt, /Ask 模式/);
|
|
assert.match(prompt, /只生成 SQL 和说明/);
|
|
assert.match(prompt, /不要暗示已经执行或即将自动执行/);
|
|
});
|
|
|
|
test("prompt gives explicit guidance for truncated schema context", () => {
|
|
const prompt = buildSystemPrompt("generate", context({ truncated: true }), "ask");
|
|
|
|
assert.match(prompt, /Schema context is truncated/);
|
|
assert.match(prompt, /如果请求可能涉及未出现的表或字段,不要猜测/);
|
|
assert.match(prompt, /@table/);
|
|
});
|
|
|
|
test("prompt enforces database dialect and single executable statement safety", () => {
|
|
const prompt = buildSystemPrompt("generate", context({ databaseType: "sqlserver" }), "agent");
|
|
|
|
assert.match(prompt, /严格使用当前数据库方言/);
|
|
assert.match(prompt, /分页、日期函数、字符串拼接/);
|
|
assert.match(prompt, /不要生成多语句 SQL/);
|
|
assert.match(prompt, /不要在同一个回答里混合 SELECT 和写操作/);
|
|
});
|