mirror of
https://github.com/lukaszraczylo/mcp-captcharesolver.git
synced 2026-10-12 00:45:28 +00:00
Reasoning models prefix responses with <think>...</think> (or <thinking>...</thinking>) scratchpad that can itself contain a JSON-looking object. The brace-counting extractor would grab that inner object instead of the real answer. Strip think/thinking blocks via a package-level regexp before the balanced-object scan. Adds table cases covering both tag spellings while keeping the plain, prose-wrapped, and unbalanced cases intact.
49 lines
1.2 KiB
Go
49 lines
1.2 KiB
Go
package captcha
|
|
|
|
import "testing"
|
|
|
|
func TestExtractJSON(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
in string
|
|
want string
|
|
}{
|
|
{"plain", `{"text":"ab12"}`, `{"text":"ab12"}`},
|
|
{"prose wrapped", `Sure, here is the answer: {"text":"ab12"} hope it helps`, `{"text":"ab12"}`},
|
|
{
|
|
"markdown fenced",
|
|
"```json\n{\"tiles\":[1,2,3]}\n```",
|
|
`{"tiles":[1,2,3]}`,
|
|
},
|
|
{
|
|
"nested object",
|
|
`prefix {"a":{"b":1},"c":2} suffix`,
|
|
`{"a":{"b":1},"c":2}`,
|
|
},
|
|
{
|
|
"first balanced object wins",
|
|
`For example {"text":"EXAMPLE"} but the real one is {"text":"REAL"}`,
|
|
`{"text":"EXAMPLE"}`,
|
|
},
|
|
{"no brace", `no json here`, `no json here`},
|
|
{"unbalanced returns from start", `tail {"text":"x"`, `{"text":"x"`},
|
|
{
|
|
"think block stripped, real object wins",
|
|
"<think>reasoning with {\"tiles\":[9]}</think>\n{\"tiles\":[0,1,2],\"confidence\":0.9}",
|
|
`{"tiles":[0,1,2],"confidence":0.9}`,
|
|
},
|
|
{
|
|
"thinking block stripped",
|
|
`<thinking>let me reason {"tiles":[5]}</thinking>{"text":"ab12"}`,
|
|
`{"text":"ab12"}`,
|
|
},
|
|
}
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if got := extractJSON(tc.in); got != tc.want {
|
|
t.Fatalf("got %q want %q", got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|