预设兼容:按真实抓包对齐装配与包装层,补上声明式工具与预设正则。

- 装配只认 prompt_order.enabled;squash_system_messages 只合并相邻 system(新增 system 档,连接符按酒馆用单换行)
- 包装层:new_chat_prompt、示例对话(new_example_chat_prompt + <START> 切段 + name)、角色卡三块与 personality_format/scenario_format、{{user}}/{{char}} 取值、任务契约并进预设条目
- 工具协议:按 ToolBindings / 伪工具协议数据声明真 tools(presetToolPolicy=preset),工具描述用到的条目不再重复作为消息发出
- 正则:promptOnly 作用于对话历史(含 depth 过滤)、写入时脚本改写回复;{{//}} 注释按配平扫描
- tools/st-request-diff:真假上游抓包对比工具、三份预设的机制结论与实测报告
This commit is contained in:
2026-10-23 00:13:08 +08:00
parent ed09e5c831
commit 9dc927282f
94 changed files with 11558 additions and 413 deletions
+109
View File
@@ -0,0 +1,109 @@
import { describe, expect, it } from "vitest";
import type { ChatMessage } from "../src/llm/client.js";
import { squashMessages } from "../src/llm/message-squash.js";
const sys = (content: string): ChatMessage => ({ role: "system", content });
const user = (content: string): ChatMessage => ({ role: "user", content });
const asst = (content: string): ChatMessage => ({ role: "assistant", content });
const toolCall: ChatMessage = {
role: "assistant",
content: null,
tool_calls: [
{ id: "1", type: "function", function: { name: "t", arguments: "{}" } },
],
};
const toolResult: ChatMessage = { role: "tool", content: "{}", tool_call_id: "1" };
describe("squashMessages", () => {
it("none returns the list untouched", () => {
const input = [sys("a"), sys("b")];
expect(squashMessages(input, "none")).toBe(input);
});
it("merge joins adjacent same-role messages with a blank line", () => {
const out = squashMessages([sys("a"), sys("b"), user("c")], "merge");
expect(out).toEqual([sys("a\n\nb"), user("c")]);
});
it("merge keeps role changes intact", () => {
const out = squashMessages([sys("a"), user("b"), asst("c")], "merge");
expect(out.map((m) => m.role)).toEqual(["system", "user", "assistant"]);
});
it("never merges tool groups", () => {
const out = squashMessages(
[sys("a"), sys("b"), toolCall, toolResult, asst("x"), asst("y")],
"merge",
);
expect(out.map((m) => m.role)).toEqual([
"system",
"assistant",
"tool",
"assistant",
]);
// 工具组原样保留
expect(out[1]).toBe(toolCall);
expect(out[2]).toBe(toolResult);
});
it("semi folds system into neighbouring messages", () => {
const out = squashMessages(
[sys("规则"), user("问题"), sys("补充"), asst("回答")],
"semi",
);
expect(out).toEqual([user("规则\n\n问题"), asst("补充\n\n回答")]);
});
it("strict makes the first message a user", () => {
const out = squashMessages([asst("前言"), user("问题")], "strict");
expect(out[0]?.role).toBe("user");
expect(out[0]?.content).toBe("前言\n\n问题");
});
it("single-user-turn collapses everything into one user message", () => {
const out = squashMessages(
[sys("规则"), user("问题"), asst("回答")],
"single-user-turn",
);
expect(out).toEqual([user("规则\n\n问题\n\n回答")]);
});
it("falls back to merge when a tool group is present", () => {
const out = squashMessages(
[sys("a"), sys("b"), toolCall, toolResult],
"single-user-turn",
);
expect(out.map((m) => m.role)).toEqual(["system", "assistant", "tool"]);
expect(out[0]?.content).toBe("a\n\nb");
});
it("handles empty input", () => {
expect(squashMessages([], "strict")).toEqual([]);
});
});
describe("system 档(对齐酒馆 squashSystemMessages)", () => {
it("只合并相邻 system,user/assistant 不动", () => {
const out = squashMessages(
[sys("a"), sys("b"), user("u1"), user("u2"), asst("c1"), asst("c2"), sys("d"), sys("e")],
"system",
);
expect(out).toEqual([
sys("a\nb"),
user("u1"),
user("u2"),
asst("c1"),
asst("c2"),
sys("d\ne"),
]);
});
it("不碰工具组", () => {
const out = squashMessages(
[sys("a"), sys("b"), toolCall, toolResult, sys("c"), sys("d")],
"system",
);
expect(out.map((m) => m.role)).toEqual(["system", "assistant", "tool", "system"]);
});
});