Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
110
backend/internal/translator/common/claude_messages_test.go
Normal file
110
backend/internal/translator/common/claude_messages_test.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func TestClaudeMessageAccumulatorGroupsAndOrdersAssistantParts(t *testing.T) {
|
||||
accumulator := NewClaudeMessageAccumulator(3)
|
||||
accumulator.Append([]byte(`{"role":"assistant","content":[{"type":"tool_use","id":"call_1","name":"first","input":{}}]}`))
|
||||
accumulator.Append([]byte(`{"role":"assistant","content":[{"type":"thinking","thinking":"reason"},{"type":"text","text":"answer"}]}`))
|
||||
accumulator.Append([]byte(`{"role":"assistant","content":[{"type":"tool_use","id":"call_2","name":"second","input":{}}]}`))
|
||||
|
||||
messages := accumulator.Messages()
|
||||
if len(messages) != 1 {
|
||||
t.Fatalf("message count = %d, want 1", len(messages))
|
||||
}
|
||||
content := gjson.GetBytes(messages[0], "content").Array()
|
||||
wantTypes := []string{"thinking", "text", "tool_use", "tool_use"}
|
||||
if len(content) != len(wantTypes) {
|
||||
t.Fatalf("content count = %d, want %d. Message: %s", len(content), len(wantTypes), string(messages[0]))
|
||||
}
|
||||
for i, wantType := range wantTypes {
|
||||
if got := content[i].Get("type").String(); got != wantType {
|
||||
t.Fatalf("content[%d].type = %q, want %q", i, got, wantType)
|
||||
}
|
||||
}
|
||||
if got := content[2].Get("id").String(); got != "call_1" {
|
||||
t.Fatalf("first tool_use id = %q, want call_1", got)
|
||||
}
|
||||
if got := content[3].Get("id").String(); got != "call_2" {
|
||||
t.Fatalf("second tool_use id = %q, want call_2", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeMessageAccumulatorPreservesUserOrderAndRoleBoundaries(t *testing.T) {
|
||||
accumulator := NewClaudeMessageAccumulator(3)
|
||||
accumulator.Append([]byte(`{"role":"user","content":[{"type":"tool_result","tool_use_id":"call_1","content":"ok"}]}`))
|
||||
accumulator.Append([]byte(`{"role":"user","content":[{"type":"text","text":"continue"}]}`))
|
||||
accumulator.Append([]byte(`{"role":"assistant","content":[{"type":"text","text":"done"}]}`))
|
||||
|
||||
messages := accumulator.Messages()
|
||||
if len(messages) != 2 {
|
||||
t.Fatalf("message count = %d, want 2", len(messages))
|
||||
}
|
||||
if got := gjson.GetBytes(messages[0], "role").String(); got != "user" {
|
||||
t.Fatalf("messages[0].role = %q, want user", got)
|
||||
}
|
||||
if got := gjson.GetBytes(messages[0], "content.0.type").String(); got != "tool_result" {
|
||||
t.Fatalf("first user block type = %q, want tool_result", got)
|
||||
}
|
||||
if got := gjson.GetBytes(messages[0], "content.1.text").String(); got != "continue" {
|
||||
t.Fatalf("second user block text = %q, want continue", got)
|
||||
}
|
||||
if got := gjson.GetBytes(messages[1], "role").String(); got != "assistant" {
|
||||
t.Fatalf("messages[1].role = %q, want assistant", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeMessageAccumulatorSkipsEmptyMessagesWithoutBreakingTurn(t *testing.T) {
|
||||
accumulator := NewClaudeMessageAccumulator(3)
|
||||
accumulator.Append([]byte(`{"role":"assistant","content":[{"type":"text","text":"first"}]}`))
|
||||
accumulator.Append([]byte(`{"role":"user"}`))
|
||||
accumulator.Append([]byte(`{"role":"user","content":null}`))
|
||||
accumulator.Append([]byte(`{"role":"user","content":""}`))
|
||||
accumulator.Append([]byte(`{"role":"user","content":[]}`))
|
||||
accumulator.Append([]byte(`{"role":"invalid","content":[{"type":"text","text":"ignored"}]}`))
|
||||
accumulator.Append([]byte(`{"role":"assistant","content":[{"type":"text","text":"second"}]}`))
|
||||
|
||||
messages := accumulator.Messages()
|
||||
if len(messages) != 1 {
|
||||
t.Fatalf("message count = %d, want 1", len(messages))
|
||||
}
|
||||
if got := gjson.GetBytes(messages[0], "content.#").Int(); got != 2 {
|
||||
t.Fatalf("assistant content count = %d, want 2. Message: %s", got, string(messages[0]))
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeMessageAccumulatorFlushPreservesExplicitBoundary(t *testing.T) {
|
||||
accumulator := NewClaudeMessageAccumulator(2)
|
||||
accumulator.Append([]byte(`{"role":"user","content":"system reminder"}`))
|
||||
accumulator.Flush()
|
||||
accumulator.Append([]byte(`{"role":"user","content":[{"type":"text","text":"question"}]}`))
|
||||
|
||||
messages := accumulator.Messages()
|
||||
if len(messages) != 2 {
|
||||
t.Fatalf("message count = %d, want 2", len(messages))
|
||||
}
|
||||
if got := gjson.GetBytes(messages[0], "content.0.text").String(); got != "system reminder" {
|
||||
t.Fatalf("first message text = %q, want system reminder", got)
|
||||
}
|
||||
if got := gjson.GetBytes(messages[1], "content.0.text").String(); got != "question" {
|
||||
t.Fatalf("second message text = %q, want question", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClaudeMessageAccumulatorPreservesBlockCacheControl(t *testing.T) {
|
||||
accumulator := NewClaudeMessageAccumulator(2)
|
||||
accumulator.Append([]byte(`{"role":"user","content":[{"type":"text","text":"cached","cache_control":{"type":"ephemeral"}}]}`))
|
||||
accumulator.Append([]byte(`{"role":"user","content":[{"type":"text","text":"fresh"}]}`))
|
||||
|
||||
messages := accumulator.Messages()
|
||||
if got := gjson.GetBytes(messages[0], "content.0.cache_control.type").String(); got != "ephemeral" {
|
||||
t.Fatalf("cache_control.type = %q, want ephemeral", got)
|
||||
}
|
||||
if gjson.GetBytes(messages[0], "content.1.cache_control").Exists() {
|
||||
t.Fatalf("second block should not have cache_control: %s", string(messages[0]))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue