





















@@ -21,6 +21,55 @@ const CLAIMS_DIGEST_PATH = ".openclaw-wiki/cache/claims.jsonl";
2121const RELATED_BLOCK_PATTERN =
2222/<!-- openclaw:wiki:related:start -->[\s\S]*?<!-- openclaw:wiki:related:end -->/g;
2323const MARKDOWN_FRONTMATTER_PATTERN = /^\s*---\r?\n[\s\S]*?\r?\n---\r?\n?/;
24+const ROUTE_QUESTION_STOP_WORDS = new Set([
25+"a",
26+"about",
27+"am",
28+"an",
29+"are",
30+"ask",
31+"asking",
32+"be",
33+"been",
34+"being",
35+"can",
36+"could",
37+"did",
38+"do",
39+"does",
40+"for",
41+"help",
42+"how",
43+"i",
44+"in",
45+"is",
46+"know",
47+"knows",
48+"me",
49+"my",
50+"need",
51+"needs",
52+"of",
53+"on",
54+"or",
55+"our",
56+"question",
57+"questions",
58+"should",
59+"the",
60+"to",
61+"us",
62+"we",
63+"what",
64+"when",
65+"where",
66+"who",
67+"whom",
68+"whose",
69+"why",
70+"with",
71+"would",
72+]);
24732574export const WIKI_SEARCH_MODES = [
2675"auto",
@@ -309,6 +358,12 @@ function buildQueryTokens(queryLower: string): string[] {
309358];
310359}
311360361+function buildRouteQuestionTokens(queryLower: string): string[] {
362+const tokens = buildQueryTokens(queryLower);
363+const routedTokens = tokens.filter((token) => !ROUTE_QUESTION_STOP_WORDS.has(token));
364+return routedTokens.length > 0 ? routedTokens : tokens;
365+}
366+312367function lineMatchesQuery(lineLower: string, queryLower: string, queryTokens: string[]): boolean {
313368if (queryLower.length > 0 && lineLower.includes(queryLower)) {
314369return true;
@@ -469,6 +524,39 @@ function hasAnyQueryMatch(
469524return values.some((value) => hasQueryMatch(value, queryLower, queryTokens));
470525}
471526527+function buildPageRouteQuestionFields(page: QueryableWikiPage): string[] {
528+return [
529+page.personCard?.lane,
530+ ...(page.personCard?.askFor ?? []),
531+ ...(page.personCard?.avoidAskingFor ?? []),
532+ ...page.bestUsedFor,
533+ ...page.notEnoughFor,
534+ ...(page.personCard?.bestUsedFor ?? []),
535+ ...(page.personCard?.notEnoughFor ?? []),
536+ ...page.relationships.flatMap((relationship) => [
537+relationship.kind,
538+relationship.targetTitle,
539+relationship.note,
540+]),
541+].filter((value): value is string => Boolean(value));
542+}
543+544+function buildDigestRouteQuestionFields(page: QueryDigestPage): string[] {
545+return [
546+page.personCard?.lane,
547+ ...(page.personCard?.askFor ?? []),
548+ ...(page.personCard?.avoidAskingFor ?? []),
549+ ...(page.bestUsedFor ?? []),
550+ ...(page.notEnoughFor ?? []),
551+ ...(page.personCard?.bestUsedFor ?? []),
552+ ...(page.personCard?.notEnoughFor ?? []),
553+].filter((value): value is string => Boolean(value));
554+}
555+556+function hasRouteQuestionMatch(values: readonly string[], queryLower: string): boolean {
557+return hasAnyQueryMatch(values, queryLower, buildRouteQuestionTokens(queryLower));
558+}
559+472560function isPersonLikeSummary(
473561page: Pick<WikiPageSummary, "entityType" | "pageType" | "personCard">,
474562): boolean {
@@ -516,26 +604,7 @@ function scorePageSearchModeBoost(params: {
516604}
517605case "route-question": {
518606let score = isPersonLikeSummary(page) ? 14 : 0;
519-if (
520-hasAnyQueryMatch(
521-[
522-page.personCard?.lane,
523- ...(page.personCard?.askFor ?? []),
524- ...(page.personCard?.avoidAskingFor ?? []),
525- ...page.bestUsedFor,
526- ...page.notEnoughFor,
527- ...(page.personCard?.bestUsedFor ?? []),
528- ...(page.personCard?.notEnoughFor ?? []),
529- ...page.relationships.flatMap((relationship) => [
530-relationship.kind,
531-relationship.targetTitle,
532-relationship.note,
533-]),
534-],
535-queryLower,
536-queryTokens,
537-)
538-) {
607+if (hasRouteQuestionMatch(buildPageRouteQuestionFields(page), queryLower)) {
539608score += 32;
540609}
541610score += Math.min(8, page.relationships.length * 2);
@@ -606,21 +675,7 @@ function scoreDigestSearchModeBoost(params: {
606675}
607676case "route-question": {
608677let score = isPersonLikeSummary(page) ? 14 : 0;
609-if (
610-hasAnyQueryMatch(
611-[
612-page.personCard?.lane,
613- ...(page.personCard?.askFor ?? []),
614- ...(page.personCard?.avoidAskingFor ?? []),
615- ...(page.bestUsedFor ?? []),
616- ...(page.notEnoughFor ?? []),
617- ...(page.personCard?.bestUsedFor ?? []),
618- ...(page.personCard?.notEnoughFor ?? []),
619-],
620-queryLower,
621-queryTokens,
622-)
623-) {
678+if (hasRouteQuestionMatch(buildDigestRouteQuestionFields(page), queryLower)) {
624679score += 32;
625680}
626681score += Math.min(8, (page.relationshipCount ?? 0) * 2);
@@ -673,7 +728,13 @@ function buildDigestCandidatePaths(params: {
673728const metadataLower = normalizeLowercaseStringOrEmpty(
674729buildDigestPageSearchText(page, claims),
675730);
676-if (!metadataLower.includes(queryLower)) {
731+if (
732+!metadataLower.includes(queryLower) &&
733+!(
734+params.mode === "route-question" &&
735+hasRouteQuestionMatch(buildDigestRouteQuestionFields(page), queryLower)
736+)
737+) {
677738return { path: page.path, score: 0 };
678739}
679740let score =
@@ -779,7 +840,10 @@ function scorePage(page: QueryableWikiPage, query: string, mode: WikiSearchMode)
779840rawLower.includes(queryLower);
780841const hasAllTokens =
781842queryTokens.length > 0 && queryTokens.every((token) => combinedLower.includes(token));
782-if (!hasExactMatch && !hasAllTokens) {
843+const hasModeMatch =
844+mode === "route-question" &&
845+hasRouteQuestionMatch(buildPageRouteQuestionFields(page), queryLower);
846+if (!hasExactMatch && !hasAllTokens && !hasModeMatch) {
783847return 0;
784848}
785849此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。