From 8f01aa224c42146f62b24dab7d96696285d3d049 Mon Sep 17 00:00:00 2001 From: songguoliang <957057673@qq.com> Date: Tue, 21 Apr 2026 10:52:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=AC=E6=AC=A1=E4=BF=AE=E5=A4=8D=E4=BA=86?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=9C=BA=E6=99=AF=E4=B8=8B=20citation=20?= =?UTF-8?q?=E6=A0=87=E7=AD=BE=E6=9C=AA=E5=AE=8C=E5=85=A8=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82=E6=A0=B9=E5=9B=A0=E6=98=AF?= =?UTF-8?q?=20citation=20=E9=A1=BA=E5=BA=8F=E6=94=B6=E9=9B=86=E9=98=B6?= =?UTF-8?q?=E6=AE=B5=E5=AF=B9=20URL=20=E5=81=9A=E4=BA=86=E5=8E=BB=E9=87=8D?= =?UTF-8?q?=EF=BC=8C=E5=AF=BC=E8=87=B4=E5=BD=93=E4=B8=8A=E6=B8=B8=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E9=87=8D=E5=A4=8D=E6=9D=A5=E6=BA=90=E4=B8=94=20cite?= =?UTF-8?q?=5Findex=20=E7=BC=BA=E5=A4=B1=E6=88=96=E4=B8=8D=E7=A8=B3?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=EF=BC=8C=E4=BD=8D=E7=BD=AE=E7=B4=A2=E5=BC=95?= =?UTF-8?q?=E8=A2=AB=E5=8E=8B=E7=BC=A9=EF=BC=8C=E9=83=A8=E5=88=86=20?= =?UTF-8?q?=EE=AA=88[citation:x]=20=E6=97=A0=E6=B3=95=E6=89=BE=E5=88=B0?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E9=93=BE=E6=8E=A5=E3=80=82=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=90=8E=E6=94=B9=E4=B8=BA=E4=BF=9D=E7=95=99=E4=B8=8A=E6=B8=B8?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E7=9A=84=E5=8E=9F=E5=A7=8B=E9=A1=BA=E5=BA=8F?= =?UTF-8?q?=EF=BC=88=E5=8C=85=E6=8B=AC=E9=87=8D=E5=A4=8D=20URL=EF=BC=89?= =?UTF-8?q?=EF=BC=8C=E4=BB=8E=E8=80=8C=E4=BF=9D=E8=AF=81=E6=8C=89=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E5=9B=9E=E5=A1=AB=20citation=20=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BC=9A=E4=B8=A2=E5=8F=B7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/sse/citation_links.go | 6 ------ internal/sse/consumer_edge_test.go | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/internal/sse/citation_links.go b/internal/sse/citation_links.go index 17a6dbb..ef744b4 100644 --- a/internal/sse/citation_links.go +++ b/internal/sse/citation_links.go @@ -7,14 +7,12 @@ import ( type citationLinkCollector struct { ordered []string - seen map[string]struct{} explicitRaw map[int]string hasZeroIdx bool } func newCitationLinkCollector() *citationLinkCollector { return &citationLinkCollector{ - seen: map[string]struct{}{}, explicitRaw: map[int]string{}, } } @@ -129,10 +127,6 @@ func (c *citationLinkCollector) captureURLAndIndex(m map[string]any) { } func (c *citationLinkCollector) addOrdered(url string) { - if _, ok := c.seen[url]; ok { - return - } - c.seen[url] = struct{}{} c.ordered = append(c.ordered, url) } diff --git a/internal/sse/consumer_edge_test.go b/internal/sse/consumer_edge_test.go index 9b49788..d720414 100644 --- a/internal/sse/consumer_edge_test.go +++ b/internal/sse/consumer_edge_test.go @@ -166,6 +166,25 @@ func TestCollectStreamExtractsCitationLinksForOneBasedIndices(t *testing.T) { } } +func TestCollectStreamExtractsCitationLinksWithRepeatedURLsAndNilIndices(t *testing.T) { + resp := makeHTTPResponse( + "data: {\"p\":\"response/fragments/-1/results\",\"v\":[{\"url\":\"https://example.com/a\",\"cite_index\":null},{\"url\":\"https://example.com/a\",\"cite_index\":null},{\"url\":\"https://example.com/b\",\"cite_index\":null}]}\n" + + "data: {\"p\":\"response/content\",\"v\":\"结论[citation:1][citation:2][citation:3]\"}\n" + + "data: [DONE]\n", + ) + result := CollectStream(resp, false, false) + + if got := result.CitationLinks[1]; got != "https://example.com/a" { + t.Fatalf("expected citation 1 link, got %q", got) + } + if got := result.CitationLinks[2]; got != "https://example.com/a" { + t.Fatalf("expected citation 2 link, got %q", got) + } + if got := result.CitationLinks[3]; got != "https://example.com/b" { + t.Fatalf("expected citation 3 link, got %q", got) + } +} + func TestCollectStreamMultipleThinkingChunks(t *testing.T) { resp := makeHTTPResponse( "data: {\"p\":\"response/thinking_content\",\"v\":\"part1\"}\n" +