chore: initial commit

This commit is contained in:
2026-10-23 18:35:44 +08:00
commit f6921b7b23
69 changed files with 12148 additions and 0 deletions
@@ -0,0 +1,101 @@
package protocol
import (
"bytes"
"context"
"strings"
"testing"
)
func TestAnthropicThinkingOutput(t *testing.T) {
for _, tool := range []bool{false, true} {
visible := `{"type":"text","text":"OK"}`
initial := `{"type":"text","text":""}`
delta := `{"type":"text_delta","text":"OK"}`
finish := "end_turn"
if tool {
visible = `{"type":"tool_use","id":"call_1","name":"weather","input":{}}`
initial = visible
delta = `{"type":"input_json_delta","partial_json":"{}"}`
finish = "tool_use"
}
hidden := `{"type":"thinking","thinking":"PRIVATE","signature":"SIGNATURE"}`
redacted := `{"type":"redacted_thinking","data":"CIPHER"}`
body := `{"id":"m","type":"message","role":"assistant","model":"m","content":[` + hidden + "," + redacted + "," + visible + `],"stop_reason":"` + finish + `","usage":{"input_tokens":9,"output_tokens":7}}`
events := []string{
`{"type":"message_start","message":{"id":"m","content":[],"usage":{"input_tokens":9,"output_tokens":0}}}`,
`{"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":"","signature":""}}`,
`{"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"PRIVATE"}}`,
`{"type":"content_block_delta","index":0,"delta":{"type":"signature_delta","signature":"SIGNATURE"}}`,
`{"type":"content_block_stop","index":0}`,
`{"type":"content_block_start","index":1,"content_block":` + redacted + "}",
`{"type":"content_block_stop","index":1}`,
`{"type":"content_block_start","index":2,"content_block":` + initial + "}",
`{"type":"content_block_delta","index":2,"delta":` + delta + "}",
`{"type":"content_block_stop","index":2}`,
`{"type":"message_delta","delta":{"stop_reason":"` + finish + `"},"usage":{"output_tokens":7}}`,
`{"type":"message_stop"}`,
}
src := reasoningSSE(events...)
for _, target := range []Kind{Chat, Responses, Anthropic} {
out, err := ConvertResponse(Anthropic, target, []byte(body))
if err != nil {
t.Fatal(err)
}
var dst bytes.Buffer
u, err := Stream(context.Background(), &dst, strings.NewReader(src), Anthropic, target, "m")
if err != nil {
t.Fatal(err)
}
if !u.Known || u.Input != 9 || u.Output != 7 {
t.Fatalf("usage %+v", u)
}
if target == Anthropic {
if string(out) != body || dst.String() != src {
t.Fatal("native bytes changed")
}
continue
}
for _, result := range []string{string(out), dst.String()} {
for _, secret := range []string{"PRIVATE", "SIGNATURE", "CIPHER", "thinking"} {
if strings.Contains(result, secret) {
t.Fatal("thinking leaked")
}
}
want := "OK"
if tool {
want = "weather"
}
if !strings.Contains(result, want) {
t.Fatal("lost visible output")
}
}
terminal := "[DONE]"
if target == Responses {
terminal = "response.completed"
}
if !strings.Contains(dst.String(), terminal) {
t.Fatal("no terminal")
}
}
for _, bad := range []string{
strings.Replace(src, `{"type":"content_block_stop","index":0}`, `{"type":"ping"}`, 1),
strings.Replace(src, `"type":"thinking_delta"`, `"type":"text_delta"`, 1),
strings.Replace(src, `"index":2,"content_block"`, `"index":0,"content_block"`, 1),
} {
var dst bytes.Buffer
if _, err := Stream(context.Background(), &dst, strings.NewReader(bad), Anthropic, Chat, "m"); err == nil {
t.Fatal("accepted invalid thinking lifecycle")
}
}
}
for _, block := range []object{
{"type": "thinking", "thinking": true, "signature": ""},
{"type": "thinking", "thinking": "", "signature": "", "unknown": true},
{"type": "redacted_thinking", "data": nil},
} {
if _, err := anthropicThinking(block); err == nil {
t.Fatal("accepted malformed thinking")
}
}
}