




















@@ -44,6 +44,8 @@ const COMPILE_PAGE_GROUPS: Array<{ kind: WikiPageKind; dir: string; heading: str
4444];
4545const AGENT_DIGEST_PATH = ".openclaw-wiki/cache/agent-digest.json";
4646const CLAIMS_DIGEST_PATH = ".openclaw-wiki/cache/claims.jsonl";
47+const MAX_RELATED_PAGES_PER_SECTION = 12;
48+const MAX_SHARED_SOURCE_FANOUT = 24;
47494850type DashboardPageDefinition = {
4951id: string;
@@ -395,12 +397,33 @@ function renderWikiPageLinks(params: {
395397.join("\n");
396398}
397399400+function sharedSourceFanout(
401+page: WikiPageSummary,
402+allPages: WikiPageSummary[],
403+): Map<string, number> {
404+const sourceIds = new Set(page.sourceIds);
405+const counts = new Map<string, number>();
406+for (const candidate of allPages) {
407+if (candidate.relativePath === page.relativePath) {
408+continue;
409+}
410+for (const sourceId of candidate.sourceIds) {
411+if (!sourceIds.has(sourceId)) {
412+continue;
413+}
414+counts.set(sourceId, (counts.get(sourceId) ?? 0) + 1);
415+}
416+}
417+return counts;
418+}
419+398420function buildRelatedBlockBody(params: {
399421config: ResolvedMemoryWikiConfig;
400422page: WikiPageSummary;
401423allPages: WikiPageSummary[];
402424}): string {
403425const candidatePages = params.allPages.filter((candidate) => candidate.kind !== "report");
426+const sourceFanout = sharedSourceFanout(params.page, candidatePages);
404427const pagesById = new Map(
405428candidatePages.flatMap((candidate) =>
406429candidate.id ? [[candidate.id, candidate] as const] : [],
@@ -426,6 +449,10 @@ function buildRelatedBlockBody(params: {
426449);
427450}),
428451);
452+const backlinkPages =
453+backlinks.length <= MAX_SHARED_SOURCE_FANOUT
454+ ? backlinks.slice(0, MAX_RELATED_PAGES_PER_SECTION)
455+ : [];
429456const relatedPages = uniquePages(
430457candidatePages.filter((candidate) => {
431458if (candidate.relativePath === params.page.relativePath) {
@@ -434,15 +461,19 @@ function buildRelatedBlockBody(params: {
434461if (sourcePages.some((sourcePage) => sourcePage.relativePath === candidate.relativePath)) {
435462return false;
436463}
437-if (backlinks.some((backlink) => backlink.relativePath === candidate.relativePath)) {
464+if (backlinkPages.some((backlink) => backlink.relativePath === candidate.relativePath)) {
438465return false;
439466}
440467if (params.page.sourceIds.length === 0 || candidate.sourceIds.length === 0) {
441468return false;
442469}
443-return params.page.sourceIds.some((sourceId) => candidate.sourceIds.includes(sourceId));
470+return params.page.sourceIds.some(
471+(sourceId) =>
472+candidate.sourceIds.includes(sourceId) &&
473+(sourceFanout.get(sourceId) ?? 0) <= MAX_SHARED_SOURCE_FANOUT,
474+);
444475}),
445-);
476+).slice(0, MAX_RELATED_PAGES_PER_SECTION);
446477447478const sections: string[] = [];
448479if (sourcePages.length > 0) {
@@ -451,10 +482,10 @@ function buildRelatedBlockBody(params: {
451482renderWikiPageLinks({ config: params.config, pages: sourcePages }),
452483);
453484}
454-if (backlinks.length > 0) {
485+if (backlinkPages.length > 0) {
455486sections.push(
456487"### Referenced By",
457-renderWikiPageLinks({ config: params.config, pages: backlinks }),
488+renderWikiPageLinks({ config: params.config, pages: backlinkPages }),
458489);
459490}
460491if (relatedPages.length > 0) {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。