feat(memory-wiki): add wiki search and get surfaces

This commit is contained in:
Vincent Koc
2026-04-05 20:44:05 +01:00
parent 516a43f9f2
commit 82710f2add
7 changed files with 430 additions and 3 deletions

View File

@@ -4,6 +4,7 @@ import type { MemoryWikiPluginConfig, ResolvedMemoryWikiConfig } from "./config.
import { resolveMemoryWikiConfig } from "./config.js";
import { ingestMemoryWikiSource } from "./ingest.js";
import { lintMemoryWikiVault } from "./lint.js";
import { getMemoryWikiPage, searchMemoryWiki } from "./query.js";
import { renderMemoryWikiStatus, resolveMemoryWikiStatus } from "./status.js";
import { initializeMemoryWikiVault } from "./vault.js";
@@ -28,6 +29,17 @@ type WikiIngestCommandOptions = {
title?: string;
};
type WikiSearchCommandOptions = {
json?: boolean;
maxResults?: number;
};
type WikiGetCommandOptions = {
json?: boolean;
from?: number;
lines?: number;
};
function writeOutput(output: string, writer: Pick<NodeJS.WriteStream, "write"> = process.stdout) {
writer.write(output.endsWith("\n") ? output : `${output}\n`);
}
@@ -103,6 +115,53 @@ export async function runWikiIngest(params: {
return result;
}
export async function runWikiSearch(params: {
config: ResolvedMemoryWikiConfig;
query: string;
maxResults?: number;
json?: boolean;
stdout?: Pick<NodeJS.WriteStream, "write">;
}) {
const results = await searchMemoryWiki({
config: params.config,
query: params.query,
maxResults: params.maxResults,
});
const summary = params.json
? JSON.stringify(results, null, 2)
: results.length === 0
? "No wiki results."
: results
.map(
(result, index) =>
`${index + 1}. ${result.title} (${result.kind})\nPath: ${result.path}\nSnippet: ${result.snippet}`,
)
.join("\n\n");
writeOutput(summary, params.stdout);
return results;
}
export async function runWikiGet(params: {
config: ResolvedMemoryWikiConfig;
lookup: string;
fromLine?: number;
lineCount?: number;
json?: boolean;
stdout?: Pick<NodeJS.WriteStream, "write">;
}) {
const result = await getMemoryWikiPage({
config: params.config,
lookup: params.lookup,
fromLine: params.fromLine,
lineCount: params.lineCount,
});
const summary = params.json
? JSON.stringify(result, null, 2)
: (result?.content ?? `Wiki page not found: ${params.lookup}`);
writeOutput(summary, params.stdout);
return result;
}
export function registerWikiCli(program: Command, pluginConfig?: MemoryWikiPluginConfig) {
const config = resolveMemoryWikiConfig(pluginConfig);
const wiki = program.command("wiki").description("Inspect and initialize the memory wiki vault");
@@ -148,4 +207,36 @@ export function registerWikiCli(program: Command, pluginConfig?: MemoryWikiPlugi
.action(async (inputPath: string, opts: WikiIngestCommandOptions) => {
await runWikiIngest({ config, inputPath, title: opts.title, json: opts.json });
});
wiki
.command("search")
.description("Search wiki pages")
.argument("<query>", "Search query")
.option("--max-results <n>", "Maximum results", (value: string) => Number(value))
.option("--json", "Print JSON")
.action(async (query: string, opts: WikiSearchCommandOptions) => {
await runWikiSearch({
config,
query,
maxResults: opts.maxResults,
json: opts.json,
});
});
wiki
.command("get")
.description("Read a wiki page by id or relative path")
.argument("<lookup>", "Relative path or page id")
.option("--from <n>", "Start line", (value: string) => Number(value))
.option("--lines <n>", "Number of lines", (value: string) => Number(value))
.option("--json", "Print JSON")
.action(async (lookup: string, opts: WikiGetCommandOptions) => {
await runWikiGet({
config,
lookup,
fromLine: opts.from,
lineCount: opts.lines,
json: opts.json,
});
});
}