feat(admin): 提示词控制面页 + 概览/状态页重做 + 接入 vitest
- 新增「提示词」页(/prompts):接 /api/v1/prompts,建版本/激活热下发/ 对比激活版行级 diff/撤销,挂到配置组 - 概览页重做为系统控制塔:吃 admin/overview(全平台口径)——平台任务/ 评测/用户规模/服务在线 + 模型路由态 + 提示词覆盖态 + 健康拓扑 + 30s自刷 - 服务状态页重做:中性克制风 + 请求链路做成深色实时数据管道(流动光点/ 节点辉光) + MCP 工具改能力域配色小卡片 - 接入 vitest(此前零测试):41 单测(api 控制面/lib diff/路由派生) - api.ts 增 statsOverview/adminOverview/prompt 控制面四接口 + groupPrompts Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { lineDiff, diffStat } from "./diff";
|
||||
|
||||
describe("lineDiff", () => {
|
||||
it("完全相同 → 全 eq", () => {
|
||||
const d = lineDiff("a\nb\nc", "a\nb\nc");
|
||||
expect(d.every((l) => l.op === "eq")).toBe(true);
|
||||
expect(d.map((l) => l.text)).toEqual(["a", "b", "c"]);
|
||||
});
|
||||
|
||||
it("纯新增行标 add", () => {
|
||||
const d = lineDiff("a\nc", "a\nb\nc");
|
||||
expect(d).toEqual([
|
||||
{ op: "eq", text: "a" },
|
||||
{ op: "add", text: "b" },
|
||||
{ op: "eq", text: "c" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("纯删除行标 del", () => {
|
||||
const d = lineDiff("a\nb\nc", "a\nc");
|
||||
expect(d).toEqual([
|
||||
{ op: "eq", text: "a" },
|
||||
{ op: "del", text: "b" },
|
||||
{ op: "eq", text: "c" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("替换 = del 旧 + add 新", () => {
|
||||
const d = lineDiff("hello\nworld", "hello\nthere");
|
||||
expect(d).toContainEqual({ op: "del", text: "world" });
|
||||
expect(d).toContainEqual({ op: "add", text: "there" });
|
||||
expect(d[0]).toEqual({ op: "eq", text: "hello" });
|
||||
});
|
||||
|
||||
it("空 → 非空全是 add", () => {
|
||||
const d = lineDiff("", "x\ny");
|
||||
// 空串 split 出一个空行,故首行是 "" 的替换
|
||||
expect(d.filter((l) => l.op === "add").map((l) => l.text)).toContain("x");
|
||||
expect(d.filter((l) => l.op === "add").map((l) => l.text)).toContain("y");
|
||||
});
|
||||
|
||||
it("保留公共子序列、只动差异块", () => {
|
||||
const d = lineDiff("1\n2\n3\n4", "1\nX\n3\n4");
|
||||
expect(d.filter((l) => l.op === "eq").map((l) => l.text)).toEqual(["1", "3", "4"]);
|
||||
expect(diffStat(d)).toEqual({ add: 1, del: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
describe("diffStat", () => {
|
||||
it("统计 add/del 行数", () => {
|
||||
expect(diffStat(lineDiff("a\nb", "a\nb\nc\nd"))).toEqual({ add: 2, del: 0 });
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
// 行级 diff(LCS)—— 用于 prompt 控制面"选某版 vs 当前激活版"的差异预览。
|
||||
// 纯函数、无依赖,便于单测。
|
||||
|
||||
export type DiffOp = "eq" | "add" | "del";
|
||||
export interface DiffLine {
|
||||
op: DiffOp; // eq=两侧相同 / add=仅在 b(新增)/ del=仅在 a(删除)
|
||||
text: string;
|
||||
}
|
||||
|
||||
// lineDiff(a, b):把 a → b 的逐行变化展开。基于最长公共子序列。
|
||||
export function lineDiff(a: string, b: string): DiffLine[] {
|
||||
const al = a.split("\n");
|
||||
const bl = b.split("\n");
|
||||
const n = al.length;
|
||||
const m = bl.length;
|
||||
|
||||
// LCS 长度表:lcs[i][j] = al[i:] 与 bl[j:] 的最长公共子序列长度。
|
||||
const lcs: number[][] = Array.from({ length: n + 1 }, () => new Array<number>(m + 1).fill(0));
|
||||
for (let i = n - 1; i >= 0; i--) {
|
||||
for (let j = m - 1; j >= 0; j--) {
|
||||
lcs[i][j] = al[i] === bl[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// 回溯:相同→eq;否则按 LCS 走向决定 del(消耗 a)还是 add(消耗 b)。
|
||||
const out: DiffLine[] = [];
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
while (i < n && j < m) {
|
||||
if (al[i] === bl[j]) {
|
||||
out.push({ op: "eq", text: al[i] });
|
||||
i++;
|
||||
j++;
|
||||
} else if (lcs[i + 1][j] >= lcs[i][j + 1]) {
|
||||
out.push({ op: "del", text: al[i] });
|
||||
i++;
|
||||
} else {
|
||||
out.push({ op: "add", text: bl[j] });
|
||||
j++;
|
||||
}
|
||||
}
|
||||
while (i < n) out.push({ op: "del", text: al[i++] });
|
||||
while (j < m) out.push({ op: "add", text: bl[j++] });
|
||||
return out;
|
||||
}
|
||||
|
||||
// diffStat:统计新增/删除行数(给 UI 角标"+3 -1")。
|
||||
export function diffStat(lines: DiffLine[]): { add: number; del: number } {
|
||||
let add = 0;
|
||||
let del = 0;
|
||||
for (const l of lines) {
|
||||
if (l.op === "add") add++;
|
||||
else if (l.op === "del") del++;
|
||||
}
|
||||
return { add, del };
|
||||
}
|
||||
Reference in New Issue
Block a user