





















@@ -5,6 +5,7 @@ import {
55jsonResult,
66readNumberParam,
77readStringParam,
8+type MemoryCorpusSearchResult,
89type OpenClawConfig,
910} from "openclaw/plugin-sdk/memory-core-host-runtime-core";
1011import type {
@@ -35,6 +36,50 @@ import {
3536searchMemoryCorpusSupplements,
3637} from "./tools.shared.js";
373839+type MemorySearchToolResult =
40+| (Record<string, unknown> & { corpus: "memory"; score: number; path: string })
41+| MemoryCorpusSearchResult;
42+43+function sortMemorySearchToolResults<T extends { score: number; path: string }>(results: T[]): T[] {
44+return results.toSorted((left, right) => {
45+if (left.score !== right.score) {
46+return right.score - left.score;
47+}
48+return left.path.localeCompare(right.path);
49+});
50+}
51+52+function mergeMemorySearchCorpusResults(params: {
53+memoryResults: MemorySearchToolResult[];
54+supplementResults: MemorySearchToolResult[];
55+maxResults: number;
56+balanceCorpora: boolean;
57+}): MemorySearchToolResult[] {
58+const memoryResults = sortMemorySearchToolResults(params.memoryResults);
59+const supplementResults = sortMemorySearchToolResults(params.supplementResults);
60+if (!params.balanceCorpora || memoryResults.length === 0 || supplementResults.length === 0) {
61+return sortMemorySearchToolResults([...memoryResults, ...supplementResults]).slice(
62+0,
63+params.maxResults,
64+);
65+}
66+67+const perCorpusCap = Math.ceil(params.maxResults / 2);
68+const selectedMemory = memoryResults.slice(0, perCorpusCap);
69+const selectedSupplements = supplementResults.slice(0, perCorpusCap);
70+const selected = [...selectedMemory, ...selectedSupplements];
71+if (selected.length < params.maxResults) {
72+selected.push(
73+ ...sortMemorySearchToolResults([
74+ ...memoryResults.slice(selectedMemory.length),
75+ ...supplementResults.slice(selectedSupplements.length),
76+]).slice(0, params.maxResults - selected.length),
77+);
78+}
79+80+return sortMemorySearchToolResults(selected).slice(0, params.maxResults);
81+}
82+3883function buildRecallKey(
3984result: Pick<MemorySearchResult, "source" | "path" | "startLine" | "endLine">,
4085): string {
@@ -319,14 +364,15 @@ export function createMemorySearchTool(options: {
319364corpus: requestedCorpus,
320365})
321366 : [];
322-const results = [...surfacedMemoryResults, ...supplementResults]
323-.toSorted((left, right) => {
324-if (left.score !== right.score) {
325-return right.score - left.score;
326-}
327-return left.path.localeCompare(right.path);
328-})
329-.slice(0, Math.max(1, maxResults ?? 10));
367+// Wiki and memory scores use incomparable scales, so corpus=all first
368+// balances candidate selection and then backfills any unused slots.
369+const effectiveMax = Math.max(1, maxResults ?? 10);
370+const results = mergeMemorySearchCorpusResults({
371+memoryResults: surfacedMemoryResults,
372+ supplementResults,
373+maxResults: effectiveMax,
374+balanceCorpora: requestedCorpus === "all",
375+});
330376return jsonResult({
331377 results,
332378 provider,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。