30e80c0eed
- 新增「提示词」页(/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>
57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
// 行级 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 };
|
||
}
|