fix(tests): align deepseek-web-tools-execute with #9343 tool envelope contract

tests/unit/deepseek-web-tools-execute-2820.test.ts (executor level) was a
test-sibling forgotten when #9343 (commit d969555417) hardened tool-call
parsing: bare JSON with no explicit <tool>/<tool_call> envelope is never
promoted to tool_calls anymore (previously it was, whenever a tools[] set
was requested — a security gap allowing prose/code-fenced JSON echoed
back by the model, or a copy-attack, to trigger real tool execution).

Three siblings were updated in the same commit: web-tools-translation.test.ts
and web-tools-translation-2820.test.ts (parseToolCallsFromText, the shared
translator), and deepseek-web-tools-variants.test.ts (parseDeepSeekToolCalls,
deepseek-specific parser) — all inverted their bare-JSON assertions to
`toolCalls === null` + `content === text` (preserved verbatim, not stripped).
This file calls the executor's execute() (full HTTP round trip through
buildToolAwareResult), so it was not touched by that diff and kept
asserting the old contract (finish_reason: "tool_calls", content: null).

Verified against source (open-sse/executors/deepseek-web.ts
buildToolAwareResult): when parseDeepSeekToolCalls returns toolCalls=null,
hasCalls is false, so finish_reason is "stop", message.tool_calls is never
set, and message.content is the parser's returned content — which for text
with no <tool>/<tool_call> tag at all is the original string, unchanged
(parseToolCallsFromText's early-return branch). The test now asserts
exactly that shape, at the same executor level as the rest of the file's
tool_calls that make sense at that level as the rest of the file's tool_calls
Refs #9343
This commit is contained in:
diegosouzapw
2026-08-05 13:53:40 -03:00
parent e2b2f017fe
commit ed661f2126

View File

@@ -132,7 +132,9 @@ test("execute (non-stream) parses <tool> reply into OpenAI tool_calls", async ()
assert.equal(choice.finish_reason, "tool_calls"); assert.equal(choice.finish_reason, "tool_calls");
assert.equal(choice.message.tool_calls.length, 1); assert.equal(choice.message.tool_calls.length, 1);
assert.equal(choice.message.tool_calls[0].function.name, "get_weather"); assert.equal(choice.message.tool_calls[0].function.name, "get_weather");
assert.deepEqual(JSON.parse(choice.message.tool_calls[0].function.arguments), { city: "Paris" }); assert.deepEqual(JSON.parse(choice.message.tool_calls[0].function.arguments), {
city: "Paris",
});
assert.ok( assert.ok(
!String(choice.message.content || "").includes("<tool>"), !String(choice.message.content || "").includes("<tool>"),
"raw tool block stripped from content" "raw tool block stripped from content"
@@ -142,8 +144,9 @@ test("execute (non-stream) parses <tool> reply into OpenAI tool_calls", async ()
} }
}); });
test("execute (non-stream) parses bare JSON reply into OpenAI tool_calls", async () => { test("execute (non-stream) does NOT promote bare JSON reply to tool_calls (#9343)", async () => {
const mock = installMock('{"name":"getWeather","arguments":{"city":"Paris"}}'); const bareJson = '{"name":"getWeather","arguments":{"city":"Paris"}}';
const mock = installMock(bareJson);
try { try {
const executor = new DeepSeekWebExecutor(); const executor = new DeepSeekWebExecutor();
const result = await executor.execute({ const result = await executor.execute({
@@ -156,11 +159,17 @@ test("execute (non-stream) parses bare JSON reply into OpenAI tool_calls", async
assert.ok(result.response.ok); assert.ok(result.response.ok);
const json = JSON.parse(await result.response.text()); const json = JSON.parse(await result.response.text());
const choice = json.choices[0]; const choice = json.choices[0];
assert.equal(choice.finish_reason, "tool_calls"); assert.equal(
assert.equal(choice.message.tool_calls.length, 1); choice.finish_reason,
assert.equal(choice.message.tool_calls[0].function.name, "get_weather"); "stop",
assert.deepEqual(JSON.parse(choice.message.tool_calls[0].function.arguments), { city: "Paris" }); "bare JSON with no <tool> envelope must not be promoted to a tool call"
assert.equal(choice.message.content, null, "bare JSON tool call is stripped from content"); );
assert.ok(!choice.message.tool_calls, "no tool_calls on a bare JSON reply (#9343)");
assert.equal(
choice.message.content,
bareJson,
"bare JSON must be preserved verbatim as content, not stripped or promoted"
);
} finally { } finally {
mock.restore(); mock.restore();
} }