mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 13:20:43 +00:00
refactor: share plugin config issue formatting
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { formatPluginConfigIssue } from "openclaw/plugin-sdk/extension-shared";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
||||
import type { z } from "openclaw/plugin-sdk/zod";
|
||||
import { AcpxPluginConfigSchema, DEFAULT_ACPX_TIMEOUT_SECONDS } from "./config-schema.js";
|
||||
import type {
|
||||
AcpxPluginConfig,
|
||||
@@ -112,26 +112,13 @@ type ParseResult =
|
||||
| { ok: true; value: AcpxPluginConfig | undefined }
|
||||
| { ok: false; message: string };
|
||||
|
||||
function formatAcpxConfigIssue(issue: z.ZodIssue | undefined): string {
|
||||
if (!issue) {
|
||||
return "invalid config";
|
||||
}
|
||||
if (issue.code === "unrecognized_keys" && issue.keys.length > 0) {
|
||||
return `unknown config key: ${issue.keys[0]}`;
|
||||
}
|
||||
if (issue.code === "invalid_type" && issue.path.length === 0) {
|
||||
return "expected config object";
|
||||
}
|
||||
return issue.message;
|
||||
}
|
||||
|
||||
function parseAcpxPluginConfig(value: unknown): ParseResult {
|
||||
if (value === undefined) {
|
||||
return { ok: true, value: undefined };
|
||||
}
|
||||
const parsed = AcpxPluginConfigSchema.safeParse(value);
|
||||
if (!parsed.success) {
|
||||
return { ok: false, message: formatAcpxConfigIssue(parsed.error.issues[0]) };
|
||||
return { ok: false, message: formatPluginConfigIssue(parsed.error.issues[0]) };
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { mapPluginConfigIssues } from "openclaw/plugin-sdk/extension-shared";
|
||||
import { buildPluginConfigSchema } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { z } from "openclaw/plugin-sdk/zod";
|
||||
import type { OpenClawPluginConfigSchema } from "../api.js";
|
||||
@@ -180,13 +181,7 @@ const diffsPluginConfigSchemaBase = buildPluginConfigSchema(DiffsPluginJsonSchem
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
issues: result.error.issues.map((issue) => ({
|
||||
path: issue.path.filter((segment): segment is string | number => {
|
||||
const kind = typeof segment;
|
||||
return kind === "string" || kind === "number";
|
||||
}),
|
||||
message: issue.message,
|
||||
})),
|
||||
issues: mapPluginConfigIssues(result.error.issues),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { mapPluginConfigIssues } from "openclaw/plugin-sdk/extension-shared";
|
||||
import { buildPluginConfigSchema, z, type OpenClawPluginConfigSchema } from "../api.js";
|
||||
|
||||
export const WIKI_VAULT_MODES = ["isolated", "bridge", "unsafe-local"] as const;
|
||||
@@ -174,13 +175,7 @@ const memoryWikiConfigSchemaBase = buildPluginConfigSchema(MemoryWikiConfigSourc
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
issues: result.error.issues.map((issue) => ({
|
||||
path: issue.path.filter((segment): segment is string | number => {
|
||||
const kind = typeof segment;
|
||||
return kind === "string" || kind === "number";
|
||||
}),
|
||||
message: issue.message,
|
||||
})),
|
||||
issues: mapPluginConfigIssues(result.error.issues),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import path from "node:path";
|
||||
import { buildPluginConfigSchema, type OpenClawPluginConfigSchema } from "openclaw/plugin-sdk/core";
|
||||
import {
|
||||
formatPluginConfigIssue,
|
||||
mapPluginConfigIssues,
|
||||
} from "openclaw/plugin-sdk/extension-shared";
|
||||
import { z } from "openclaw/plugin-sdk/zod";
|
||||
|
||||
export type OpenShellPluginConfig = {
|
||||
@@ -91,19 +95,6 @@ const OpenShellPluginConfigSchema = z.strictObject({
|
||||
.optional(),
|
||||
});
|
||||
|
||||
function formatOpenShellConfigIssue(issue: z.ZodIssue | undefined): string {
|
||||
if (!issue) {
|
||||
return "invalid config";
|
||||
}
|
||||
if (issue.code === "unrecognized_keys" && issue.keys.length > 0) {
|
||||
return `unknown config key: ${issue.keys[0]}`;
|
||||
}
|
||||
if (issue.code === "invalid_type" && issue.path.length === 0) {
|
||||
return "expected config object";
|
||||
}
|
||||
return issue.message;
|
||||
}
|
||||
|
||||
function isManagedOpenShellRemotePath(value: string): boolean {
|
||||
return OPEN_SHELL_MANAGED_REMOTE_ROOTS.some(
|
||||
(root) => value === root || value.startsWith(`${root}/`),
|
||||
@@ -141,13 +132,7 @@ export function createOpenShellPluginConfigSchema(): OpenClawPluginConfigSchema
|
||||
return {
|
||||
success: false,
|
||||
error: {
|
||||
issues: parsed.error.issues.map((issue) => ({
|
||||
path: issue.path.filter((segment): segment is string | number => {
|
||||
const kind = typeof segment;
|
||||
return kind === "string" || kind === "number";
|
||||
}),
|
||||
message: formatOpenShellConfigIssue(issue),
|
||||
})),
|
||||
issues: mapPluginConfigIssues(parsed.error.issues),
|
||||
},
|
||||
};
|
||||
},
|
||||
@@ -176,7 +161,7 @@ export function resolveOpenShellPluginConfig(value: unknown): ResolvedOpenShellP
|
||||
|
||||
const parsed = OpenShellPluginConfigSchema.safeParse(value);
|
||||
if (!parsed.success) {
|
||||
const message = formatOpenShellConfigIssue(parsed.error.issues[0]);
|
||||
const message = formatPluginConfigIssue(parsed.error.issues[0]);
|
||||
throw new Error(`Invalid openshell plugin config: ${message}`);
|
||||
}
|
||||
const cfg = parsed.data as OpenShellPluginConfig;
|
||||
|
||||
@@ -143,6 +143,54 @@ const DEFAULT_PACKAGE_JSON_VERSION_CANDIDATES = [
|
||||
|
||||
type PackageJsonRequire = (id: string) => unknown;
|
||||
|
||||
type PluginConfigIssuePathSegment = string | number;
|
||||
|
||||
type PluginConfigIssue = {
|
||||
path: PluginConfigIssuePathSegment[];
|
||||
message: string;
|
||||
};
|
||||
|
||||
type PluginConfigIssueMessageOptions = {
|
||||
invalidConfigMessage?: string;
|
||||
unknownKeyMessage?: (key: string) => string;
|
||||
rootInvalidTypeMessage?: string;
|
||||
};
|
||||
|
||||
export function formatPluginConfigIssue(
|
||||
issue: z.ZodIssue | undefined,
|
||||
options?: PluginConfigIssueMessageOptions,
|
||||
): string {
|
||||
if (!issue) {
|
||||
return options?.invalidConfigMessage ?? "invalid config";
|
||||
}
|
||||
if (issue.code === "unrecognized_keys" && issue.keys.length > 0) {
|
||||
return options?.unknownKeyMessage?.(issue.keys[0]) ?? `unknown config key: ${issue.keys[0]}`;
|
||||
}
|
||||
if (issue.code === "invalid_type" && issue.path.length === 0) {
|
||||
return options?.rootInvalidTypeMessage ?? "expected config object";
|
||||
}
|
||||
return issue.message;
|
||||
}
|
||||
|
||||
export function normalizePluginConfigIssuePath(
|
||||
path: readonly unknown[],
|
||||
): PluginConfigIssuePathSegment[] {
|
||||
return path.filter((segment): segment is PluginConfigIssuePathSegment => {
|
||||
const kind = typeof segment;
|
||||
return kind === "string" || kind === "number";
|
||||
});
|
||||
}
|
||||
|
||||
export function mapPluginConfigIssues(
|
||||
issues: readonly z.ZodIssue[],
|
||||
options?: PluginConfigIssueMessageOptions,
|
||||
): PluginConfigIssue[] {
|
||||
return issues.map((issue) => ({
|
||||
path: normalizePluginConfigIssuePath(issue.path),
|
||||
message: formatPluginConfigIssue(issue, options),
|
||||
}));
|
||||
}
|
||||
|
||||
export function readPluginPackageVersion(params: {
|
||||
require: PackageJsonRequire;
|
||||
candidates?: readonly string[];
|
||||
|
||||
Reference in New Issue
Block a user