fix(ts-oss/anthropic): find the text block in no-tools responses (#6506)

This commit is contained in:
Abhay Singh
2026-07-23 00:40:40 +05:30
committed by GitHub
parent 9caffeaa7b
commit 0e582adc6c
2 changed files with 40 additions and 5 deletions
+9 -5
View File
@@ -100,12 +100,16 @@ export class AnthropicLLM implements LLM {
return { content, role: "assistant", toolCalls };
}
const firstBlock = response.content[0];
if (firstBlock.type === "text") {
return firstBlock.text;
} else {
throw new Error("Unexpected response type from Anthropic API");
// Thinking-enabled responses put a thinking block before the text block,
// and a response can carry no text block at all, so find the text block
// like the tools branch above instead of indexing content[0]. Mirrors the
// Python provider (#6481).
for (const block of response.content) {
if (block.type === "text") {
return block.text;
}
}
return "";
}
async generateChat(messages: Message[]): Promise<LLMResponse> {
@@ -72,6 +72,37 @@ describe("AnthropicLLM (unit)", () => {
expect(callArgs.tool_choice).toBeUndefined();
});
// Regression: thinking-enabled models emit a thinking block before the text
// block. Indexing content[0] threw "Unexpected response type"; the text block
// must be found by type instead (TS parity with #6481).
it("returns the text block when a thinking block precedes it (no tools)", async () => {
mockCreate.mockResolvedValueOnce({
content: [
{ type: "thinking", thinking: "Let me reason about this." },
{ type: "text", text: '{"facts": ["fact1"]}' },
],
});
const llm = new AnthropicLLM({ apiKey: "test-key" });
const result = await llm.generateResponse([
{ role: "user", content: "Hello" },
]);
expect(result).toBe('{"facts": ["fact1"]}');
});
// A response carrying no text block at all must resolve to "" rather than throw.
it("returns an empty string when no text block is present (no tools)", async () => {
mockCreate.mockResolvedValueOnce({
content: [{ type: "thinking", thinking: "Thinking only." }],
});
const llm = new AnthropicLLM({ apiKey: "test-key" });
await expect(
llm.generateResponse([{ role: "user", content: "Hello" }]),
).resolves.toBe("");
});
// Bug #1 regression: bare string "auto" must NOT be sent; object form required
it("forwards tool_choice as { type: 'auto' } (not bare string) when tools are provided", async () => {
mockCreate.mockResolvedValueOnce({