fix(deepseek): fall back to reasoning "搜索到 XX 个网页" panel for citations

When the standard search-results panel never opens, click the reasoning-chain
"搜索到 N 个网页" affordance to reveal the citation source list, and prefer the
revealed panel links over stale snapshot links so citations point at the right
URLs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 10:18:44 +08:00
parent 05aa982f76
commit 2fd6267632
2 changed files with 401 additions and 6 deletions
@@ -1,4 +1,48 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it, vi } from "vitest";
vi.mock("electron/main", () => ({
app: {
getPath: () => "/tmp/geo-rankly-deepseek-test",
getVersion: () => "0.0.0-test",
isPackaged: false,
on: vi.fn(),
whenReady: () => Promise.resolve(),
},
BrowserWindow: vi.fn(),
WebContentsView: vi.fn(),
ipcMain: {
handle: vi.fn(),
on: vi.fn(),
removeHandler: vi.fn(),
},
Menu: {
buildFromTemplate: vi.fn(() => ({ popup: vi.fn() })),
setApplicationMenu: vi.fn(),
},
Tray: vi.fn(),
nativeTheme: {
on: vi.fn(),
shouldUseDarkColors: false,
},
safeStorage: {
decryptString: vi.fn(),
encryptString: vi.fn(),
isEncryptionAvailable: () => false,
},
session: {
fromPartition: vi.fn(() => ({
cookies: {
get: vi.fn(),
remove: vi.fn(),
set: vi.fn(),
},
webRequest: {
onBeforeSendHeaders: vi.fn(),
onHeadersReceived: vi.fn(),
},
})),
},
}));
import { __deepseekTestUtils } from "./deepseek";
import { getMonitorAdapter } from "./index";
@@ -11,9 +55,11 @@ const {
dedupeSourceItems,
classifyDeepseekSources,
mergeDeepSeekRawSourceLinks,
resolveDeepSeekCitationPanelLinks,
isObservationComplete,
isDeepSeekToggleSelected,
isDeepSeekWebpagesTriggerText,
isDeepSeekReasoningSearchTriggerText,
} = __deepseekTestUtils;
describe("deepseek adapter helpers", () => {
@@ -67,6 +113,74 @@ describe("deepseek adapter helpers", () => {
expect(classified.searchResults[0]?.url).toBe("https://example.com/search");
});
it("uses revealed xx webpages panel links instead of stale snapshot links for citation sources", () => {
const citationPanelLinks = resolveDeepSeekCitationPanelLinks(
[
{
url: "https://stale.example/from-snapshot",
title: "Stale snapshot result",
text: "Wrong result from the page snapshot",
siteName: "Stale",
kind: "search",
},
],
[
{
url: "https://right.example/from-xx-webpages",
title: "Right side panel result",
text: "Correct result from DeepSeek search results",
siteName: "Right",
kind: "search",
},
],
);
const classified = classifyDeepseekSources({
inlineLinks: [
{
url: "https://inline.example/body-link",
title: "Inline body link",
text: "[1]",
siteName: "Inline",
kind: "inline",
},
],
sourcePanelLinks: [],
searchPanelLinks: citationPanelLinks,
});
expect(citationPanelLinks.map((item) => item.url)).toEqual([
"https://right.example/from-xx-webpages",
]);
expect(classified.citations.map((item) => item.url)).toEqual([
"https://right.example/from-xx-webpages",
]);
expect(classified.searchResults.map((item) => item.url)).toEqual([
"https://right.example/from-xx-webpages",
]);
expect(classified.inlineCitationCandidates.map((item) => item.url)).toEqual([
"https://inline.example/body-link",
]);
});
it("falls back to snapshot search links when the revealed xx webpages panel is unavailable", () => {
const citationPanelLinks = resolveDeepSeekCitationPanelLinks(
[
{
url: "https://snapshot.example/result",
title: "Snapshot result",
text: "Fallback result",
siteName: "Snapshot",
kind: "search",
},
],
[],
);
expect(citationPanelLinks.map((item) => item.url)).toEqual([
"https://snapshot.example/result",
]);
});
it("enriches numeric inline citations with source metadata from revealed search cards", () => {
const classified = classifyDeepseekSources({
inlineLinks: [
@@ -267,6 +381,12 @@ describe("deepseek adapter helpers", () => {
expect(isDeepSeekWebpagesTriggerText("搜索到 39 个网页")).toBe(false);
});
it("treats reasoning 搜索到 xx 个网页 as a separate citation-source fallback trigger", () => {
expect(isDeepSeekReasoningSearchTriggerText("搜索到 30 个网页")).toBe(true);
expect(isDeepSeekReasoningSearchTriggerText("57 个网页")).toBe(false);
expect(isDeepSeekReasoningSearchTriggerText("已阅读 57 个网页")).toBe(false);
});
it("normalizes DeepSeek model labels without mistaking search toggles for models", () => {
const snapshot = {
url: "https://chat.deepseek.com/",