Files
diegosouzapw--omniroute/tests/unit/translator-redacted-thinking-model-aware-4479.test.ts
2026-07-13 13:39:12 +08:00

73 lines
3.2 KiB
TypeScript

/**
* Regression for #4479 (port: model-aware supportsRedactedThinking for mixed-format providers).
*
* Mixed-format providers like `opencode-go` have some models that target Anthropic's
* Messages API (targetFormat="claude", e.g. minimax-m3) and others that target OpenAI's
* /chat/completions (default, e.g. glm-5.1). The Anthropic-format models hit a real
* Anthropic endpoint that validates signatures, so they need `redacted_thinking` blocks —
* but `supportsRedactedThinking` used to be decided by provider name alone, so those models
* received plain `thinking` blocks without a signature and got a 400.
*
* prepareClaudeRequest now takes a `model` param and also enables redacted_thinking when
* getModelTargetFormat(provider, model) === "claude". These tests pin both branches plus
* the backward-compatible no-model call.
*/
import test from "node:test";
import assert from "node:assert/strict";
const { prepareClaudeRequest } = await import("../../open-sse/translator/helpers/claudeHelper.ts");
const { DEFAULT_THINKING_CLAUDE_SIGNATURE } = await import(
"../../open-sse/config/defaultThinkingSignature.ts"
);
// Assistant turn with only a tool_use → prepareClaudeRequest injects a thinking block before
// it. Anthropic-format upstreams get redacted_thinking{data}; everyone else gets plain
// thinking{text}. Mirrors the shape in translator-claude-helper-thinking.test.ts.
function bodyWithToolUseNeedingThinking() {
return {
thinking: { type: "enabled", budget_tokens: 4096 },
messages: [
{ role: "user", content: [{ type: "text", text: "hi" }] },
{
role: "assistant",
content: [{ type: "tool_use", id: "call_x", name: "ls", input: { path: "." } }],
},
{
role: "user",
content: [{ type: "tool_result", tool_use_id: "call_x", content: "README.md" }],
},
],
};
}
test("opencode-go + claude-format model (minimax-m3) → redacted_thinking with synthetic data", () => {
const result = prepareClaudeRequest(
bodyWithToolUseNeedingThinking() as any,
"opencode-go",
false,
"minimax-m3"
);
const content = (result as any).messages[1].content;
assert.equal(content[0].type, "redacted_thinking", "claude-targetFormat model needs redacted_thinking");
assert.equal(content[0].data, DEFAULT_THINKING_CLAUDE_SIGNATURE);
assert.equal(content[0].thinking, undefined);
});
test("opencode-go + OpenAI-format model (glm-5.1) → plain thinking (no redaction)", () => {
const result = prepareClaudeRequest(
bodyWithToolUseNeedingThinking() as any,
"opencode-go",
false,
"glm-5.1"
);
const content = (result as any).messages[1].content;
assert.equal(content[0].type, "thinking", "OpenAI-targetFormat model must stay plain thinking");
assert.equal(content[0].data, undefined, "no synthetic redacted data for non-Anthropic upstream");
});
test("opencode-go without model param → plain thinking (backward-compatible)", () => {
const result = prepareClaudeRequest(bodyWithToolUseNeedingThinking() as any, "opencode-go");
const content = (result as any).messages[1].content;
assert.equal(content[0].type, "thinking", "no model → old provider-name behavior preserved");
});