mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-15 19:21:08 +00:00
feat(memory-wiki): surface imported source provenance
This commit is contained in:
@@ -260,7 +260,7 @@ export async function runWikiSearch(params: {
|
||||
: results
|
||||
.map(
|
||||
(result, index) =>
|
||||
`${index + 1}. ${result.title} (${result.corpus}/${result.kind})\nPath: ${result.path}${typeof result.startLine === "number" && typeof result.endLine === "number" ? `\nLines: ${result.startLine}-${result.endLine}` : ""}\nSnippet: ${result.snippet}`,
|
||||
`${index + 1}. ${result.title} (${result.corpus}/${result.kind})\nPath: ${result.path}${typeof result.startLine === "number" && typeof result.endLine === "number" ? `\nLines: ${result.startLine}-${result.endLine}` : ""}${result.provenanceLabel ? `\nProvenance: ${result.provenanceLabel}` : ""}\nSnippet: ${result.snippet}`,
|
||||
)
|
||||
.join("\n\n");
|
||||
writeOutput(summary, params.stdout);
|
||||
|
||||
@@ -22,8 +22,20 @@ export type WikiPageSummary = {
|
||||
contradictions: string[];
|
||||
questions: string[];
|
||||
confidence?: number;
|
||||
sourceType?: string;
|
||||
provenanceMode?: string;
|
||||
sourcePath?: string;
|
||||
bridgeRelativePath?: string;
|
||||
bridgeWorkspaceDir?: string;
|
||||
unsafeLocalConfiguredPath?: string;
|
||||
unsafeLocalRelativePath?: string;
|
||||
updatedAt?: string;
|
||||
};
|
||||
|
||||
function normalizeOptionalString(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
const FRONTMATTER_PATTERN = /^---\n([\s\S]*?)\n---\n?/;
|
||||
const OBSIDIAN_LINK_PATTERN = /\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/g;
|
||||
|
||||
@@ -156,14 +168,8 @@ export function toWikiPageSummary(params: {
|
||||
relativePath: params.relativePath.split(path.sep).join("/"),
|
||||
kind,
|
||||
title,
|
||||
id:
|
||||
typeof parsed.frontmatter.id === "string" && parsed.frontmatter.id.trim()
|
||||
? parsed.frontmatter.id.trim()
|
||||
: undefined,
|
||||
pageType:
|
||||
typeof parsed.frontmatter.pageType === "string" && parsed.frontmatter.pageType.trim()
|
||||
? parsed.frontmatter.pageType.trim()
|
||||
: undefined,
|
||||
id: normalizeOptionalString(parsed.frontmatter.id),
|
||||
pageType: normalizeOptionalString(parsed.frontmatter.pageType),
|
||||
sourceIds: normalizeSourceIds(parsed.frontmatter.sourceIds),
|
||||
linkTargets: extractWikiLinks(params.raw),
|
||||
contradictions: normalizeStringList(parsed.frontmatter.contradictions),
|
||||
@@ -173,5 +179,15 @@ export function toWikiPageSummary(params: {
|
||||
Number.isFinite(parsed.frontmatter.confidence)
|
||||
? parsed.frontmatter.confidence
|
||||
: undefined,
|
||||
sourceType: normalizeOptionalString(parsed.frontmatter.sourceType),
|
||||
provenanceMode: normalizeOptionalString(parsed.frontmatter.provenanceMode),
|
||||
sourcePath: normalizeOptionalString(parsed.frontmatter.sourcePath),
|
||||
bridgeRelativePath: normalizeOptionalString(parsed.frontmatter.bridgeRelativePath),
|
||||
bridgeWorkspaceDir: normalizeOptionalString(parsed.frontmatter.bridgeWorkspaceDir),
|
||||
unsafeLocalConfiguredPath: normalizeOptionalString(
|
||||
parsed.frontmatter.unsafeLocalConfiguredPath,
|
||||
),
|
||||
unsafeLocalRelativePath: normalizeOptionalString(parsed.frontmatter.unsafeLocalRelativePath),
|
||||
updatedAt: normalizeOptionalString(parsed.frontmatter.updatedAt),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -88,6 +88,44 @@ describe("searchMemoryWiki", () => {
|
||||
expect(getActiveMemorySearchManagerMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("surfaces bridge provenance for imported source pages", async () => {
|
||||
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-wiki-query-"));
|
||||
tempDirs.push(rootDir);
|
||||
const config = resolveMemoryWikiConfig(
|
||||
{ vault: { path: rootDir } },
|
||||
{ homedir: "/Users/tester" },
|
||||
);
|
||||
await initializeMemoryWikiVault(config);
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "sources", "bridge-alpha.md"),
|
||||
renderWikiMarkdown({
|
||||
frontmatter: {
|
||||
pageType: "source",
|
||||
id: "source.bridge.alpha",
|
||||
title: "Bridge Alpha",
|
||||
sourceType: "memory-bridge",
|
||||
sourcePath: "/tmp/workspace/MEMORY.md",
|
||||
bridgeRelativePath: "MEMORY.md",
|
||||
bridgeWorkspaceDir: "/tmp/workspace",
|
||||
updatedAt: "2026-04-05T12:00:00.000Z",
|
||||
},
|
||||
body: "# Bridge Alpha\n\nalpha bridge body\n",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const results = await searchMemoryWiki({ config, query: "alpha" });
|
||||
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results[0]).toMatchObject({
|
||||
corpus: "wiki",
|
||||
sourceType: "memory-bridge",
|
||||
sourcePath: "/tmp/workspace/MEMORY.md",
|
||||
provenanceLabel: "bridge: MEMORY.md",
|
||||
updatedAt: "2026-04-05T12:00:00.000Z",
|
||||
});
|
||||
});
|
||||
|
||||
it("includes active memory results when shared search and all corpora are enabled", async () => {
|
||||
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-wiki-query-"));
|
||||
tempDirs.push(rootDir);
|
||||
@@ -212,6 +250,49 @@ describe("getMemoryWikiPage", () => {
|
||||
expect(result?.content).not.toContain("line three");
|
||||
});
|
||||
|
||||
it("returns provenance for imported wiki source pages", async () => {
|
||||
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-wiki-query-"));
|
||||
tempDirs.push(rootDir);
|
||||
const config = resolveMemoryWikiConfig(
|
||||
{ vault: { path: rootDir } },
|
||||
{ homedir: "/Users/tester" },
|
||||
);
|
||||
await initializeMemoryWikiVault(config);
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "sources", "unsafe-alpha.md"),
|
||||
renderWikiMarkdown({
|
||||
frontmatter: {
|
||||
pageType: "source",
|
||||
id: "source.unsafe.alpha",
|
||||
title: "Unsafe Alpha",
|
||||
sourceType: "memory-unsafe-local",
|
||||
provenanceMode: "unsafe-local",
|
||||
sourcePath: "/tmp/private/alpha.md",
|
||||
unsafeLocalConfiguredPath: "/tmp/private",
|
||||
unsafeLocalRelativePath: "alpha.md",
|
||||
updatedAt: "2026-04-05T13:00:00.000Z",
|
||||
},
|
||||
body: "# Unsafe Alpha\n\nsecret alpha\n",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const result = await getMemoryWikiPage({
|
||||
config,
|
||||
lookup: "sources/unsafe-alpha.md",
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
corpus: "wiki",
|
||||
path: "sources/unsafe-alpha.md",
|
||||
sourceType: "memory-unsafe-local",
|
||||
provenanceMode: "unsafe-local",
|
||||
sourcePath: "/tmp/private/alpha.md",
|
||||
provenanceLabel: "unsafe-local: alpha.md",
|
||||
updatedAt: "2026-04-05T13:00:00.000Z",
|
||||
});
|
||||
});
|
||||
|
||||
it("falls back to active memory reads when memory corpus is selected", async () => {
|
||||
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-wiki-query-"));
|
||||
tempDirs.push(rootDir);
|
||||
|
||||
@@ -22,6 +22,11 @@ export type WikiSearchResult = {
|
||||
endLine?: number;
|
||||
citation?: string;
|
||||
memorySource?: MemorySearchResult["source"];
|
||||
sourceType?: string;
|
||||
provenanceMode?: string;
|
||||
sourcePath?: string;
|
||||
provenanceLabel?: string;
|
||||
updatedAt?: string;
|
||||
};
|
||||
|
||||
export type WikiGetResult = {
|
||||
@@ -33,6 +38,11 @@ export type WikiGetResult = {
|
||||
fromLine: number;
|
||||
lineCount: number;
|
||||
id?: string;
|
||||
sourceType?: string;
|
||||
provenanceMode?: string;
|
||||
sourcePath?: string;
|
||||
provenanceLabel?: string;
|
||||
updatedAt?: string;
|
||||
};
|
||||
|
||||
export type QueryableWikiPage = WikiPageSummary & {
|
||||
@@ -164,6 +174,28 @@ function buildMemorySearchTitle(resultPath: string): string {
|
||||
return basename.length > 0 ? basename : resultPath;
|
||||
}
|
||||
|
||||
function buildWikiProvenanceLabel(
|
||||
page: Pick<
|
||||
WikiPageSummary,
|
||||
| "sourceType"
|
||||
| "provenanceMode"
|
||||
| "bridgeRelativePath"
|
||||
| "unsafeLocalRelativePath"
|
||||
| "relativePath"
|
||||
>,
|
||||
): string | undefined {
|
||||
if (page.sourceType === "memory-bridge-events") {
|
||||
return `bridge events: ${page.bridgeRelativePath ?? page.relativePath}`;
|
||||
}
|
||||
if (page.sourceType === "memory-bridge") {
|
||||
return `bridge: ${page.bridgeRelativePath ?? page.relativePath}`;
|
||||
}
|
||||
if (page.provenanceMode === "unsafe-local" || page.sourceType === "memory-unsafe-local") {
|
||||
return `unsafe-local: ${page.unsafeLocalRelativePath ?? page.relativePath}`;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function toWikiSearchResult(page: QueryableWikiPage, query: string): WikiSearchResult {
|
||||
return {
|
||||
corpus: "wiki",
|
||||
@@ -173,6 +205,11 @@ function toWikiSearchResult(page: QueryableWikiPage, query: string): WikiSearchR
|
||||
score: scorePage(page, query),
|
||||
snippet: buildSnippet(page.raw, query),
|
||||
...(page.id ? { id: page.id } : {}),
|
||||
...(page.sourceType ? { sourceType: page.sourceType } : {}),
|
||||
...(page.provenanceMode ? { provenanceMode: page.provenanceMode } : {}),
|
||||
...(page.sourcePath ? { sourcePath: page.sourcePath } : {}),
|
||||
...(buildWikiProvenanceLabel(page) ? { provenanceLabel: buildWikiProvenanceLabel(page) } : {}),
|
||||
...(page.updatedAt ? { updatedAt: page.updatedAt } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -269,6 +306,13 @@ export async function getMemoryWikiPage(params: {
|
||||
fromLine,
|
||||
lineCount,
|
||||
...(page.id ? { id: page.id } : {}),
|
||||
...(page.sourceType ? { sourceType: page.sourceType } : {}),
|
||||
...(page.provenanceMode ? { provenanceMode: page.provenanceMode } : {}),
|
||||
...(page.sourcePath ? { sourcePath: page.sourcePath } : {}),
|
||||
...(buildWikiProvenanceLabel(page)
|
||||
? { provenanceLabel: buildWikiProvenanceLabel(page) }
|
||||
: {}),
|
||||
...(page.updatedAt ? { updatedAt: page.updatedAt } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveMemoryWikiConfig } from "./config.js";
|
||||
import { renderWikiMarkdown } from "./markdown.js";
|
||||
import {
|
||||
buildMemoryWikiDoctorReport,
|
||||
renderMemoryWikiDoctor,
|
||||
@@ -28,6 +32,13 @@ describe("resolveMemoryWikiStatus", () => {
|
||||
"vault-missing",
|
||||
"obsidian-cli-missing",
|
||||
]);
|
||||
expect(status.sourceCounts).toEqual({
|
||||
native: 0,
|
||||
bridge: 0,
|
||||
bridgeEvents: 0,
|
||||
unsafeLocal: 0,
|
||||
other: 0,
|
||||
});
|
||||
});
|
||||
|
||||
it("warns when unsafe-local is selected without explicit private access", async () => {
|
||||
@@ -45,6 +56,83 @@ describe("resolveMemoryWikiStatus", () => {
|
||||
|
||||
expect(status.warnings.map((warning) => warning.code)).toContain("unsafe-local-disabled");
|
||||
});
|
||||
|
||||
it("counts source provenance from the vault", async () => {
|
||||
const rootDir = await fs.mkdtemp(path.join(os.tmpdir(), "memory-wiki-status-"));
|
||||
await fs.mkdir(path.join(rootDir, "sources"), { recursive: true });
|
||||
await fs.mkdir(path.join(rootDir, "entities"), { recursive: true });
|
||||
await fs.mkdir(path.join(rootDir, "concepts"), { recursive: true });
|
||||
await fs.mkdir(path.join(rootDir, "syntheses"), { recursive: true });
|
||||
await fs.mkdir(path.join(rootDir, "reports"), { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "sources", "native.md"),
|
||||
renderWikiMarkdown({
|
||||
frontmatter: { pageType: "source", id: "source.native", title: "Native Source" },
|
||||
body: "# Native Source\n",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "sources", "bridge.md"),
|
||||
renderWikiMarkdown({
|
||||
frontmatter: {
|
||||
pageType: "source",
|
||||
id: "source.bridge",
|
||||
title: "Bridge Source",
|
||||
sourceType: "memory-bridge",
|
||||
},
|
||||
body: "# Bridge Source\n",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "sources", "events.md"),
|
||||
renderWikiMarkdown({
|
||||
frontmatter: {
|
||||
pageType: "source",
|
||||
id: "source.events",
|
||||
title: "Event Source",
|
||||
sourceType: "memory-bridge-events",
|
||||
},
|
||||
body: "# Event Source\n",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(rootDir, "sources", "unsafe.md"),
|
||||
renderWikiMarkdown({
|
||||
frontmatter: {
|
||||
pageType: "source",
|
||||
id: "source.unsafe",
|
||||
title: "Unsafe Source",
|
||||
sourceType: "memory-unsafe-local",
|
||||
provenanceMode: "unsafe-local",
|
||||
},
|
||||
body: "# Unsafe Source\n",
|
||||
}),
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const config = resolveMemoryWikiConfig(
|
||||
{ vault: { path: rootDir } },
|
||||
{ homedir: "/Users/tester" },
|
||||
);
|
||||
const status = await resolveMemoryWikiStatus(config, {
|
||||
pathExists: async () => true,
|
||||
resolveCommand: async () => null,
|
||||
});
|
||||
|
||||
expect(status.pageCounts.source).toBe(4);
|
||||
expect(status.sourceCounts).toEqual({
|
||||
native: 1,
|
||||
bridge: 1,
|
||||
bridgeEvents: 1,
|
||||
unsafeLocal: 1,
|
||||
other: 0,
|
||||
});
|
||||
|
||||
await fs.rm(rootDir, { recursive: true, force: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("renderMemoryWikiStatus", () => {
|
||||
@@ -79,11 +167,21 @@ describe("renderMemoryWikiStatus", () => {
|
||||
synthesis: 0,
|
||||
report: 0,
|
||||
},
|
||||
sourceCounts: {
|
||||
native: 0,
|
||||
bridge: 0,
|
||||
bridgeEvents: 0,
|
||||
unsafeLocal: 0,
|
||||
other: 0,
|
||||
},
|
||||
warnings: [{ code: "vault-missing", message: "Wiki vault has not been initialized yet." }],
|
||||
});
|
||||
|
||||
expect(rendered).toContain("Wiki vault mode: isolated");
|
||||
expect(rendered).toContain("Pages: 0 sources, 0 entities, 0 concepts, 0 syntheses, 0 reports");
|
||||
expect(rendered).toContain(
|
||||
"Source provenance: 0 native, 0 bridge, 0 bridge-events, 0 unsafe-local, 0 other",
|
||||
);
|
||||
expect(rendered).toContain("Warnings:");
|
||||
expect(rendered).toContain("Wiki vault has not been initialized yet.");
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { ResolvedMemoryWikiConfig } from "./config.js";
|
||||
import { inferWikiPageKind, type WikiPageKind } from "./markdown.js";
|
||||
import { inferWikiPageKind, toWikiPageSummary, type WikiPageKind } from "./markdown.js";
|
||||
import { probeObsidianCli } from "./obsidian.js";
|
||||
|
||||
export type MemoryWikiStatusWarning = {
|
||||
@@ -32,6 +32,13 @@ export type MemoryWikiStatus = {
|
||||
pathCount: number;
|
||||
};
|
||||
pageCounts: Record<WikiPageKind, number>;
|
||||
sourceCounts: {
|
||||
native: number;
|
||||
bridge: number;
|
||||
bridgeEvents: number;
|
||||
unsafeLocal: number;
|
||||
other: number;
|
||||
};
|
||||
warnings: MemoryWikiStatusWarning[];
|
||||
};
|
||||
|
||||
@@ -61,14 +68,24 @@ async function pathExists(inputPath: string): Promise<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
async function collectPageCounts(vaultPath: string): Promise<Record<WikiPageKind, number>> {
|
||||
const counts: Record<WikiPageKind, number> = {
|
||||
async function collectVaultCounts(vaultPath: string): Promise<{
|
||||
pageCounts: Record<WikiPageKind, number>;
|
||||
sourceCounts: MemoryWikiStatus["sourceCounts"];
|
||||
}> {
|
||||
const pageCounts: Record<WikiPageKind, number> = {
|
||||
entity: 0,
|
||||
concept: 0,
|
||||
source: 0,
|
||||
synthesis: 0,
|
||||
report: 0,
|
||||
};
|
||||
const sourceCounts: MemoryWikiStatus["sourceCounts"] = {
|
||||
native: 0,
|
||||
bridge: 0,
|
||||
bridgeEvents: 0,
|
||||
unsafeLocal: 0,
|
||||
other: 0,
|
||||
};
|
||||
const dirs = ["entities", "concepts", "sources", "syntheses", "reports"] as const;
|
||||
for (const dir of dirs) {
|
||||
const entries = await fs
|
||||
@@ -80,11 +97,40 @@ async function collectPageCounts(vaultPath: string): Promise<Record<WikiPageKind
|
||||
}
|
||||
const kind = inferWikiPageKind(path.join(dir, entry.name));
|
||||
if (kind) {
|
||||
counts[kind] += 1;
|
||||
pageCounts[kind] += 1;
|
||||
}
|
||||
if (dir === "sources") {
|
||||
const absolutePath = path.join(vaultPath, dir, entry.name);
|
||||
const raw = await fs.readFile(absolutePath, "utf8").catch(() => null);
|
||||
if (!raw) {
|
||||
continue;
|
||||
}
|
||||
const page = toWikiPageSummary({
|
||||
absolutePath,
|
||||
relativePath: path.join(dir, entry.name),
|
||||
raw,
|
||||
});
|
||||
if (!page) {
|
||||
continue;
|
||||
}
|
||||
if (page.sourceType === "memory-bridge-events") {
|
||||
sourceCounts.bridgeEvents += 1;
|
||||
} else if (page.sourceType === "memory-bridge") {
|
||||
sourceCounts.bridge += 1;
|
||||
} else if (
|
||||
page.provenanceMode === "unsafe-local" ||
|
||||
page.sourceType === "memory-unsafe-local"
|
||||
) {
|
||||
sourceCounts.unsafeLocal += 1;
|
||||
} else if (!page.sourceType) {
|
||||
sourceCounts.native += 1;
|
||||
} else {
|
||||
sourceCounts.other += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return counts;
|
||||
return { pageCounts, sourceCounts };
|
||||
}
|
||||
|
||||
function buildWarnings(params: {
|
||||
@@ -153,14 +199,23 @@ export async function resolveMemoryWikiStatus(
|
||||
const exists = deps?.pathExists ?? pathExists;
|
||||
const vaultExists = await exists(config.vault.path);
|
||||
const obsidianProbe = await probeObsidianCli({ resolveCommand: deps?.resolveCommand });
|
||||
const pageCounts = vaultExists
|
||||
? await collectPageCounts(config.vault.path)
|
||||
const counts = vaultExists
|
||||
? await collectVaultCounts(config.vault.path)
|
||||
: {
|
||||
entity: 0,
|
||||
concept: 0,
|
||||
source: 0,
|
||||
synthesis: 0,
|
||||
report: 0,
|
||||
pageCounts: {
|
||||
entity: 0,
|
||||
concept: 0,
|
||||
source: 0,
|
||||
synthesis: 0,
|
||||
report: 0,
|
||||
},
|
||||
sourceCounts: {
|
||||
native: 0,
|
||||
bridge: 0,
|
||||
bridgeEvents: 0,
|
||||
unsafeLocal: 0,
|
||||
other: 0,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -179,7 +234,8 @@ export async function resolveMemoryWikiStatus(
|
||||
allowPrivateMemoryCoreAccess: config.unsafeLocal.allowPrivateMemoryCoreAccess,
|
||||
pathCount: config.unsafeLocal.paths.length,
|
||||
},
|
||||
pageCounts,
|
||||
pageCounts: counts.pageCounts,
|
||||
sourceCounts: counts.sourceCounts,
|
||||
warnings: buildWarnings({ config, vaultExists, obsidianCommand: obsidianProbe.command }),
|
||||
};
|
||||
}
|
||||
@@ -217,6 +273,7 @@ export function renderMemoryWikiStatus(status: MemoryWikiStatus): string {
|
||||
`Bridge: ${status.bridge.enabled ? "enabled" : "disabled"}`,
|
||||
`Unsafe local: ${status.unsafeLocal.allowPrivateMemoryCoreAccess ? `enabled (${status.unsafeLocal.pathCount} paths)` : "disabled"}`,
|
||||
`Pages: ${status.pageCounts.source} sources, ${status.pageCounts.entity} entities, ${status.pageCounts.concept} concepts, ${status.pageCounts.synthesis} syntheses, ${status.pageCounts.report} reports`,
|
||||
`Source provenance: ${status.sourceCounts.native} native, ${status.sourceCounts.bridge} bridge, ${status.sourceCounts.bridgeEvents} bridge-events, ${status.sourceCounts.unsafeLocal} unsafe-local, ${status.sourceCounts.other} other`,
|
||||
];
|
||||
|
||||
if (status.warnings.length > 0) {
|
||||
|
||||
@@ -92,7 +92,7 @@ export function createWikiSearchTool(
|
||||
: results
|
||||
.map(
|
||||
(result, index) =>
|
||||
`${index + 1}. ${result.title} (${result.corpus}/${result.kind})\nPath: ${result.path}${typeof result.startLine === "number" && typeof result.endLine === "number" ? `\nLines: ${result.startLine}-${result.endLine}` : ""}\nSnippet: ${result.snippet}`,
|
||||
`${index + 1}. ${result.title} (${result.corpus}/${result.kind})\nPath: ${result.path}${typeof result.startLine === "number" && typeof result.endLine === "number" ? `\nLines: ${result.startLine}-${result.endLine}` : ""}${result.provenanceLabel ? `\nProvenance: ${result.provenanceLabel}` : ""}\nSnippet: ${result.snippet}`,
|
||||
)
|
||||
.join("\n\n");
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user