205 lines · 6.9 KB · Go
RawDownload
package executor import (	"testing" 	"github.com/tidwall/gjson") func TestNormalizeKimiToolMessageLinks_UsesCallIDFallback(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[{"id":"list_directory:1","type":"function","function":{"name":"list_directory","arguments":"{}"}}]},			{"role":"tool","call_id":"list_directory:1","content":"[]"}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.1.tool_call_id").String()	if got != "list_directory:1" {		t.Fatalf("messages.1.tool_call_id = %q, want %q", got, "list_directory:1")	}} func TestNormalizeKimiToolMessageLinks_InferSinglePendingID(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[{"id":"call_123","type":"function","function":{"name":"read_file","arguments":"{}"}}]},			{"role":"tool","content":"file-content"}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.1.tool_call_id").String()	if got != "call_123" {		t.Fatalf("messages.1.tool_call_id = %q, want %q", got, "call_123")	}} func TestNormalizeKimiToolMessageLinks_AmbiguousMissingIDIsNotInferred(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[				{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}},				{"id":"call_2","type":"function","function":{"name":"read_file","arguments":"{}"}}			]},			{"role":"tool","content":"result-without-id"}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	if gjson.GetBytes(out, "messages.1.tool_call_id").Exists() {		t.Fatalf("messages.1.tool_call_id should be absent for ambiguous case, got %q", gjson.GetBytes(out, "messages.1.tool_call_id").String())	}} func TestNormalizeKimiToolMessageLinks_PreservesExistingToolCallID(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}]},			{"role":"tool","tool_call_id":"call_1","call_id":"different-id","content":"result"}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.1.tool_call_id").String()	if got != "call_1" {		t.Fatalf("messages.1.tool_call_id = %q, want %q", got, "call_1")	}} func TestNormalizeKimiToolMessageLinks_InheritsPreviousReasoningForAssistantToolCalls(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","content":"plan","reasoning_content":"previous reasoning"},			{"role":"assistant","tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}]}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.1.reasoning_content").String()	if got != "previous reasoning" {		t.Fatalf("messages.1.reasoning_content = %q, want %q", got, "previous reasoning")	}} func TestNormalizeKimiToolMessageLinks_InsertsFallbackReasoningWhenMissing(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}]}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	reasoning := gjson.GetBytes(out, "messages.0.reasoning_content")	if !reasoning.Exists() {		t.Fatalf("messages.0.reasoning_content should exist")	}	if reasoning.String() != "[reasoning unavailable]" {		t.Fatalf("messages.0.reasoning_content = %q, want %q", reasoning.String(), "[reasoning unavailable]")	}} func TestNormalizeKimiToolMessageLinks_UsesContentAsReasoningFallback(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","content":[{"type":"text","text":"first line"},{"type":"text","text":"second line"}],"tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}]}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.0.reasoning_content").String()	if got != "first line\nsecond line" {		t.Fatalf("messages.0.reasoning_content = %q, want %q", got, "first line\nsecond line")	}} func TestNormalizeKimiToolMessageLinks_ReplacesEmptyReasoningContent(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","content":"assistant summary","tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}],"reasoning_content":""}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.0.reasoning_content").String()	if got != "assistant summary" {		t.Fatalf("messages.0.reasoning_content = %q, want %q", got, "assistant summary")	}} func TestNormalizeKimiToolMessageLinks_PreservesExistingAssistantReasoning(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}],"reasoning_content":"keep me"}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	got := gjson.GetBytes(out, "messages.0.reasoning_content").String()	if got != "keep me" {		t.Fatalf("messages.0.reasoning_content = %q, want %q", got, "keep me")	}} func TestNormalizeKimiToolMessageLinks_RepairsIDsAndReasoningTogether(t *testing.T) {	body := []byte(`{		"messages":[			{"role":"assistant","tool_calls":[{"id":"call_1","type":"function","function":{"name":"list_directory","arguments":"{}"}}],"reasoning_content":"r1"},			{"role":"tool","call_id":"call_1","content":"[]"},			{"role":"assistant","tool_calls":[{"id":"call_2","type":"function","function":{"name":"read_file","arguments":"{}"}}]},			{"role":"tool","call_id":"call_2","content":"file"}		]	}`) 	out, err := normalizeKimiToolMessageLinks(body)	if err != nil {		t.Fatalf("normalizeKimiToolMessageLinks() error = %v", err)	} 	if got := gjson.GetBytes(out, "messages.1.tool_call_id").String(); got != "call_1" {		t.Fatalf("messages.1.tool_call_id = %q, want %q", got, "call_1")	}	if got := gjson.GetBytes(out, "messages.3.tool_call_id").String(); got != "call_2" {		t.Fatalf("messages.3.tool_call_id = %q, want %q", got, "call_2")	}	if got := gjson.GetBytes(out, "messages.2.reasoning_content").String(); got != "r1" {		t.Fatalf("messages.2.reasoning_content = %q, want %q", got, "r1")	}}