fix(ai): validated preserved web-search history blocks
Required non-empty server/result ids and a present result content field before narrowing gateway or stream blocks into replayable Anthropic web-search history. Malformed variants now remain flattened or ignored.
This commit is contained in:
@@ -89,8 +89,17 @@ export type WebSearchToolResultBlockParam = {
|
||||
export function isAnthropicWebSearchHistoryBlock(block: {
|
||||
type: string;
|
||||
name?: unknown;
|
||||
id?: unknown;
|
||||
tool_use_id?: unknown;
|
||||
content?: unknown;
|
||||
}): block is WebSearchServerToolUseBlockParam | WebSearchToolResultBlockParam {
|
||||
return block.type === "web_search_tool_result" || (block.type === "server_tool_use" && block.name === "web_search");
|
||||
if (block.type === "server_tool_use") {
|
||||
return block.name === "web_search" && typeof block.id === "string" && block.id.length > 0;
|
||||
}
|
||||
if (block.type === "web_search_tool_result") {
|
||||
return typeof block.tool_use_id === "string" && block.tool_use_id.length > 0 && Object.hasOwn(block, "content");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export type ThinkingBlockParam = {
|
||||
|
||||
@@ -344,6 +344,28 @@ describe("anthropic-messages parseRequest", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("flattens malformed web-search history blocks instead of preserving invalid replay state", () => {
|
||||
const parsed = parseRequest({
|
||||
model: "claude-opus-4-7",
|
||||
max_tokens: 8,
|
||||
messages: [
|
||||
{ role: "user", content: "weather?" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "server_tool_use", name: "web_search" },
|
||||
{ type: "web_search_tool_result", tool_use_id: "srvtoolu_1" },
|
||||
{ type: "web_search_tool_result", content: [] },
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
const assistant = parsed.context.messages.find(message => message.role === "assistant");
|
||||
expect(assistant?.content).toHaveLength(3);
|
||||
expect(assistant?.content.every(block => block.type === "text")).toBe(true);
|
||||
expect(assistant?.content.some(block => block.type === "anthropicServerTool")).toBe(false);
|
||||
});
|
||||
|
||||
it("does not retain a partial code-execution server-tool history", () => {
|
||||
const parsed = parseRequest({
|
||||
model: "claude-opus-4-7",
|
||||
|
||||
Reference in New Issue
Block a user