191 lines
5.1 KiB
Go
191 lines
5.1 KiB
Go
/*
|
|
* Copyright 2025 CloudWeGo Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package claude
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestConcatAssistantGenTextExtensions(t *testing.T) {
|
|
t.Run("multiple extensions - concatenates all citations", func(t *testing.T) {
|
|
exts := []*AssistantGenTextExtension{
|
|
{
|
|
Citations: []*TextCitation{
|
|
{
|
|
Type: "char_location",
|
|
CharLocation: &CitationCharLocation{
|
|
CitedText: "citation 1",
|
|
DocumentIndex: 0,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Citations: []*TextCitation{
|
|
{
|
|
Type: "page_location",
|
|
PageLocation: &CitationPageLocation{
|
|
CitedText: "citation 2",
|
|
StartPageNumber: 1,
|
|
EndPageNumber: 2,
|
|
},
|
|
},
|
|
{
|
|
Type: "web_search_result_location",
|
|
WebSearchResultLocation: &CitationWebSearchResultLocation{
|
|
CitedText: "citation 3",
|
|
URL: "https://example.com",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Citations: []*TextCitation{
|
|
{
|
|
Type: "content_block_location",
|
|
ContentBlockLocation: &CitationContentBlockLocation{
|
|
CitedText: "citation 4",
|
|
StartBlockIndex: 0,
|
|
EndBlockIndex: 5,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
result, err := ConcatAssistantGenTextExtensions(exts)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, result.Citations, 4)
|
|
assert.Equal(t, "citation 1", result.Citations[0].CharLocation.CitedText)
|
|
assert.Equal(t, "citation 2", result.Citations[1].PageLocation.CitedText)
|
|
assert.Equal(t, "citation 3", result.Citations[2].WebSearchResultLocation.CitedText)
|
|
assert.Equal(t, "citation 4", result.Citations[3].ContentBlockLocation.CitedText)
|
|
})
|
|
|
|
t.Run("mixed empty and non-empty citations", func(t *testing.T) {
|
|
exts := []*AssistantGenTextExtension{
|
|
{Citations: nil},
|
|
{
|
|
Citations: []*TextCitation{
|
|
{
|
|
Type: "char_location",
|
|
CharLocation: &CitationCharLocation{
|
|
CitedText: "text1",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{Citations: []*TextCitation{}},
|
|
{
|
|
Citations: []*TextCitation{
|
|
{
|
|
Type: "page_location",
|
|
PageLocation: &CitationPageLocation{
|
|
CitedText: "text2",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
result, err := ConcatAssistantGenTextExtensions(exts)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, result.Citations, 2)
|
|
assert.Equal(t, "text1", result.Citations[0].CharLocation.CitedText)
|
|
assert.Equal(t, "text2", result.Citations[1].PageLocation.CitedText)
|
|
})
|
|
|
|
t.Run("streaming scenario - citations arrive in chunks", func(t *testing.T) {
|
|
// Simulates streaming where citations arrive progressively
|
|
exts := []*AssistantGenTextExtension{
|
|
{
|
|
Citations: []*TextCitation{
|
|
{Type: "char_location", CharLocation: &CitationCharLocation{CitedText: "chunk1"}},
|
|
},
|
|
},
|
|
{
|
|
Citations: []*TextCitation{
|
|
{Type: "char_location", CharLocation: &CitationCharLocation{CitedText: "chunk2"}},
|
|
},
|
|
},
|
|
{
|
|
Citations: []*TextCitation{
|
|
{Type: "char_location", CharLocation: &CitationCharLocation{CitedText: "chunk3"}},
|
|
},
|
|
},
|
|
}
|
|
|
|
result, err := ConcatAssistantGenTextExtensions(exts)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, result.Citations, 3)
|
|
assert.Equal(t, "chunk1", result.Citations[0].CharLocation.CitedText)
|
|
assert.Equal(t, "chunk2", result.Citations[1].CharLocation.CitedText)
|
|
assert.Equal(t, "chunk3", result.Citations[2].CharLocation.CitedText)
|
|
})
|
|
}
|
|
|
|
func TestConcatResponseMetaExtensions(t *testing.T) {
|
|
t.Run("multiple extensions - takes last non-empty values", func(t *testing.T) {
|
|
exts := []*ResponseMetaExtension{
|
|
{
|
|
ID: "msg_1",
|
|
StopReason: "stop_1",
|
|
},
|
|
{
|
|
ID: "msg_2",
|
|
StopReason: "",
|
|
},
|
|
{
|
|
ID: "",
|
|
StopReason: "stop_3",
|
|
},
|
|
}
|
|
|
|
result, err := ConcatResponseMetaExtensions(exts)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "msg_2", result.ID) // Last non-empty ID
|
|
assert.Equal(t, "stop_3", result.StopReason) // Last non-empty StopReason
|
|
})
|
|
|
|
t.Run("all empty fields", func(t *testing.T) {
|
|
exts := []*ResponseMetaExtension{
|
|
{ID: "", StopReason: ""},
|
|
{ID: "", StopReason: ""},
|
|
}
|
|
|
|
result, err := ConcatResponseMetaExtensions(exts)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "", result.ID)
|
|
assert.Equal(t, "", result.StopReason)
|
|
})
|
|
|
|
t.Run("streaming scenario - ID in first chunk, StopReason in last", func(t *testing.T) {
|
|
exts := []*ResponseMetaExtension{
|
|
{ID: "msg_stream_123", StopReason: ""},
|
|
{ID: "", StopReason: ""},
|
|
{ID: "", StopReason: "end_turn"},
|
|
}
|
|
|
|
result, err := ConcatResponseMetaExtensions(exts)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, "msg_stream_123", result.ID)
|
|
assert.Equal(t, "end_turn", result.StopReason)
|
|
})
|
|
}
|