Skip to content

Commit 25f76ce

Browse files
authored
Revert "fix: capture extended thinking signatures for tool use continuations" (#10360)
1 parent c61dd7a commit 25f76ce

File tree

2 files changed

+10
-367
lines changed

2 files changed

+10
-367
lines changed

src/api/providers/__tests__/anthropic.spec.ts

Lines changed: 0 additions & 298 deletions
Original file line numberDiff line numberDiff line change
@@ -746,302 +746,4 @@ describe("AnthropicHandler", () => {
746746
})
747747
})
748748
})
749-
750-
describe("extended thinking with signature capture", () => {
751-
const systemPrompt = "You are a helpful assistant."
752-
const messages: Anthropic.Messages.MessageParam[] = [
753-
{
754-
role: "user",
755-
content: [{ type: "text" as const, text: "Think about this carefully" }],
756-
},
757-
]
758-
759-
it("should capture signature_delta and make it available via getThoughtSignature()", async () => {
760-
mockCreate.mockImplementationOnce(async () => ({
761-
async *[Symbol.asyncIterator]() {
762-
yield {
763-
type: "message_start",
764-
message: {
765-
usage: {
766-
input_tokens: 100,
767-
output_tokens: 50,
768-
},
769-
},
770-
}
771-
yield {
772-
type: "content_block_start",
773-
index: 0,
774-
content_block: {
775-
type: "thinking",
776-
thinking: "Let me think...",
777-
},
778-
}
779-
yield {
780-
type: "content_block_delta",
781-
index: 0,
782-
delta: {
783-
type: "thinking_delta",
784-
thinking: " about this carefully",
785-
},
786-
}
787-
yield {
788-
type: "content_block_delta",
789-
index: 0,
790-
delta: {
791-
type: "signature_delta",
792-
signature: "test_signature_123",
793-
},
794-
}
795-
yield {
796-
type: "content_block_stop",
797-
index: 0,
798-
}
799-
yield {
800-
type: "content_block_start",
801-
index: 1,
802-
content_block: {
803-
type: "text",
804-
text: "Here is my response",
805-
},
806-
}
807-
yield {
808-
type: "content_block_stop",
809-
index: 1,
810-
}
811-
},
812-
}))
813-
814-
const stream = handler.createMessage(systemPrompt, messages, {
815-
taskId: "test-task",
816-
})
817-
818-
const chunks: any[] = []
819-
for await (const chunk of stream) {
820-
chunks.push(chunk)
821-
}
822-
823-
// Verify reasoning chunks were emitted
824-
const reasoningChunks = chunks.filter((chunk) => chunk.type === "reasoning")
825-
expect(reasoningChunks).toHaveLength(2)
826-
expect(reasoningChunks[0].text).toBe("Let me think...")
827-
expect(reasoningChunks[1].text).toBe(" about this carefully")
828-
829-
// Verify thinking_complete chunk was emitted with signature
830-
const thinkingCompleteChunk = chunks.find((chunk) => chunk.type === "thinking_complete")
831-
expect(thinkingCompleteChunk).toBeDefined()
832-
expect(thinkingCompleteChunk.signature).toBe("test_signature_123")
833-
834-
// Verify getThoughtSignature() returns the captured signature
835-
expect(handler.getThoughtSignature()).toBe("test_signature_123")
836-
})
837-
838-
it("should reset signature for each new request", async () => {
839-
// First request with signature
840-
mockCreate.mockImplementationOnce(async () => ({
841-
async *[Symbol.asyncIterator]() {
842-
yield {
843-
type: "message_start",
844-
message: { usage: { input_tokens: 100, output_tokens: 50 } },
845-
}
846-
yield {
847-
type: "content_block_start",
848-
index: 0,
849-
content_block: { type: "thinking", thinking: "First thinking" },
850-
}
851-
yield {
852-
type: "content_block_delta",
853-
index: 0,
854-
delta: { type: "signature_delta", signature: "first_signature" },
855-
}
856-
yield { type: "content_block_stop", index: 0 }
857-
},
858-
}))
859-
860-
const stream1 = handler.createMessage(systemPrompt, messages, { taskId: "test-task-1" })
861-
for await (const _chunk of stream1) {
862-
// consume
863-
}
864-
expect(handler.getThoughtSignature()).toBe("first_signature")
865-
866-
// Second request without signature
867-
mockCreate.mockImplementationOnce(async () => ({
868-
async *[Symbol.asyncIterator]() {
869-
yield {
870-
type: "message_start",
871-
message: { usage: { input_tokens: 100, output_tokens: 50 } },
872-
}
873-
yield {
874-
type: "content_block_start",
875-
index: 0,
876-
content_block: { type: "text", text: "Just text, no thinking" },
877-
}
878-
yield { type: "content_block_stop", index: 0 }
879-
},
880-
}))
881-
882-
const stream2 = handler.createMessage(systemPrompt, messages, { taskId: "test-task-2" })
883-
for await (const _chunk of stream2) {
884-
// consume
885-
}
886-
887-
// Signature should be reset (undefined) for the new request
888-
expect(handler.getThoughtSignature()).toBeUndefined()
889-
})
890-
891-
it("should accumulate signature_delta chunks (incremental signature)", async () => {
892-
mockCreate.mockImplementationOnce(async () => ({
893-
async *[Symbol.asyncIterator]() {
894-
yield {
895-
type: "message_start",
896-
message: { usage: { input_tokens: 100, output_tokens: 50 } },
897-
}
898-
yield {
899-
type: "content_block_start",
900-
index: 0,
901-
content_block: { type: "thinking", thinking: "Thinking..." },
902-
}
903-
yield {
904-
type: "content_block_delta",
905-
index: 0,
906-
delta: { type: "signature_delta", signature: "sig_part1" },
907-
}
908-
yield {
909-
type: "content_block_delta",
910-
index: 0,
911-
delta: { type: "signature_delta", signature: "_part2" },
912-
}
913-
yield {
914-
type: "content_block_delta",
915-
index: 0,
916-
delta: { type: "signature_delta", signature: "_part3" },
917-
}
918-
yield { type: "content_block_stop", index: 0 }
919-
},
920-
}))
921-
922-
const stream = handler.createMessage(systemPrompt, messages, { taskId: "test-task" })
923-
924-
const chunks: any[] = []
925-
for await (const chunk of stream) {
926-
chunks.push(chunk)
927-
}
928-
929-
// Verify the accumulated signature
930-
expect(handler.getThoughtSignature()).toBe("sig_part1_part2_part3")
931-
932-
// Verify thinking_complete has the accumulated signature
933-
const thinkingCompleteChunk = chunks.find((chunk) => chunk.type === "thinking_complete")
934-
expect(thinkingCompleteChunk?.signature).toBe("sig_part1_part2_part3")
935-
})
936-
937-
it("should not emit thinking_complete if no signature is captured", async () => {
938-
mockCreate.mockImplementationOnce(async () => ({
939-
async *[Symbol.asyncIterator]() {
940-
yield {
941-
type: "message_start",
942-
message: { usage: { input_tokens: 100, output_tokens: 50 } },
943-
}
944-
yield {
945-
type: "content_block_start",
946-
index: 0,
947-
content_block: { type: "thinking", thinking: "Thinking without signature" },
948-
}
949-
yield {
950-
type: "content_block_delta",
951-
index: 0,
952-
delta: { type: "thinking_delta", thinking: "More thinking" },
953-
}
954-
// No signature_delta event
955-
yield { type: "content_block_stop", index: 0 }
956-
},
957-
}))
958-
959-
const stream = handler.createMessage(systemPrompt, messages, { taskId: "test-task" })
960-
961-
const chunks: any[] = []
962-
for await (const chunk of stream) {
963-
chunks.push(chunk)
964-
}
965-
966-
// Verify thinking_complete was NOT emitted (no signature)
967-
const thinkingCompleteChunk = chunks.find((chunk) => chunk.type === "thinking_complete")
968-
expect(thinkingCompleteChunk).toBeUndefined()
969-
970-
// Verify getThoughtSignature() returns undefined
971-
expect(handler.getThoughtSignature()).toBeUndefined()
972-
})
973-
974-
it("should handle interleaved thinking with tool use", async () => {
975-
mockCreate.mockImplementationOnce(async () => ({
976-
async *[Symbol.asyncIterator]() {
977-
yield {
978-
type: "message_start",
979-
message: { usage: { input_tokens: 100, output_tokens: 50 } },
980-
}
981-
// First: thinking block
982-
yield {
983-
type: "content_block_start",
984-
index: 0,
985-
content_block: { type: "thinking", thinking: "Let me think about what tool to use" },
986-
}
987-
yield {
988-
type: "content_block_delta",
989-
index: 0,
990-
delta: { type: "signature_delta", signature: "thinking_signature_abc" },
991-
}
992-
yield { type: "content_block_stop", index: 0 }
993-
// Second: tool use block
994-
yield {
995-
type: "content_block_start",
996-
index: 1,
997-
content_block: {
998-
type: "tool_use",
999-
id: "toolu_456",
1000-
name: "get_weather",
1001-
},
1002-
}
1003-
yield {
1004-
type: "content_block_delta",
1005-
index: 1,
1006-
delta: {
1007-
type: "input_json_delta",
1008-
partial_json: '{"location":"Paris"}',
1009-
},
1010-
}
1011-
yield { type: "content_block_stop", index: 1 }
1012-
},
1013-
}))
1014-
1015-
const stream = handler.createMessage(systemPrompt, messages, {
1016-
taskId: "test-task",
1017-
tools: [
1018-
{
1019-
type: "function" as const,
1020-
function: {
1021-
name: "get_weather",
1022-
description: "Get weather",
1023-
parameters: { type: "object", properties: { location: { type: "string" } } },
1024-
},
1025-
},
1026-
],
1027-
})
1028-
1029-
const chunks: any[] = []
1030-
for await (const chunk of stream) {
1031-
chunks.push(chunk)
1032-
}
1033-
1034-
// Verify thinking_complete was emitted for the thinking block
1035-
const thinkingCompleteChunk = chunks.find((chunk) => chunk.type === "thinking_complete")
1036-
expect(thinkingCompleteChunk).toBeDefined()
1037-
expect(thinkingCompleteChunk.signature).toBe("thinking_signature_abc")
1038-
1039-
// Verify signature is available for tool use continuation
1040-
expect(handler.getThoughtSignature()).toBe("thinking_signature_abc")
1041-
1042-
// Verify tool_call_partial was also emitted
1043-
const toolChunks = chunks.filter((chunk) => chunk.type === "tool_call_partial")
1044-
expect(toolChunks.length).toBeGreaterThan(0)
1045-
})
1046-
})
1047749
})

0 commit comments

Comments
 (0)