feat(monitoring): add DeepSeek monitoring end-to-end

- desktop: new DeepSeek page adapter and monitor registry
- desktop: extract generic AI auth helpers into shared module and
  skip binding when challenge signals are present
- admin-web: render DeepSeek HTML answers with inline citation anchors
  and surface reference-number badges on source cards
- server: fall back to inline_links/source_panel_links and read
  text/siteName fields when extracting DeepSeek citations

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 22:54:56 +08:00
parent f6889ecdee
commit f6e553dcc3
12 changed files with 2971 additions and 65 deletions
@@ -68,6 +68,30 @@ func TestBuildMonitoringRawPayloadQwenIncludesSearchResultsInCitationInputs(t *t
}
}
func TestBuildMonitoringRawPayloadDeepSeekIncludesSearchResultsInCitationInputs(t *testing.T) {
searchTitle := "搜索网页结果"
req := MonitoringTaskResultRequest{
Status: "succeeded",
SearchResults: []MonitoringSourceItem{
{
URL: "https://example.com/search",
Title: &searchTitle,
},
},
}
_, sourceInputs := buildMonitoringRawPayload("deepseek", req)
if len(sourceInputs) != 1 {
t.Fatalf("buildMonitoringRawPayload() sourceInputs len = %d, want 1", len(sourceInputs))
}
for _, item := range sourceInputs {
if item.URL != "https://example.com/search" {
t.Fatalf("buildMonitoringRawPayload() source url = %q, want search url", item.URL)
}
}
}
func TestExtractMonitoringInlineCitationsFromRawResponseKimi(t *testing.T) {
raw := []byte(`{
"inline_citation_candidates": [
@@ -100,3 +124,34 @@ func TestExtractMonitoringInlineCitationsFromRawResponseKimi(t *testing.T) {
t.Fatalf("extractMonitoringInlineCitationsFromRawResponse() second url = %q, want https://example.com/b", items[1].URL)
}
}
func TestExtractMonitoringInlineCitationsFromRawResponseDeepSeekFallsBackToInlineLinks(t *testing.T) {
raw := []byte(`{
"inline_links": [
{
"url": "https://example.com/a#cite-1",
"text": "-1",
"siteName": "示例站点"
},
{
"url": "https://example.com/b",
"title": "文章 B",
"siteName": "另一个站点"
}
]
}`)
items := extractMonitoringInlineCitationsFromRawResponse(raw, "deepseek")
if len(items) != 2 {
t.Fatalf("extractMonitoringInlineCitationsFromRawResponse() len = %d, want 2", len(items))
}
if items[0].URL != "https://example.com/a" {
t.Fatalf("extractMonitoringInlineCitationsFromRawResponse() first url = %q, want https://example.com/a", items[0].URL)
}
if items[0].SiteName == nil || *items[0].SiteName != "示例站点" {
t.Fatalf("extractMonitoringInlineCitationsFromRawResponse() first site = %v, want 示例站点", items[0].SiteName)
}
if items[1].Title == nil || *items[1].Title != "文章 B" {
t.Fatalf("extractMonitoringInlineCitationsFromRawResponse() second title = %v, want 文章 B", items[1].Title)
}
}