把正文组成收成数据契约,程序投影与旁观维护不再靠模型临场猜。

有变量真值时固定开旁观填表,开场与游玩只填模型生成区。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-07 23:47:58 +08:00
co-authored by Cursor
parent bb4f934b3d
commit d0a48f9431
21 changed files with 3094 additions and 224 deletions
+37 -1
View File
@@ -13,7 +13,7 @@ import {
sanitizeReasoningEffort,
sanitizeVerbosity,
} from "../src/llm/generation-compat.js";
import { buildRequestBody } from "../src/llm/client.js";
import { buildRequestBody, extractMessageParts, openRouterSessionId } from "../src/llm/client.js";
import type { LlmConfig } from "../src/config/env.js";
const stGeneration = {
@@ -410,6 +410,24 @@ describe("fetchWithGenerationCompat", () => {
});
});
describe("extractMessageParts", () => {
it("keeps reply_user when arguments are an object and id is missing", () => {
const parts = extractMessageParts({
content: [{ type: "text", text: "同一次请求里的说明" }],
tool_calls: [
{
type: "function",
function: { name: "reply_user", arguments: { text: "形成了气氛" } },
},
],
});
expect(parts.toolCalls).toEqual([
{ id: "call-0", name: "reply_user", arguments: JSON.stringify({ text: "形成了气氛" }) },
]);
expect(parts.content).toBe("同一次请求里的说明");
});
});
describe("buildRequestBody", () => {
const messages = [{ role: "user" as const, content: "hi" }];
@@ -597,6 +615,24 @@ describe("buildRequestBody", () => {
expect(body.messages).toBe(messages);
});
it("writes session_id only for OpenRouter", () => {
const openrouter: LlmConfig = {
baseUrl: "https://openrouter.ai/api/v1",
apiKey: "k",
model: "google/gemini-3.8-flash",
};
const direct: LlmConfig = {
baseUrl: "https://api.deepseek.com/v1",
apiKey: "k",
model: "deepseek-v4-pro",
};
const id = "9b76dcb6-0703-4b0d-ba75-faa985b532b4";
expect(buildRequestBody(openrouter, messages, { sessionId: id }).session_id).toBe(id);
expect(buildRequestBody(direct, messages, { sessionId: id }).session_id).toBeUndefined();
expect(buildRequestBody(openrouter, messages, {}).session_id).toBeUndefined();
expect(openRouterSessionId(openrouter.baseUrl, ` ${"a".repeat(300)} `)).toHaveLength(256);
});
it("does not forward top_k from an imported ST preset", () => {
const config: LlmConfig = {
baseUrl: "https://example.test/v1",