chore(frontend): introduce prettier + eslint and prune unused code
- Add Prettier 3 with prettier-plugin-organize-imports (sorts/removes unused imports) - Add ESLint 10 flat config with typescript-eslint + eslint-plugin-vue + eslint-config-prettier - Add root scripts: format, format:check, lint, lint:fix - Reformat 257 files across admin-web, ops-web, desktop-client, packages - Remove unused locals/exports flagged by --noUnusedLocals/--noUnusedParameters - Fix duplicate localTabLabel key, surrogate-pair regex u-flag, NBSP literal in regex - Skip server/ (Go) and apps/browser-extension/ (deprecated per ADR) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { __yuanbaoTestUtils } from "./yuanbao";
|
||||
import { __yuanbaoTestUtils } from './yuanbao'
|
||||
|
||||
const {
|
||||
appendUniqueSourceItems,
|
||||
@@ -13,130 +13,143 @@ const {
|
||||
normalizeSourceUrl,
|
||||
parseYuanbaoCaptures,
|
||||
resolveCitationsFromMarkers,
|
||||
} = __yuanbaoTestUtils;
|
||||
} = __yuanbaoTestUtils
|
||||
|
||||
describe("yuanbao adapter helpers", () => {
|
||||
it("unwraps redirect URLs and reads Yuanbao document URL fields", () => {
|
||||
expect(normalizeSourceUrl("https://yuanbao.tencent.com/link?target=https%3A%2F%2Fexample.com%2Fa%23ref")).toBe(
|
||||
"https://example.com/a",
|
||||
);
|
||||
describe('yuanbao adapter helpers', () => {
|
||||
it('unwraps redirect URLs and reads Yuanbao document URL fields', () => {
|
||||
expect(
|
||||
normalizeSourceUrl(
|
||||
'https://yuanbao.tencent.com/link?target=https%3A%2F%2Fexample.com%2Fa%23ref',
|
||||
),
|
||||
).toBe('https://example.com/a')
|
||||
|
||||
expect(buildSourceItem({
|
||||
docUrl: "https://example.com/doc?from=yuanbao#source",
|
||||
title: "引用文章",
|
||||
siteName: "Example",
|
||||
})).toMatchObject({
|
||||
url: "https://example.com/doc?from=yuanbao",
|
||||
normalized_url: "https://example.com/doc?from=yuanbao",
|
||||
title: "引用文章",
|
||||
site_name: "Example",
|
||||
host: "example.com",
|
||||
});
|
||||
});
|
||||
expect(
|
||||
buildSourceItem({
|
||||
docUrl: 'https://example.com/doc?from=yuanbao#source',
|
||||
title: '引用文章',
|
||||
siteName: 'Example',
|
||||
}),
|
||||
).toMatchObject({
|
||||
url: 'https://example.com/doc?from=yuanbao',
|
||||
normalized_url: 'https://example.com/doc?from=yuanbao',
|
||||
title: '引用文章',
|
||||
site_name: 'Example',
|
||||
host: 'example.com',
|
||||
})
|
||||
})
|
||||
|
||||
it("rejects browser and build diagnostics as monitoring questions", () => {
|
||||
expect(extractQuestionText({ question_text: "合肥全屋定制推荐" })).toBe("合肥全屋定制推荐");
|
||||
expect(() => extractQuestionText({
|
||||
question_text:
|
||||
"The resource http://localhost:8000/static/js/runtime.c632b2fe.js was preloaded using link preload but not used within a few seconds from the window's load event.",
|
||||
})).toThrow("yuanbao_question_text_runtime_diagnostic");
|
||||
expect(() => extractQuestionText({
|
||||
question_text:
|
||||
"failed to solve: process \"/bin/sh -c go build\" did not complete successfully: exit code: 1",
|
||||
})).toThrow("yuanbao_question_text_runtime_diagnostic");
|
||||
});
|
||||
it('rejects browser and build diagnostics as monitoring questions', () => {
|
||||
expect(extractQuestionText({ question_text: '合肥全屋定制推荐' })).toBe('合肥全屋定制推荐')
|
||||
expect(() =>
|
||||
extractQuestionText({
|
||||
question_text:
|
||||
"The resource http://localhost:8000/static/js/runtime.c632b2fe.js was preloaded using link preload but not used within a few seconds from the window's load event.",
|
||||
}),
|
||||
).toThrow('yuanbao_question_text_runtime_diagnostic')
|
||||
expect(() =>
|
||||
extractQuestionText({
|
||||
question_text:
|
||||
'failed to solve: process "/bin/sh -c go build" did not complete successfully: exit code: 1',
|
||||
}),
|
||||
).toThrow('yuanbao_question_text_runtime_diagnostic')
|
||||
})
|
||||
|
||||
it("merges streaming answer fragments without duplicating a repeated prefix", () => {
|
||||
const first = "通过三轮搜索,我已经掌握了合肥全屋定制市场的高性价比品牌。一定要合同中的定标准确和责任。";
|
||||
const repeated = "通过三轮搜索,我已经掌握了合肥全屋定制市场的高性价比品牌。结合你的预算,我建议优先看本土老牌。";
|
||||
it('merges streaming answer fragments without duplicating a repeated prefix', () => {
|
||||
const first =
|
||||
'通过三轮搜索,我已经掌握了合肥全屋定制市场的高性价比品牌。一定要合同中的定标准确和责任。'
|
||||
const repeated =
|
||||
'通过三轮搜索,我已经掌握了合肥全屋定制市场的高性价比品牌。结合你的预算,我建议优先看本土老牌。'
|
||||
|
||||
expect(mergeText(first, repeated)).toBe(repeated);
|
||||
});
|
||||
expect(mergeText(first, repeated)).toBe(repeated)
|
||||
})
|
||||
|
||||
it("resolves citation markers against the best available source pool", () => {
|
||||
it('resolves citation markers against the best available source pool', () => {
|
||||
const sources = [
|
||||
{ url: "https://example.com/1", normalized_url: "https://example.com/1" },
|
||||
{ url: "https://example.com/2", normalized_url: "https://example.com/2" },
|
||||
{ url: "https://example.com/3", normalized_url: "https://example.com/3" },
|
||||
];
|
||||
{ url: 'https://example.com/1', normalized_url: 'https://example.com/1' },
|
||||
{ url: 'https://example.com/2', normalized_url: 'https://example.com/2' },
|
||||
{ url: 'https://example.com/3', normalized_url: 'https://example.com/3' },
|
||||
]
|
||||
|
||||
expect(extractCitationMarkerIndexes("正文 [citation:1] 和 [citation:3]")).toEqual([1, 3]);
|
||||
expect(resolveCitationsFromMarkers("正文 [citation:1] 和 [citation:3]", [[], sources]).map((item) => item.url)).toEqual([
|
||||
"https://example.com/1",
|
||||
"https://example.com/3",
|
||||
]);
|
||||
});
|
||||
expect(extractCitationMarkerIndexes('正文 [citation:1] 和 [citation:3]')).toEqual([1, 3])
|
||||
expect(
|
||||
resolveCitationsFromMarkers('正文 [citation:1] 和 [citation:3]', [[], sources]).map(
|
||||
(item) => item.url,
|
||||
),
|
||||
).toEqual(['https://example.com/1', 'https://example.com/3'])
|
||||
})
|
||||
|
||||
it("preserves indexed DOM citation slots even when URLs repeat", () => {
|
||||
it('preserves indexed DOM citation slots even when URLs repeat', () => {
|
||||
const domSources = buildOrderedDomSourceItems([
|
||||
{
|
||||
url: "https://example.com/repeated",
|
||||
title: "来源 1",
|
||||
url: 'https://example.com/repeated',
|
||||
title: '来源 1',
|
||||
text: null,
|
||||
siteName: "Example",
|
||||
siteName: 'Example',
|
||||
sourceIndex: 1,
|
||||
},
|
||||
{
|
||||
url: "https://example.com/repeated",
|
||||
title: "来源 2",
|
||||
url: 'https://example.com/repeated',
|
||||
title: '来源 2',
|
||||
text: null,
|
||||
siteName: "Example",
|
||||
siteName: 'Example',
|
||||
sourceIndex: 2,
|
||||
},
|
||||
{
|
||||
url: "https://example.com/third",
|
||||
title: "来源 3",
|
||||
url: 'https://example.com/third',
|
||||
title: '来源 3',
|
||||
text: null,
|
||||
siteName: "Example",
|
||||
siteName: 'Example',
|
||||
sourceIndex: 3,
|
||||
},
|
||||
]);
|
||||
])
|
||||
|
||||
expect(domSources).toHaveLength(3);
|
||||
expect(domSources.map((item) => item.title)).toEqual(["来源 1", "来源 2", "来源 3"]);
|
||||
expect(findUnresolvedCitationIndexes("正文 [citation:2] [citation:3]", domSources)).toEqual([]);
|
||||
});
|
||||
expect(domSources).toHaveLength(3)
|
||||
expect(domSources.map((item) => item.title)).toEqual(['来源 1', '来源 2', '来源 3'])
|
||||
expect(findUnresolvedCitationIndexes('正文 [citation:2] [citation:3]', domSources)).toEqual([])
|
||||
})
|
||||
|
||||
it("keeps primary DOM citation order when appending parsed extras", () => {
|
||||
it('keeps primary DOM citation order when appending parsed extras', () => {
|
||||
const primary = [
|
||||
{ url: "https://example.com/1", normalized_url: "https://example.com/1" },
|
||||
{ url: "https://example.com/2", normalized_url: "https://example.com/2" },
|
||||
];
|
||||
{ url: 'https://example.com/1', normalized_url: 'https://example.com/1' },
|
||||
{ url: 'https://example.com/2', normalized_url: 'https://example.com/2' },
|
||||
]
|
||||
const appended = appendUniqueSourceItems(primary, [
|
||||
{ url: "https://example.com/2", normalized_url: "https://example.com/2", title: "duplicate" },
|
||||
{ url: "https://example.com/3", normalized_url: "https://example.com/3" },
|
||||
]);
|
||||
{ url: 'https://example.com/2', normalized_url: 'https://example.com/2', title: 'duplicate' },
|
||||
{ url: 'https://example.com/3', normalized_url: 'https://example.com/3' },
|
||||
])
|
||||
|
||||
expect(appended.map((item) => item.url)).toEqual([
|
||||
"https://example.com/1",
|
||||
"https://example.com/2",
|
||||
"https://example.com/3",
|
||||
]);
|
||||
});
|
||||
'https://example.com/1',
|
||||
'https://example.com/2',
|
||||
'https://example.com/3',
|
||||
])
|
||||
})
|
||||
|
||||
it("does not report incomplete citations when the answer has no markers", () => {
|
||||
expect(findUnresolvedCitationIndexes("正文没有引用小图标", [])).toEqual([]);
|
||||
});
|
||||
it('does not report incomplete citations when the answer has no markers', () => {
|
||||
expect(findUnresolvedCitationIndexes('正文没有引用小图标', [])).toEqual([])
|
||||
})
|
||||
|
||||
it("collects source candidates from deep search thinking fields", () => {
|
||||
it('collects source candidates from deep search thinking fields', () => {
|
||||
const summary = parseYuanbaoCaptures([
|
||||
{
|
||||
url: "https://yuanbao.tencent.com/api/chat",
|
||||
url: 'https://yuanbao.tencent.com/api/chat',
|
||||
status: 200,
|
||||
contentType: "text/event-stream",
|
||||
contentType: 'text/event-stream',
|
||||
body: [
|
||||
"data: {\"type\":\"deepSearch\",\"contents\":[{\"type\":\"step\",\"webPages\":[{\"targetUrl\":\"https://example.com/a#ref\",\"title\":\"来源 A\",\"siteName\":\"Example\"}],\"references\":[{\"sourceUrl\":\"https://example.com/b\",\"title\":\"来源 B\"}]}]}",
|
||||
"data: {\"type\":\"text\",\"msg\":\"正文 [citation:1] [citation:2]\"}",
|
||||
].join("\n\n"),
|
||||
'data: {"type":"deepSearch","contents":[{"type":"step","webPages":[{"targetUrl":"https://example.com/a#ref","title":"来源 A","siteName":"Example"}],"references":[{"sourceUrl":"https://example.com/b","title":"来源 B"}]}]}',
|
||||
'data: {"type":"text","msg":"正文 [citation:1] [citation:2]"}',
|
||||
].join('\n\n'),
|
||||
},
|
||||
]);
|
||||
])
|
||||
|
||||
expect(summary.searchResults.map((item) => item.url)).toContain("https://example.com/a");
|
||||
expect(summary.citations.map((item) => item.url)).toContain("https://example.com/b");
|
||||
expect(resolveCitationsFromMarkers(summary.answer, [
|
||||
summary.citations,
|
||||
summary.searchResults,
|
||||
[...summary.citations, ...summary.searchResults],
|
||||
]).map((item) => item.url)).toEqual(["https://example.com/b", "https://example.com/a"]);
|
||||
});
|
||||
});
|
||||
expect(summary.searchResults.map((item) => item.url)).toContain('https://example.com/a')
|
||||
expect(summary.citations.map((item) => item.url)).toContain('https://example.com/b')
|
||||
expect(
|
||||
resolveCitationsFromMarkers(summary.answer, [
|
||||
summary.citations,
|
||||
summary.searchResults,
|
||||
[...summary.citations, ...summary.searchResults],
|
||||
]).map((item) => item.url),
|
||||
).toEqual(['https://example.com/b', 'https://example.com/a'])
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user