fix: validate memory wiki numeric params

This commit is contained in:
Peter Steinberger
2026-05-28 19:27:47 -04:00
parent 2ba725ef48
commit 30de7874cf
3 changed files with 39 additions and 21 deletions

View File

@@ -468,6 +468,37 @@ describe("memory-wiki gateway methods", () => {
});
});
it.each([
["wiki.importRuns", { limit: 0 }, "limit must be a positive integer"],
[
"wiki.search",
{ query: "Teams Azure", maxResults: 1.5 },
"maxResults must be a positive integer",
],
["wiki.get", { lookup: "Teams Azure", fromLine: 1.5 }, "fromLine must be a positive integer"],
["wiki.get", { lookup: "Teams Azure", lineCount: 0 }, "lineCount must be a positive integer"],
])("rejects invalid positive integer gateway param for %s", async (method, params, message) => {
const { config } = await createVault({ prefix: "memory-wiki-gateway-" });
const { api, registerGatewayMethod } = createPluginApi();
registerMemoryWikiGatewayMethods({ api, config });
const handler = findGatewayHandler(registerGatewayMethod, method);
if (!handler) {
throw new Error(`${method} handler missing`);
}
const respond = vi.fn();
await handler({
params,
respond,
});
expect(readRespondError(respond)).toEqual({
code: "internal_error",
message,
});
});
it("forwards wiki.search mode and corpus options over the gateway", async () => {
const { config } = await createVault({ prefix: "memory-wiki-gateway-" });
const { api, registerGatewayMethod } = createPluginApi();

View File

@@ -1,5 +1,6 @@
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
import { resolveDefaultAgentId } from "openclaw/plugin-sdk/memory-host-core";
import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers";
import type { OpenClawConfig, OpenClawPluginApi } from "../api.js";
import { applyMemoryWikiMutation, normalizeMemoryWikiMutationInput } from "./apply.js";
import { compileMemoryWikiVault } from "./compile.js";
@@ -55,20 +56,6 @@ function readStringParam(
return undefined;
}
function readNumberParam(params: Record<string, unknown>, key: string): number | undefined {
const value = params[key];
if (typeof value === "number" && Number.isFinite(value)) {
return value;
}
if (typeof value === "string" && value.trim()) {
const parsed = Number(value);
if (Number.isFinite(parsed)) {
return parsed;
}
}
return undefined;
}
function readEnumParam<T extends string>(
params: Record<string, unknown>,
key: string,
@@ -135,7 +122,7 @@ export function registerMemoryWikiGatewayMethods(params: {
"wiki.importRuns",
async ({ params: requestParams, respond }) => {
try {
const limit = readNumberParam(requestParams, "limit");
const limit = readPositiveIntegerParam(requestParams, "limit");
respond(true, await listMemoryWikiImportRuns(config, limit !== undefined ? { limit } : {}));
} catch (error) {
respondError(respond, error);
@@ -287,7 +274,7 @@ export function registerMemoryWikiGatewayMethods(params: {
try {
await syncImportedSourcesIfNeeded(config, appConfig);
const query = readStringParam(requestParams, "query", { required: true });
const maxResults = readNumberParam(requestParams, "maxResults");
const maxResults = readPositiveIntegerParam(requestParams, "maxResults");
const searchBackend = readEnumParam(requestParams, "backend", WIKI_SEARCH_BACKENDS);
const searchCorpus = readEnumParam(requestParams, "corpus", WIKI_SEARCH_CORPORA);
const mode = readEnumParam(requestParams, "mode", WIKI_SEARCH_MODES);
@@ -337,8 +324,8 @@ export function registerMemoryWikiGatewayMethods(params: {
try {
await syncImportedSourcesIfNeeded(config, appConfig);
const lookup = readStringParam(requestParams, "lookup", { required: true });
const fromLine = readNumberParam(requestParams, "fromLine");
const lineCount = readNumberParam(requestParams, "lineCount");
const fromLine = readPositiveIntegerParam(requestParams, "fromLine");
const lineCount = readPositiveIntegerParam(requestParams, "lineCount");
const searchBackend = readEnumParam(requestParams, "backend", WIKI_SEARCH_BACKENDS);
const searchCorpus = readEnumParam(requestParams, "corpus", WIKI_SEARCH_CORPORA);
const agentId = resolveGatewayAgentId(requestParams, appConfig);

View File

@@ -36,7 +36,7 @@ const WikiSearchModeSchema = Type.Union(WIKI_SEARCH_MODES.map((value) => Type.Li
const WikiSearchSchema = Type.Object(
{
query: Type.String({ minLength: 1 }),
maxResults: Type.Optional(Type.Number({ minimum: 1 })),
maxResults: Type.Optional(Type.Integer({ minimum: 1 })),
backend: Type.Optional(WikiSearchBackendSchema),
corpus: Type.Optional(WikiSearchCorpusSchema),
mode: Type.Optional(WikiSearchModeSchema),
@@ -46,8 +46,8 @@ const WikiSearchSchema = Type.Object(
const WikiGetSchema = Type.Object(
{
lookup: Type.String({ minLength: 1 }),
fromLine: Type.Optional(Type.Number({ minimum: 1 })),
lineCount: Type.Optional(Type.Number({ minimum: 1 })),
fromLine: Type.Optional(Type.Integer({ minimum: 1 })),
lineCount: Type.Optional(Type.Integer({ minimum: 1 })),
backend: Type.Optional(WikiSearchBackendSchema),
corpus: Type.Optional(WikiSearchCorpusSchema),
},