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";
const OpenShellPluginConfigSchema = z.strictObject({
mode: z.enum(["mirror", "remote"], { error: "mode must be one of mirror, remote" }).optional(),
command: nonEmptyTrimmedString("command must be a non-empty string").optional(),
gateway: nonEmptyTrimmedString("gateway must be a non-empty string").optional(),
gatewayEndpoint: nonEmptyTrimmedString("gatewayEndpoint must be a non-empty string").optional(),
from: nonEmptyTrimmedString("from must be a non-empty string").optional(),
policy: nonEmptyTrimmedString("policy must be a non-empty string").optional(),
providers: z
.array(
z.string({ error: "providers must be an array of strings" }).trim().min(1, {
error: "providers must be an array of strings",
}),
{
error: "providers must be an array of strings",
},
)
.optional(),
gpu: z.boolean({ error: "gpu must be a boolean" }).optional(),
autoProviders: z.boolean({ error: "autoProviders must be a boolean" }).optional(),
remoteWorkspaceDir: nonEmptyTrimmedString( "remoteWorkspaceDir must be a non-empty string",
).optional(),
remoteAgentWorkspaceDir: nonEmptyTrimmedString( "remoteAgentWorkspaceDir must be a non-empty string",
).optional(),
timeoutSeconds: z
.number({ error: "timeoutSeconds must be a number >= 1" })
.min(1, { error: "timeoutSeconds must be a number >= 1" })
.optional(),
});
function isManagedOpenShellRemotePath(value: string): boolean { return OPEN_SHELL_MANAGED_REMOTE_ROOTS.some(
(root) => value === root || value.startsWith(`${root}/`),
);
}
export function normalizeOpenShellRemotePath(
value: string | undefined,
fallback: string,
fieldName = "remote path",
): string { const candidate = value ?? fallback; const normalized = path.posix.normalize(candidate.trim() || fallback); if (!normalized.startsWith("/")) { thrownew Error(`OpenShell ${fieldName} must be absolute: ${candidate}`);
} if (!isManagedOpenShellRemotePath(normalized)) { thrownew Error(
`OpenShell ${fieldName} must stay under ${OPEN_SHELL_MANAGED_REMOTE_ROOTS.join(" or ")}: ${candidate}`,
);
} return normalized;
}
export function resolveOpenShellPluginConfig(value: unknown): ResolvedOpenShellPluginConfig { if (value === undefined) { // The built-in defaults are managed OpenShell roots, so they do not need to // flow back through normalizeOpenShellRemotePath. return {
mode: DEFAULT_MODE,
command: DEFAULT_COMMAND,
gateway: undefined,
gatewayEndpoint: undefined,
from: DEFAULT_SOURCE,
policy: undefined,
providers: [],
gpu: false,
autoProviders: true,
remoteWorkspaceDir: DEFAULT_REMOTE_WORKSPACE_DIR,
remoteAgentWorkspaceDir: DEFAULT_REMOTE_AGENT_WORKSPACE_DIR,
timeoutMs: DEFAULT_TIMEOUT_MS,
};
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.