refactor: remove plugin sdk facade generator

This commit is contained in:
Peter Steinberger 2026-04-05 09:23:42 +01:00
parent a4b767c89b
commit 8be017fae6
No known key found for this signature in database
40 changed files with 97 additions and 1341 deletions

View File

@ -1,2 +1,2 @@
cbffdf76d6a7254d8b2d3a601e1206d7b6c835bc44f170d4038bc711a35ef756 plugin-sdk-api-baseline.json
fe026bf3ba1e3b55f6c0b560d76940f3c301d8f593d6f0f6dcc4625745c76d31 plugin-sdk-api-baseline.jsonl
dbd41e5bf7f4f1179d7069fb16a5fe3035064194b12213665312d44f072d3917 plugin-sdk-api-baseline.json
715e95912a2415507d7da07b7f93573e5686246dea0b58ae0d065b51f3241996 plugin-sdk-api-baseline.jsonl

View File

@ -296,19 +296,19 @@ Current bundled provider examples:
</Accordion>
This table is intentionally the common migration subset, not the full SDK
surface. The generated full list of 200+ entrypoints lives in
surface. The full list of 200+ entrypoints lives in
`scripts/lib/plugin-sdk-entrypoints.json`.
That generated list still includes some bundled-plugin helper seams such as
That list still includes some bundled-plugin helper seams such as
`plugin-sdk/feishu`, `plugin-sdk/feishu-setup`, `plugin-sdk/zalo`,
`plugin-sdk/zalo-setup`, and `plugin-sdk/matrix*`. Those remain exported for
bundled-plugin maintenance and compatibility, but they are intentionally
omitted from the common migration table and are not the recommended target for
new plugin code.
The same rule applies to other generated bundled-helper families such as:
The same rule applies to other bundled-helper families such as:
- browser: `plugin-sdk/browser*`
- browser support helpers: `plugin-sdk/browser-config-support`, `plugin-sdk/browser-support`
- Matrix: `plugin-sdk/matrix*`
- LINE: `plugin-sdk/line*`
- IRC: `plugin-sdk/irc*`

View File

@ -262,9 +262,9 @@ explicitly promotes one as public.
</Accordion>
<Accordion title="Reserved bundled-helper subpaths">
| Family | Current generated subpaths | Intended use |
| Family | Current subpaths | Intended use |
| --- | --- | --- |
| Browser | `plugin-sdk/browser`, `plugin-sdk/browser-config-support`, `plugin-sdk/browser-support` | Bundled browser plugin maintenance and compatibility |
| Browser | `plugin-sdk/browser-config-support`, `plugin-sdk/browser-support` | Bundled browser plugin support helpers |
| Matrix | `plugin-sdk/matrix`, `plugin-sdk/matrix-helper`, `plugin-sdk/matrix-runtime-heavy`, `plugin-sdk/matrix-runtime-shared`, `plugin-sdk/matrix-runtime-surface`, `plugin-sdk/matrix-surface`, `plugin-sdk/matrix-thread-bindings` | Bundled Matrix helper/runtime surface |
| Line | `plugin-sdk/line`, `plugin-sdk/line-core`, `plugin-sdk/line-runtime`, `plugin-sdk/line-surface` | Bundled LINE helper/runtime surface |
| IRC | `plugin-sdk/irc`, `plugin-sdk/irc-surface` | Bundled IRC helper surface |

View File

@ -335,10 +335,6 @@
"types": "./dist/plugin-sdk/bluebubbles-policy.d.ts",
"default": "./dist/plugin-sdk/bluebubbles-policy.js"
},
"./plugin-sdk/browser": {
"types": "./dist/plugin-sdk/browser.d.ts",
"default": "./dist/plugin-sdk/browser.js"
},
"./plugin-sdk/browser-config-support": {
"types": "./dist/plugin-sdk/browser-config-support.d.ts",
"default": "./dist/plugin-sdk/browser-config-support.js"
@ -983,8 +979,6 @@
"plugin-sdk:api:check": "node --import tsx scripts/generate-plugin-sdk-api-baseline.ts --check",
"plugin-sdk:api:gen": "node --import tsx scripts/generate-plugin-sdk-api-baseline.ts --write",
"plugin-sdk:check-exports": "node scripts/sync-plugin-sdk-exports.mjs --check",
"plugin-sdk:facades:check": "node scripts/generate-plugin-sdk-facades.mjs --check",
"plugin-sdk:facades:gen": "node scripts/generate-plugin-sdk-facades.mjs --write",
"plugin-sdk:sync-exports": "node scripts/sync-plugin-sdk-exports.mjs",
"plugin-sdk:usage": "node --import tsx scripts/analyze-plugin-sdk-usage.ts",
"plugins:sync": "node --import tsx scripts/sync-plugin-versions.ts",
@ -995,7 +989,7 @@
"protocol:check": "pnpm protocol:gen && pnpm protocol:gen:swift && git diff --exit-code -- dist/protocol.schema.json apps/macos/Sources/OpenClawProtocol/GatewayModels.swift apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift",
"protocol:gen": "node --import tsx scripts/protocol-gen.ts",
"protocol:gen:swift": "node --import tsx scripts/protocol-gen-swift.ts",
"release:check": "pnpm check:base-config-schema && pnpm check:bundled-channel-config-metadata && pnpm config:docs:check && pnpm plugin-sdk:check-exports && pnpm plugin-sdk:facades:check && pnpm plugin-sdk:api:check && node --import tsx scripts/release-check.ts",
"release:check": "pnpm check:base-config-schema && pnpm check:bundled-channel-config-metadata && pnpm config:docs:check && pnpm plugin-sdk:check-exports && pnpm plugin-sdk:api:check && node --import tsx scripts/release-check.ts",
"release:openclaw:npm:check": "node --import tsx scripts/openclaw-npm-release-check.ts",
"release:openclaw:npm:verify-published": "node --import tsx scripts/openclaw-npm-postpublish-verify.ts",
"release:plugins:clawhub:check": "node --import tsx scripts/plugin-clawhub-release-check.ts",

View File

@ -11,7 +11,6 @@ import {
visitModuleSpecifiers,
writeLine,
} from "./lib/guard-inventory-utils.mjs";
import { GENERATED_PLUGIN_SDK_FACADES_SCRIPT } from "./lib/plugin-sdk-facades.mjs";
import {
collectTypeScriptFilesFromRoots,
resolveSourceRoots,
@ -42,9 +41,6 @@ function scanPluginSdkExtensionFacadeSmells(sourceFile, filePath) {
if (!relativeFile.startsWith("src/plugin-sdk/")) {
return [];
}
if (sourceFile.text.includes(`Generated by ${GENERATED_PLUGIN_SDK_FACADES_SCRIPT}`)) {
return [];
}
const entries = [];

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
/**
* Verifies that the root plugin-sdk runtime surface and generated facade types
* are present in the compiled dist output.
* Verifies that the root plugin-sdk runtime surface is present in the compiled
* dist output.
*
* Run after `pnpm build` to catch missing root exports or leaked repo-only type
* aliases before release.
@ -15,16 +15,6 @@ import { pluginSdkSubpaths } from "./lib/plugin-sdk-entries.mjs";
const __dirname = dirname(fileURLToPath(import.meta.url));
const distFile = resolve(__dirname, "..", "dist", "plugin-sdk", "index.js");
const generatedFacadeTypeMapDts = resolve(
__dirname,
"..",
"dist",
"plugin-sdk",
"src",
"generated",
"plugin-sdk-facade-type-map.generated.d.ts",
);
if (!existsSync(distFile)) {
console.error("ERROR: dist/plugin-sdk/index.js not found. Run `pnpm build` first.");
process.exit(1);
@ -91,21 +81,6 @@ for (const entry of requiredRuntimeShimEntries) {
}
}
if (!existsSync(generatedFacadeTypeMapDts)) {
console.error(
"MISSING GENERATED FACADE TYPE MAP DTS: dist/plugin-sdk/src/generated/plugin-sdk-facade-type-map.generated.d.ts",
);
missing += 1;
} else {
const facadeTypeMapContent = readFileSync(generatedFacadeTypeMapDts, "utf-8");
if (facadeTypeMapContent.includes("@openclaw/")) {
console.error(
"INVALID GENERATED FACADE TYPE MAP DTS: dist/plugin-sdk/src/generated/plugin-sdk-facade-type-map.generated.d.ts leaks @openclaw/* imports",
);
missing += 1;
}
}
if (missing > 0) {
console.error(
`\nERROR: ${missing} required plugin-sdk artifact(s) missing (named exports or subpath files).`,

View File

@ -1,95 +0,0 @@
#!/usr/bin/env node
import path from "node:path";
import { pathToFileURL } from "node:url";
import { formatGeneratedModule } from "./lib/format-generated-module.mjs";
import { writeGeneratedOutput } from "./lib/generated-output-utils.mjs";
import {
GENERATED_PLUGIN_SDK_FACADES,
GENERATED_PLUGIN_SDK_FACADES_LABEL,
GENERATED_PLUGIN_SDK_FACADE_TYPES_OUTPUT,
buildPluginSdkFacadeTypeMapModule,
buildPluginSdkFacadeModule,
} from "./lib/plugin-sdk-facades.mjs";
function parseArgs(argv) {
const check = argv.includes("--check");
const write = argv.includes("--write");
if (check === write) {
throw new Error("Use exactly one of --check or --write.");
}
return { check };
}
export function generatePluginSdkFacades(params) {
const results = [];
const typeMapOutputPath = GENERATED_PLUGIN_SDK_FACADE_TYPES_OUTPUT;
const typeMapNext = formatGeneratedModule(
buildPluginSdkFacadeTypeMapModule(GENERATED_PLUGIN_SDK_FACADES),
{
repoRoot: params.repoRoot,
outputPath: typeMapOutputPath,
errorLabel: `${GENERATED_PLUGIN_SDK_FACADES_LABEL}:type-map`,
},
);
results.push(
writeGeneratedOutput({
repoRoot: params.repoRoot,
outputPath: typeMapOutputPath,
next: typeMapNext,
check: params.check,
}),
);
for (const entry of GENERATED_PLUGIN_SDK_FACADES) {
const outputPath = `src/plugin-sdk/${entry.subpath}.ts`;
const next = formatGeneratedModule(
buildPluginSdkFacadeModule(entry, { repoRoot: params.repoRoot }),
{
repoRoot: params.repoRoot,
outputPath,
errorLabel: `${GENERATED_PLUGIN_SDK_FACADES_LABEL}:${entry.subpath}`,
},
);
results.push(
writeGeneratedOutput({
repoRoot: params.repoRoot,
outputPath,
next,
check: params.check,
}),
);
}
return results;
}
async function main(argv = process.argv.slice(2)) {
const { check } = parseArgs(argv);
const repoRoot = process.cwd();
const results = generatePluginSdkFacades({ repoRoot, check });
const changed = results.filter((entry) => entry.changed);
if (changed.length === 0) {
console.log(`[${GENERATED_PLUGIN_SDK_FACADES_LABEL}] up to date`);
return;
}
if (check) {
for (const result of changed) {
console.error(
`[${GENERATED_PLUGIN_SDK_FACADES_LABEL}] stale generated output at ${path.relative(repoRoot, result.outputPath)}`,
);
}
process.exitCode = 1;
return;
}
for (const result of changed) {
console.log(
`[${GENERATED_PLUGIN_SDK_FACADES_LABEL}] wrote ${path.relative(repoRoot, result.outputPath)}`,
);
}
}
if (import.meta.url === pathToFileURL(process.argv[1] ?? "").href) {
await main();
}

View File

@ -73,7 +73,6 @@
"allowlist-config-edit",
"bluebubbles",
"bluebubbles-policy",
"browser",
"browser-config-support",
"browser-support",
"boolean-param",

View File

@ -1,727 +0,0 @@
import fs from "node:fs";
import path from "node:path";
import ts from "typescript";
import { bundledPluginFile } from "./bundled-plugin-paths.mjs";
function pluginSource(dirName, artifactBasename = "api.js") {
return `@openclaw/${dirName}/${artifactBasename}`;
}
function runtimeApiSourcePath(dirName) {
return bundledPluginFile(dirName, "runtime-api.ts");
}
export const GENERATED_PLUGIN_SDK_FACADES = [
{
subpath: "anthropic-cli",
source: pluginSource("anthropic", "api.js"),
exports: ["CLAUDE_CLI_BACKEND_ID", "isClaudeCliProvider"],
},
{
subpath: "bluebubbles-policy",
source: pluginSource("bluebubbles", "api.js"),
exports: [
"isAllowedBlueBubblesSender",
"resolveBlueBubblesGroupRequireMention",
"resolveBlueBubblesGroupToolPolicy",
],
},
{
subpath: "browser",
source: pluginSource("browser", "runtime-api.js"),
loadPolicy: "activated",
exports: [
"browserHandlers",
"createBrowserPluginService",
"createBrowserTool",
"handleBrowserGatewayRequest",
"registerBrowserCli",
],
},
{
subpath: "feishu-conversation",
source: pluginSource("feishu", "api.js"),
exports: [
"buildFeishuConversationId",
"createFeishuThreadBindingManager",
"feishuSessionBindingAdapterChannels",
"feishuThreadBindingTesting",
"parseFeishuDirectConversationId",
"parseFeishuConversationId",
"parseFeishuTargetId",
],
},
{
subpath: "feishu-setup",
source: pluginSource("feishu", "api.js"),
exports: ["feishuSetupAdapter", "feishuSetupWizard"],
},
{
subpath: "github-copilot-login",
source: pluginSource("github-copilot", "api.js"),
exports: ["githubCopilotLoginCommand"],
},
{
subpath: "image-generation-runtime",
source: pluginSource("image-generation-core", "runtime-api.js"),
loadPolicy: "activated",
exports: [
"generateImage",
"listRuntimeImageGenerationProviders",
"GenerateImageParams",
"GenerateImageRuntimeResult",
],
typeExports: ["GenerateImageParams", "GenerateImageRuntimeResult"],
},
{
subpath: "irc-surface",
source: pluginSource("irc", "api.js"),
exports: [
"ircSetupAdapter",
"ircSetupWizard",
"listIrcAccountIds",
"resolveDefaultIrcAccountId",
"resolveIrcAccount",
],
},
{
subpath: "memory-core-engine-runtime",
source: pluginSource("memory-core", "runtime-api.js"),
loadPolicy: "activated",
exports: [
"auditShortTermPromotionArtifacts",
"BuiltinMemoryEmbeddingProviderDoctorMetadata",
"getBuiltinMemoryEmbeddingProviderDoctorMetadata",
"getMemorySearchManager",
"listBuiltinAutoSelectMemoryEmbeddingProviderDoctorMetadata",
"MemoryIndexManager",
"repairShortTermPromotionArtifacts",
],
typeExports: [
"BuiltinMemoryEmbeddingProviderDoctorMetadata",
"RepairShortTermPromotionArtifactsResult",
"ShortTermAuditSummary",
],
},
{
subpath: "mattermost-policy",
source: pluginSource("mattermost", "api.js"),
exports: ["isMattermostSenderAllowed"],
},
{
subpath: "litellm",
source: pluginSource("litellm", "api.js"),
exports: [
"applyLitellmConfig",
"applyLitellmProviderConfig",
"buildLitellmModelDefinition",
"LITELLM_BASE_URL",
"LITELLM_DEFAULT_MODEL_ID",
"LITELLM_DEFAULT_MODEL_REF",
],
},
{
subpath: "line-runtime",
source: pluginSource("line", "runtime-api.js"),
loadPolicy: "activated",
runtimeApiPreExportsPath: runtimeApiSourcePath("line"),
typeExports: [
"Action",
"CardAction",
"CreateRichMenuParams",
"FlexBox",
"FlexBubble",
"FlexButton",
"FlexCarousel",
"FlexComponent",
"FlexContainer",
"FlexImage",
"FlexText",
"LineChannelData",
"LineConfig",
"LineProbeResult",
"ListItem",
"ResolvedLineAccount",
"RichMenuArea",
"RichMenuAreaRequest",
"RichMenuRequest",
"RichMenuResponse",
"RichMenuSize",
],
},
{
subpath: "line-surface",
source: pluginSource("line", "runtime-api.js"),
// This surface is also used by passive reply normalization helpers.
// Keep it loadable without requiring the LINE plugin to be activated.
exports: [
"CardAction",
"createActionCard",
"createAgendaCard",
"createAppleTvRemoteCard",
"createDeviceControlCard",
"createEventCard",
"createImageCard",
"createInfoCard",
"createListCard",
"createMediaPlayerCard",
"createReceiptCard",
"LineChannelData",
"LineConfig",
"LineConfigSchema",
"LineProbeResult",
"listLineAccountIds",
"ListItem",
"normalizeAccountId",
"processLineMessage",
"ResolvedLineAccount",
"resolveDefaultLineAccountId",
"resolveExactLineGroupConfigKey",
"resolveLineAccount",
],
typeExports: [
"CardAction",
"LineChannelData",
"LineConfig",
"LineProbeResult",
"ListItem",
"ResolvedLineAccount",
],
},
{
subpath: "matrix-helper",
source: pluginSource("matrix", "api.js"),
exports: [
"findMatrixAccountEntry",
"getMatrixScopedEnvVarNames",
"requiresExplicitMatrixDefaultAccount",
"resolveConfiguredMatrixAccountIds",
"resolveMatrixAccountStorageRoot",
"resolveMatrixChannelConfig",
"resolveMatrixCredentialsDir",
"resolveMatrixCredentialsPath",
"resolveMatrixDefaultOrOnlyAccountId",
"resolveMatrixLegacyFlatStoragePaths",
],
},
{
subpath: "matrix-runtime-surface",
source: pluginSource("matrix", "runtime-api.js"),
loadPolicy: "activated",
exports: ["resolveMatrixAccountStringValues", "setMatrixRuntime"],
},
{
subpath: "matrix-surface",
source: pluginSource("matrix", "api.js"),
exports: [
"createMatrixThreadBindingManager",
"matrixSessionBindingAdapterChannels",
"resetMatrixThreadBindingsForTests",
],
},
{
subpath: "matrix-thread-bindings",
source: pluginSource("matrix", "api.js"),
exports: [
"setMatrixThreadBindingIdleTimeoutBySessionKey",
"setMatrixThreadBindingMaxAgeBySessionKey",
],
},
{
subpath: "openrouter",
source: pluginSource("openrouter", "api.js"),
exports: [
"applyOpenrouterConfig",
"applyOpenrouterProviderConfig",
"buildOpenrouterProvider",
"OPENROUTER_DEFAULT_MODEL_REF",
],
},
{
subpath: "vercel-ai-gateway",
source: pluginSource("vercel-ai-gateway", "api.js"),
exports: [
"buildVercelAiGatewayProvider",
"discoverVercelAiGatewayModels",
"getStaticVercelAiGatewayModelCatalog",
"VERCEL_AI_GATEWAY_BASE_URL",
"VERCEL_AI_GATEWAY_DEFAULT_CONTEXT_WINDOW",
"VERCEL_AI_GATEWAY_DEFAULT_COST",
"VERCEL_AI_GATEWAY_DEFAULT_MAX_TOKENS",
"VERCEL_AI_GATEWAY_DEFAULT_MODEL_ID",
"VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF",
"VERCEL_AI_GATEWAY_PROVIDER_ID",
],
},
{
subpath: "xiaomi",
source: pluginSource("xiaomi", "api.js"),
exports: [
"applyXiaomiConfig",
"applyXiaomiProviderConfig",
"buildXiaomiProvider",
"XIAOMI_DEFAULT_MODEL_ID",
"XIAOMI_DEFAULT_MODEL_REF",
],
},
{
subpath: "zai",
source: pluginSource("zai", "api.js"),
exports: [
"applyZaiConfig",
"applyZaiProviderConfig",
"ZAI_CN_BASE_URL",
"ZAI_CODING_CN_BASE_URL",
"ZAI_CODING_GLOBAL_BASE_URL",
"ZAI_DEFAULT_MODEL_ID",
"ZAI_DEFAULT_MODEL_REF",
"ZAI_GLOBAL_BASE_URL",
],
},
{
subpath: "zalo-setup",
source: pluginSource("zalo", "api.js"),
exports: [
"evaluateZaloGroupAccess",
"resolveZaloRuntimeGroupPolicy",
"zaloSetupAdapter",
"zaloSetupWizard",
],
},
];
export const GENERATED_PLUGIN_SDK_FACADES_BY_SUBPATH = Object.fromEntries(
GENERATED_PLUGIN_SDK_FACADES.map((entry) => [entry.subpath, entry]),
);
function resolveFacadeLoadPolicy(entry, sourcePath) {
// Keep loader policy next to the facade entry itself so additions stay local
// and mixed-source facades can opt into per-source behavior later if needed.
const sourcePolicy = entry.sourceLoadPolicy?.[sourcePath];
if (sourcePolicy) {
return sourcePolicy;
}
return entry.loadPolicy ?? "plain";
}
export const GENERATED_PLUGIN_SDK_FACADES_LABEL = "plugin-sdk-facades";
export const GENERATED_PLUGIN_SDK_FACADES_SCRIPT = "scripts/generate-plugin-sdk-facades.mjs";
export const GENERATED_PLUGIN_SDK_FACADE_TYPES_OUTPUT =
"src/generated/plugin-sdk-facade-type-map.generated.ts";
function rewriteFacadeTypeImportSpecifier(sourcePath) {
return sourcePath;
}
const MODULE_RESOLUTION_OPTIONS = {
allowJs: true,
checkJs: false,
jsx: ts.JsxEmit.Preserve,
module: ts.ModuleKind.ESNext,
moduleResolution: ts.ModuleResolutionKind.Bundler,
skipLibCheck: true,
target: ts.ScriptTarget.ESNext,
};
const MODULE_RESOLUTION_HOST = ts.createCompilerHost(MODULE_RESOLUTION_OPTIONS, true);
const moduleResolutionContextCache = new Map();
const sourceExportKindsCache = new Map();
function listFacadeEntrySourcePaths(entry) {
return Array.from(new Set([entry.source, ...Object.values(entry.exportSources ?? {})]));
}
function buildFacadeSourceModuleKey(sourceIndex) {
return `source${sourceIndex + 1}`;
}
function isPrimitiveTypeLike(type) {
if (type.isUnion()) {
return type.types.every((member) => isPrimitiveTypeLike(member));
}
const primitiveFlags =
ts.TypeFlags.StringLike |
ts.TypeFlags.NumberLike |
ts.TypeFlags.BooleanLike |
ts.TypeFlags.BigIntLike |
ts.TypeFlags.ESSymbolLike |
ts.TypeFlags.Null |
ts.TypeFlags.Undefined |
ts.TypeFlags.Void;
return Boolean(type.flags & primitiveFlags);
}
function isArrayTypeLike(checker, type) {
if (type.isUnion()) {
return type.types.every((member) => isArrayTypeLike(checker, member));
}
return checker.isArrayType(type) || checker.isTupleType(type);
}
function normalizeFacadeSourceParts(sourcePath) {
const packageSourceMatch = /^@openclaw\/([^/]+)\/([^/]+)$/u.exec(sourcePath);
if (packageSourceMatch) {
return {
dirName: packageSourceMatch[1],
artifactBasename: packageSourceMatch[2],
};
}
const match = /^\.\.\/\.\.\/extensions\/([^/]+)\/([^/]+)$/u.exec(sourcePath);
if (!match) {
throw new Error(`Unsupported plugin-sdk facade source: ${sourcePath}`);
}
return {
dirName: match[1],
artifactBasename: match[2],
};
}
function collectRuntimeApiPreExports(repoRoot, runtimeApiPath) {
const absolutePath = path.join(repoRoot, runtimeApiPath);
const sourceText = fs.readFileSync(absolutePath, "utf8");
const sourceFile = ts.createSourceFile(absolutePath, sourceText, ts.ScriptTarget.Latest, true);
const exportNames = new Set();
for (const statement of sourceFile.statements) {
if (!ts.isExportDeclaration(statement)) {
continue;
}
const moduleSpecifier =
statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier)
? statement.moduleSpecifier.text
: undefined;
if (!moduleSpecifier) {
continue;
}
if (statement.isTypeOnly) {
continue;
}
if (moduleSpecifier === "openclaw/plugin-sdk/line-runtime") {
break;
}
if (!moduleSpecifier.startsWith("./src/")) {
continue;
}
if (!statement.exportClause || !ts.isNamedExports(statement.exportClause)) {
continue;
}
for (const element of statement.exportClause.elements) {
if (!element.isTypeOnly) {
exportNames.add(element.name.text);
}
}
}
return Array.from(exportNames).toSorted((left, right) => left.localeCompare(right));
}
function resolveFacadeSourceTypescriptPath(repoRoot, sourcePath) {
const packageSourceMatch = /^@openclaw\/([^/]+)\/(.+)$/u.exec(sourcePath);
const absolutePath = packageSourceMatch
? path.resolve(repoRoot, "extensions", packageSourceMatch[1], packageSourceMatch[2])
: path.resolve(repoRoot, "src/plugin-sdk", sourcePath);
const candidates = [absolutePath.replace(/\.js$/, ".ts"), absolutePath.replace(/\.js$/, ".tsx")];
return candidates.find((candidate) => fs.existsSync(candidate));
}
function resolveFacadeModuleResolutionContext(repoRoot) {
const cacheKey = repoRoot || "__default__";
const cached = moduleResolutionContextCache.get(cacheKey);
if (cached) {
return cached;
}
let context = {
options: MODULE_RESOLUTION_OPTIONS,
host: MODULE_RESOLUTION_HOST,
};
if (repoRoot) {
const fileExists = (filePath) => ts.sys.fileExists(filePath);
const readFile = (filePath) => ts.sys.readFile(filePath);
const configPath = ts.findConfigFile(repoRoot, fileExists, "tsconfig.json");
if (configPath) {
const configFile = ts.readConfigFile(configPath, readFile);
if (!configFile.error) {
const parsedConfig = ts.parseJsonConfigFileContent(
configFile.config,
ts.sys,
path.dirname(configPath),
MODULE_RESOLUTION_OPTIONS,
configPath,
);
const options = {
...MODULE_RESOLUTION_OPTIONS,
...parsedConfig.options,
};
context = {
options,
host: ts.createCompilerHost(options, true),
};
}
}
}
moduleResolutionContextCache.set(cacheKey, context);
return context;
}
function resolveFacadeSourceExportKinds(repoRoot, sourcePath) {
const cacheKey = `${repoRoot}::${sourcePath}`;
const cached = sourceExportKindsCache.get(cacheKey);
if (cached) {
return cached;
}
const sourceTsPath = resolveFacadeSourceTypescriptPath(repoRoot, sourcePath);
if (!sourceTsPath) {
const empty = new Map();
sourceExportKindsCache.set(cacheKey, empty);
return empty;
}
const moduleResolutionContext = resolveFacadeModuleResolutionContext(repoRoot);
const program = ts.createProgram(
[sourceTsPath],
moduleResolutionContext.options,
moduleResolutionContext.host,
);
const sourceFile = program.getSourceFile(sourceTsPath);
if (!sourceFile) {
const empty = new Map();
sourceExportKindsCache.set(cacheKey, empty);
return empty;
}
const checker = program.getTypeChecker();
const moduleSymbol = checker.getSymbolAtLocation(sourceFile) ?? sourceFile.symbol;
const exportKinds = new Map();
if (moduleSymbol) {
for (const exported of checker.getExportsOfModule(moduleSymbol)) {
const symbol =
exported.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported;
const flags = symbol.flags;
const declaration =
symbol.valueDeclaration ?? exported.valueDeclaration ?? exported.declarations?.[0];
const typeAtLocation = declaration
? checker.getTypeOfSymbolAtLocation(symbol, declaration)
: checker.getDeclaredTypeOfSymbol(symbol);
exportKinds.set(exported.getName(), {
type: Boolean(flags & ts.SymbolFlags.Type),
value: Boolean(flags & ts.SymbolFlags.Value),
functionLike: Boolean(flags & (ts.SymbolFlags.Function | ts.SymbolFlags.Method)),
callable: typeAtLocation.getCallSignatures().length > 0,
arrayLike: isArrayTypeLike(checker, typeAtLocation),
primitiveLike: isPrimitiveTypeLike(typeAtLocation),
});
}
}
sourceExportKindsCache.set(cacheKey, exportKinds);
return exportKinds;
}
export function buildPluginSdkFacadeModule(entry, params = {}) {
const sourceExportKinds = params.repoRoot
? resolveFacadeSourceExportKinds(params.repoRoot, entry.source)
: new Map();
const explicitFunctionExports = new Set(entry.functionExports ?? []);
const directExportSources = entry.directExports ?? {};
const exportNames = entry.exportAll
? Array.from(sourceExportKinds.keys()).toSorted((left, right) => left.localeCompare(right))
: entry.runtimeApiPreExportsPath
? collectRuntimeApiPreExports(params.repoRoot, entry.runtimeApiPreExportsPath)
: entry.exports;
const explicitTypeExports = new Set(entry.typeExports ?? []);
const valueExports = [];
const typeExports = [];
const valueExportsBySource = new Map();
let needsLazyArrayHelper = false;
let needsLazyObjectHelper = false;
for (const exportName of exportNames ?? []) {
if (explicitTypeExports.has(exportName)) {
continue;
}
if (directExportSources[exportName]) {
valueExports.push(exportName);
continue;
}
const kind = sourceExportKinds.get(exportName);
if (kind?.type && !kind.value) {
typeExports.push(exportName);
continue;
}
valueExports.push(exportName);
if (kind?.arrayLike) {
needsLazyArrayHelper = true;
} else if (!kind?.functionLike && !kind?.callable && !kind?.primitiveLike) {
needsLazyObjectHelper = true;
}
const sourcePath = entry.exportSources?.[exportName] ?? entry.source;
const exportsForSource = valueExportsBySource.get(sourcePath) ?? [];
exportsForSource.push(exportName);
valueExportsBySource.set(sourcePath, exportsForSource);
}
for (const typeExport of entry.typeExports ?? []) {
if (!typeExports.includes(typeExport)) {
typeExports.push(typeExport);
}
}
const nonDirectValueExports = valueExports.filter(
(exportName) => !directExportSources[exportName],
);
const lines = [`// Generated by ${GENERATED_PLUGIN_SDK_FACADES_SCRIPT}. Do not edit manually.`];
if (nonDirectValueExports.length || typeExports.length) {
lines.push(
'import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";',
);
lines.push(`type FacadeEntry = PluginSdkFacadeTypeMap[${JSON.stringify(entry.subpath)}];`);
lines.push('type FacadeModule = FacadeEntry["module"];');
for (const [sourceIndex] of listFacadeEntrySourcePaths(entry).entries()) {
if (sourceIndex === 0) {
continue;
}
lines.push(
`type FacadeModule${sourceIndex + 1} = FacadeEntry["sourceModules"][${JSON.stringify(buildFacadeSourceModuleKey(sourceIndex))}]["module"];`,
);
}
}
const directExportsBySource = new Map();
for (const exportName of valueExports) {
const sourcePath = directExportSources[exportName];
if (!sourcePath) {
continue;
}
const exportsForSource = directExportsBySource.get(sourcePath) ?? [];
exportsForSource.push(exportName);
directExportsBySource.set(sourcePath, exportsForSource);
}
if (directExportsBySource.size > 0) {
for (const [sourcePath, exportNamesForSource] of [...directExportsBySource.entries()].toSorted(
([left], [right]) => left.localeCompare(right),
)) {
lines.push(
`export { ${exportNamesForSource.toSorted((left, right) => left.localeCompare(right)).join(", ")} } from ${JSON.stringify(sourcePath)};`,
);
}
}
if (nonDirectValueExports.length) {
const runtimeImports = new Set();
if (needsLazyArrayHelper) {
runtimeImports.add("createLazyFacadeArrayValue");
}
if (needsLazyObjectHelper) {
runtimeImports.add("createLazyFacadeObjectValue");
}
for (const sourcePath of listFacadeEntrySourcePaths(entry)) {
const loadPolicy = resolveFacadeLoadPolicy(entry, sourcePath);
runtimeImports.add(
loadPolicy === "activated"
? "loadActivatedBundledPluginPublicSurfaceModuleSync"
: "loadBundledPluginPublicSurfaceModuleSync",
);
}
lines.push(
`import { ${[...runtimeImports].toSorted((left, right) => left.localeCompare(right)).join(", ")} } from "./facade-runtime.js";`,
);
for (const [sourceIndex, sourcePath] of listFacadeEntrySourcePaths(entry).entries()) {
if (!valueExportsBySource.has(sourcePath)) {
continue;
}
const { dirName: sourceDirName, artifactBasename: sourceArtifactBasename } =
normalizeFacadeSourceParts(sourcePath);
const loadPolicy = resolveFacadeLoadPolicy(entry, sourcePath);
const loaderName =
loadPolicy === "activated"
? "loadActivatedBundledPluginPublicSurfaceModuleSync"
: "loadBundledPluginPublicSurfaceModuleSync";
const loaderSuffix = sourceIndex === 0 ? "" : String(sourceIndex + 1);
const moduleTypeName = sourceIndex === 0 ? "FacadeModule" : `FacadeModule${sourceIndex + 1}`;
lines.push("");
lines.push(`function loadFacadeModule${loaderSuffix}(): ${moduleTypeName} {`);
lines.push(` return ${loaderName}<${moduleTypeName}>({`);
lines.push(` dirName: ${JSON.stringify(sourceDirName)},`);
lines.push(` artifactBasename: ${JSON.stringify(sourceArtifactBasename)},`);
lines.push(" });");
lines.push("}");
}
}
if (nonDirectValueExports.length) {
const sourceIndexByPath = new Map(
listFacadeEntrySourcePaths(entry).map((sourcePath, index) => [sourcePath, index]),
);
for (const exportName of nonDirectValueExports) {
if (directExportSources[exportName]) {
continue;
}
const kind = sourceExportKinds.get(exportName);
const isExplicitFunctionExport = explicitFunctionExports.has(exportName);
const sourcePath = entry.exportSources?.[exportName] ?? entry.source;
const sourceIndex = sourceIndexByPath.get(sourcePath) ?? 0;
const loaderSuffix = sourceIndex === 0 ? "" : String(sourceIndex + 1);
const moduleTypeName = sourceIndex === 0 ? "FacadeModule" : `FacadeModule${sourceIndex + 1}`;
if (isExplicitFunctionExport || kind?.functionLike || kind?.callable) {
lines.push(
`export const ${exportName}: ${moduleTypeName}[${JSON.stringify(exportName)}] = ((...args) =>`,
);
lines.push(
` loadFacadeModule${loaderSuffix}()[${JSON.stringify(exportName)}](...args)) as ${moduleTypeName}[${JSON.stringify(exportName)}];`,
);
continue;
}
if (kind?.arrayLike) {
lines.push(
`export const ${exportName}: ${moduleTypeName}[${JSON.stringify(exportName)}] = createLazyFacadeArrayValue(() => loadFacadeModule${loaderSuffix}()[${JSON.stringify(exportName)}] as unknown as readonly unknown[]) as ${moduleTypeName}[${JSON.stringify(exportName)}];`,
);
continue;
}
if (!kind?.primitiveLike) {
lines.push(
`export const ${exportName}: ${moduleTypeName}[${JSON.stringify(exportName)}] = createLazyFacadeObjectValue(() => loadFacadeModule${loaderSuffix}()[${JSON.stringify(exportName)}] as object) as ${moduleTypeName}[${JSON.stringify(exportName)}];`,
);
continue;
}
lines.push(
`export const ${exportName}: ${moduleTypeName}[${JSON.stringify(exportName)}] = loadFacadeModule${loaderSuffix}()[${JSON.stringify(exportName)}];`,
);
}
}
if (typeExports.length) {
for (const exportedType of typeExports) {
lines.push(
`export type ${exportedType} = FacadeEntry["types"][${JSON.stringify(exportedType)}];`,
);
}
}
lines.push("");
return lines.join("\n");
}
export function buildPluginSdkFacadeTypeMapModule(entries) {
const lines = [`// Generated by ${GENERATED_PLUGIN_SDK_FACADES_SCRIPT}. Do not edit manually.`];
lines.push("export interface PluginSdkFacadeTypeMap {");
for (const entry of entries) {
const moduleImportPath = rewriteFacadeTypeImportSpecifier(entry.source);
lines.push(` ${JSON.stringify(entry.subpath)}: {`);
lines.push(` module: typeof import(${JSON.stringify(moduleImportPath)});`);
lines.push(" sourceModules: {");
for (const [sourceIndex, sourcePath] of listFacadeEntrySourcePaths(entry).entries()) {
const rewrittenSourcePath = rewriteFacadeTypeImportSpecifier(sourcePath);
lines.push(` ${JSON.stringify(buildFacadeSourceModuleKey(sourceIndex))}: {`);
lines.push(` module: typeof import(${JSON.stringify(rewrittenSourcePath)});`);
lines.push(" };");
}
lines.push(" };");
lines.push(" types: {");
for (const exportedType of entry.typeExports ?? []) {
const typeImportPath = rewriteFacadeTypeImportSpecifier(entry.source);
lines.push(
` ${JSON.stringify(exportedType)}: import(${JSON.stringify(typeImportPath)}).${exportedType};`,
);
}
lines.push(" };");
lines.push(" };");
}
lines.push("}");
lines.push("");
return lines.join("\n");
}

View File

@ -56,32 +56,6 @@ const TYPE_SHIMS: Partial<Record<string, string>> = {
].join("\n"),
};
const GENERATED_FACADE_TYPE_MAP_SOURCE = path.join(
process.cwd(),
"dist/plugin-sdk/src/generated/plugin-sdk-facade-type-map.generated.d.ts",
);
const GENERATED_FACADE_TYPE_MAP_DIST_PREFIX = "../../../extensions/";
function rewriteFacadeTypeMapSpecifier(specifier: string): string {
if (!specifier.startsWith("@openclaw/")) {
return specifier;
}
return `${GENERATED_FACADE_TYPE_MAP_DIST_PREFIX}${specifier.slice("@openclaw/".length)}`;
}
function rewriteGeneratedFacadeTypeMapDts(): void {
if (!fs.existsSync(GENERATED_FACADE_TYPE_MAP_SOURCE)) {
return;
}
const source = fs.readFileSync(GENERATED_FACADE_TYPE_MAP_SOURCE, "utf8");
const rewritten = source.replace(/@openclaw\/([a-z0-9-]+\/[^")\s]+)/g, (_match, suffix: string) =>
rewriteFacadeTypeMapSpecifier(`@openclaw/${suffix}`),
);
if (rewritten !== source) {
fs.writeFileSync(GENERATED_FACADE_TYPE_MAP_SOURCE, rewritten, "utf8");
}
}
// `tsc` emits declarations under `dist/plugin-sdk/src/plugin-sdk/*` because the source lives
// at `src/plugin-sdk/*` and `rootDir` is `.` (repo root, to support cross-src/extensions refs).
//
@ -104,5 +78,3 @@ for (const entry of pluginSdkEntrypoints) {
fs.mkdirSync(path.dirname(runtimeOut), { recursive: true });
fs.writeFileSync(runtimeOut, runtimeShim, "utf8");
}
rewriteGeneratedFacadeTypeMapDts();

View File

@ -4,8 +4,8 @@ import path from "node:path";
import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core";
import { Type } from "@sinclair/typebox";
import { describe, expect, it, vi } from "vitest";
import { createBrowserTool } from "../../extensions/browser/runtime-api.js";
import { applyXaiModelCompat } from "../../extensions/xai/api.js";
import { createBrowserTool } from "../plugin-sdk/browser.js";
import {
findUnsupportedSchemaKeywords,
GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS,

View File

@ -1,237 +0,0 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
export interface PluginSdkFacadeTypeMap {
"anthropic-cli": {
module: typeof import("@openclaw/anthropic/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/anthropic/api.js");
};
};
types: {};
};
"bluebubbles-policy": {
module: typeof import("@openclaw/bluebubbles/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/bluebubbles/api.js");
};
};
types: {};
};
browser: {
module: typeof import("@openclaw/browser/runtime-api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/browser/runtime-api.js");
};
};
types: {};
};
"feishu-conversation": {
module: typeof import("@openclaw/feishu/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/feishu/api.js");
};
};
types: {};
};
"feishu-setup": {
module: typeof import("@openclaw/feishu/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/feishu/api.js");
};
};
types: {};
};
"github-copilot-login": {
module: typeof import("@openclaw/github-copilot/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/github-copilot/api.js");
};
};
types: {};
};
"image-generation-runtime": {
module: typeof import("@openclaw/image-generation-core/runtime-api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/image-generation-core/runtime-api.js");
};
};
types: {
GenerateImageParams: import("@openclaw/image-generation-core/runtime-api.js").GenerateImageParams;
GenerateImageRuntimeResult: import("@openclaw/image-generation-core/runtime-api.js").GenerateImageRuntimeResult;
};
};
"irc-surface": {
module: typeof import("@openclaw/irc/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/irc/api.js");
};
};
types: {};
};
"memory-core-engine-runtime": {
module: typeof import("@openclaw/memory-core/runtime-api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/memory-core/runtime-api.js");
};
};
types: {
BuiltinMemoryEmbeddingProviderDoctorMetadata: import("@openclaw/memory-core/runtime-api.js").BuiltinMemoryEmbeddingProviderDoctorMetadata;
RepairShortTermPromotionArtifactsResult: import("@openclaw/memory-core/runtime-api.js").RepairShortTermPromotionArtifactsResult;
ShortTermAuditSummary: import("@openclaw/memory-core/runtime-api.js").ShortTermAuditSummary;
};
};
"mattermost-policy": {
module: typeof import("@openclaw/mattermost/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/mattermost/api.js");
};
};
types: {};
};
litellm: {
module: typeof import("@openclaw/litellm/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/litellm/api.js");
};
};
types: {};
};
"line-runtime": {
module: typeof import("@openclaw/line/runtime-api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/line/runtime-api.js");
};
};
types: {
Action: import("@openclaw/line/runtime-api.js").Action;
CardAction: import("@openclaw/line/runtime-api.js").CardAction;
CreateRichMenuParams: import("@openclaw/line/runtime-api.js").CreateRichMenuParams;
FlexBox: import("@openclaw/line/runtime-api.js").FlexBox;
FlexBubble: import("@openclaw/line/runtime-api.js").FlexBubble;
FlexButton: import("@openclaw/line/runtime-api.js").FlexButton;
FlexCarousel: import("@openclaw/line/runtime-api.js").FlexCarousel;
FlexComponent: import("@openclaw/line/runtime-api.js").FlexComponent;
FlexContainer: import("@openclaw/line/runtime-api.js").FlexContainer;
FlexImage: import("@openclaw/line/runtime-api.js").FlexImage;
FlexText: import("@openclaw/line/runtime-api.js").FlexText;
LineChannelData: import("@openclaw/line/runtime-api.js").LineChannelData;
LineConfig: import("@openclaw/line/runtime-api.js").LineConfig;
LineProbeResult: import("@openclaw/line/runtime-api.js").LineProbeResult;
ListItem: import("@openclaw/line/runtime-api.js").ListItem;
ResolvedLineAccount: import("@openclaw/line/runtime-api.js").ResolvedLineAccount;
RichMenuArea: import("@openclaw/line/runtime-api.js").RichMenuArea;
RichMenuAreaRequest: import("@openclaw/line/runtime-api.js").RichMenuAreaRequest;
RichMenuRequest: import("@openclaw/line/runtime-api.js").RichMenuRequest;
RichMenuResponse: import("@openclaw/line/runtime-api.js").RichMenuResponse;
RichMenuSize: import("@openclaw/line/runtime-api.js").RichMenuSize;
};
};
"line-surface": {
module: typeof import("@openclaw/line/runtime-api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/line/runtime-api.js");
};
};
types: {
CardAction: import("@openclaw/line/runtime-api.js").CardAction;
LineChannelData: import("@openclaw/line/runtime-api.js").LineChannelData;
LineConfig: import("@openclaw/line/runtime-api.js").LineConfig;
LineProbeResult: import("@openclaw/line/runtime-api.js").LineProbeResult;
ListItem: import("@openclaw/line/runtime-api.js").ListItem;
ResolvedLineAccount: import("@openclaw/line/runtime-api.js").ResolvedLineAccount;
};
};
"matrix-helper": {
module: typeof import("@openclaw/matrix/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/matrix/api.js");
};
};
types: {};
};
"matrix-runtime-surface": {
module: typeof import("@openclaw/matrix/runtime-api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/matrix/runtime-api.js");
};
};
types: {};
};
"matrix-surface": {
module: typeof import("@openclaw/matrix/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/matrix/api.js");
};
};
types: {};
};
"matrix-thread-bindings": {
module: typeof import("@openclaw/matrix/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/matrix/api.js");
};
};
types: {};
};
openrouter: {
module: typeof import("@openclaw/openrouter/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/openrouter/api.js");
};
};
types: {};
};
"vercel-ai-gateway": {
module: typeof import("@openclaw/vercel-ai-gateway/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/vercel-ai-gateway/api.js");
};
};
types: {};
};
xiaomi: {
module: typeof import("@openclaw/xiaomi/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/xiaomi/api.js");
};
};
types: {};
};
zai: {
module: typeof import("@openclaw/zai/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/zai/api.js");
};
};
types: {};
};
"zalo-setup": {
module: typeof import("@openclaw/zalo/api.js");
sourceModules: {
source1: {
module: typeof import("@openclaw/zalo/api.js");
};
};
types: {};
};
}

View File

@ -5,14 +5,14 @@ import {
generateImage,
listRuntimeImageGenerationProviders,
type GenerateImageRuntimeResult,
} from "../plugin-sdk/image-generation-runtime.js";
} from "./runtime.js";
const mocks = vi.hoisted(() => ({
generateImage: vi.fn<typeof generateImage>(),
listRuntimeImageGenerationProviders: vi.fn<typeof listRuntimeImageGenerationProviders>(),
}));
vi.mock("../plugin-sdk/image-generation-runtime.js", () => ({
vi.mock("../../extensions/image-generation-core/runtime-api.js", () => ({
generateImage: mocks.generateImage,
listRuntimeImageGenerationProviders: mocks.listRuntimeImageGenerationProviders,
}));
@ -23,7 +23,7 @@ describe("image-generation runtime facade", () => {
mocks.listRuntimeImageGenerationProviders.mockReset();
});
it("delegates image generation to the plugin-sdk runtime", async () => {
it("delegates image generation to the image runtime", async () => {
const result: GenerateImageRuntimeResult = {
images: [{ buffer: Buffer.from("png-bytes"), mimeType: "image/png", fileName: "sample.png" }],
provider: "image-plugin",
@ -48,7 +48,7 @@ describe("image-generation runtime facade", () => {
expect(mocks.generateImage).toHaveBeenCalledWith(params);
});
it("delegates provider listing to the plugin-sdk runtime", () => {
it("delegates provider listing to the image runtime", () => {
const providers: ImageGenerationProvider[] = [
{
id: "image-plugin",

View File

@ -3,4 +3,4 @@ export {
listRuntimeImageGenerationProviders,
type GenerateImageParams,
type GenerateImageRuntimeResult,
} from "../plugin-sdk/image-generation-runtime.js";
} from "../../extensions/image-generation-core/runtime-api.js";

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["anthropic-cli"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/anthropic/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["bluebubbles-policy"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/bluebubbles/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,32 +0,0 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["browser"];
type FacadeModule = FacadeEntry["module"];
import {
createLazyFacadeObjectValue,
loadActivatedBundledPluginPublicSurfaceModuleSync,
} from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {
return loadActivatedBundledPluginPublicSurfaceModuleSync<FacadeModule>({
dirName: "browser",
artifactBasename: "runtime-api.js",
});
}
export const browserHandlers: FacadeModule["browserHandlers"] = createLazyFacadeObjectValue(
() => loadFacadeModule()["browserHandlers"] as object,
) as FacadeModule["browserHandlers"];
export const createBrowserPluginService: FacadeModule["createBrowserPluginService"] = ((...args) =>
loadFacadeModule()["createBrowserPluginService"](
...args,
)) as FacadeModule["createBrowserPluginService"];
export const createBrowserTool: FacadeModule["createBrowserTool"] = ((...args) =>
loadFacadeModule()["createBrowserTool"](...args)) as FacadeModule["createBrowserTool"];
export const handleBrowserGatewayRequest: FacadeModule["handleBrowserGatewayRequest"] = ((
...args
) =>
loadFacadeModule()["handleBrowserGatewayRequest"](
...args,
)) as FacadeModule["handleBrowserGatewayRequest"];
export const registerBrowserCli: FacadeModule["registerBrowserCli"] = ((...args) =>
loadFacadeModule()["registerBrowserCli"](...args)) as FacadeModule["registerBrowserCli"];

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["feishu-conversation"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/feishu/api.js");
import {
createLazyFacadeArrayValue,
createLazyFacadeObjectValue,

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["feishu-setup"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/feishu/api.js");
import {
createLazyFacadeObjectValue,
loadBundledPluginPublicSurfaceModuleSync,

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["github-copilot-login"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/github-copilot/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,21 +0,0 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["image-generation-runtime"];
type FacadeModule = FacadeEntry["module"];
import { loadActivatedBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {
return loadActivatedBundledPluginPublicSurfaceModuleSync<FacadeModule>({
dirName: "image-generation-core",
artifactBasename: "runtime-api.js",
});
}
export const generateImage: FacadeModule["generateImage"] = ((...args) =>
loadFacadeModule()["generateImage"](...args)) as FacadeModule["generateImage"];
export const listRuntimeImageGenerationProviders: FacadeModule["listRuntimeImageGenerationProviders"] =
((...args) =>
loadFacadeModule()["listRuntimeImageGenerationProviders"](
...args,
)) as FacadeModule["listRuntimeImageGenerationProviders"];
export type GenerateImageParams = FacadeEntry["types"]["GenerateImageParams"];
export type GenerateImageRuntimeResult = FacadeEntry["types"]["GenerateImageRuntimeResult"];

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["irc-surface"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/irc/api.js");
import {
createLazyFacadeObjectValue,
loadBundledPluginPublicSurfaceModuleSync,

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["line-runtime"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/line/runtime-api.js");
import { loadActivatedBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {
@ -136,24 +134,24 @@ export const uploadRichMenuImage: FacadeModule["uploadRichMenuImage"] = ((...arg
loadFacadeModule()["uploadRichMenuImage"](...args)) as FacadeModule["uploadRichMenuImage"];
export const uriAction: FacadeModule["uriAction"] = ((...args) =>
loadFacadeModule()["uriAction"](...args)) as FacadeModule["uriAction"];
export type Action = FacadeEntry["types"]["Action"];
export type CardAction = FacadeEntry["types"]["CardAction"];
export type CreateRichMenuParams = FacadeEntry["types"]["CreateRichMenuParams"];
export type FlexBox = FacadeEntry["types"]["FlexBox"];
export type FlexBubble = FacadeEntry["types"]["FlexBubble"];
export type FlexButton = FacadeEntry["types"]["FlexButton"];
export type FlexCarousel = FacadeEntry["types"]["FlexCarousel"];
export type FlexComponent = FacadeEntry["types"]["FlexComponent"];
export type FlexContainer = FacadeEntry["types"]["FlexContainer"];
export type FlexImage = FacadeEntry["types"]["FlexImage"];
export type FlexText = FacadeEntry["types"]["FlexText"];
export type LineChannelData = FacadeEntry["types"]["LineChannelData"];
export type LineConfig = FacadeEntry["types"]["LineConfig"];
export type LineProbeResult = FacadeEntry["types"]["LineProbeResult"];
export type ListItem = FacadeEntry["types"]["ListItem"];
export type ResolvedLineAccount = FacadeEntry["types"]["ResolvedLineAccount"];
export type RichMenuArea = FacadeEntry["types"]["RichMenuArea"];
export type RichMenuAreaRequest = FacadeEntry["types"]["RichMenuAreaRequest"];
export type RichMenuRequest = FacadeEntry["types"]["RichMenuRequest"];
export type RichMenuResponse = FacadeEntry["types"]["RichMenuResponse"];
export type RichMenuSize = FacadeEntry["types"]["RichMenuSize"];
export type Action = import("@openclaw/line/runtime-api.js").Action;
export type CardAction = import("@openclaw/line/runtime-api.js").CardAction;
export type CreateRichMenuParams = import("@openclaw/line/runtime-api.js").CreateRichMenuParams;
export type FlexBox = import("@openclaw/line/runtime-api.js").FlexBox;
export type FlexBubble = import("@openclaw/line/runtime-api.js").FlexBubble;
export type FlexButton = import("@openclaw/line/runtime-api.js").FlexButton;
export type FlexCarousel = import("@openclaw/line/runtime-api.js").FlexCarousel;
export type FlexComponent = import("@openclaw/line/runtime-api.js").FlexComponent;
export type FlexContainer = import("@openclaw/line/runtime-api.js").FlexContainer;
export type FlexImage = import("@openclaw/line/runtime-api.js").FlexImage;
export type FlexText = import("@openclaw/line/runtime-api.js").FlexText;
export type LineChannelData = import("@openclaw/line/runtime-api.js").LineChannelData;
export type LineConfig = import("@openclaw/line/runtime-api.js").LineConfig;
export type LineProbeResult = import("@openclaw/line/runtime-api.js").LineProbeResult;
export type ListItem = import("@openclaw/line/runtime-api.js").ListItem;
export type ResolvedLineAccount = import("@openclaw/line/runtime-api.js").ResolvedLineAccount;
export type RichMenuArea = import("@openclaw/line/runtime-api.js").RichMenuArea;
export type RichMenuAreaRequest = import("@openclaw/line/runtime-api.js").RichMenuAreaRequest;
export type RichMenuRequest = import("@openclaw/line/runtime-api.js").RichMenuRequest;
export type RichMenuResponse = import("@openclaw/line/runtime-api.js").RichMenuResponse;
export type RichMenuSize = import("@openclaw/line/runtime-api.js").RichMenuSize;

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["line-surface"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/line/runtime-api.js");
import {
createLazyFacadeObjectValue,
loadBundledPluginPublicSurfaceModuleSync,
@ -60,9 +58,9 @@ export const resolveExactLineGroupConfigKey: FacadeModule["resolveExactLineGroup
)) as FacadeModule["resolveExactLineGroupConfigKey"];
export const resolveLineAccount: FacadeModule["resolveLineAccount"] = ((...args) =>
loadFacadeModule()["resolveLineAccount"](...args)) as FacadeModule["resolveLineAccount"];
export type CardAction = FacadeEntry["types"]["CardAction"];
export type LineChannelData = FacadeEntry["types"]["LineChannelData"];
export type LineConfig = FacadeEntry["types"]["LineConfig"];
export type LineProbeResult = FacadeEntry["types"]["LineProbeResult"];
export type ListItem = FacadeEntry["types"]["ListItem"];
export type ResolvedLineAccount = FacadeEntry["types"]["ResolvedLineAccount"];
export type CardAction = import("@openclaw/line/runtime-api.js").CardAction;
export type LineChannelData = import("@openclaw/line/runtime-api.js").LineChannelData;
export type LineConfig = import("@openclaw/line/runtime-api.js").LineConfig;
export type LineProbeResult = import("@openclaw/line/runtime-api.js").LineProbeResult;
export type ListItem = import("@openclaw/line/runtime-api.js").ListItem;
export type ResolvedLineAccount = import("@openclaw/line/runtime-api.js").ResolvedLineAccount;

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["litellm"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/litellm/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["matrix-helper"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/matrix/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["matrix-runtime-surface"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/matrix/runtime-api.js");
import { loadActivatedBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["matrix-surface"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/matrix/api.js");
import {
createLazyFacadeArrayValue,
loadBundledPluginPublicSurfaceModuleSync,

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["matrix-thread-bindings"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/matrix/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["mattermost-policy"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/mattermost/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["memory-core-engine-runtime"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/memory-core/runtime-api.js");
import {
createLazyFacadeObjectValue,
loadActivatedBundledPluginPublicSurfaceModuleSync,
@ -40,7 +38,8 @@ export const repairShortTermPromotionArtifacts: FacadeModule["repairShortTermPro
...args,
)) as FacadeModule["repairShortTermPromotionArtifacts"];
export type BuiltinMemoryEmbeddingProviderDoctorMetadata =
FacadeEntry["types"]["BuiltinMemoryEmbeddingProviderDoctorMetadata"];
import("@openclaw/memory-core/runtime-api.js").BuiltinMemoryEmbeddingProviderDoctorMetadata;
export type RepairShortTermPromotionArtifactsResult =
FacadeEntry["types"]["RepairShortTermPromotionArtifactsResult"];
export type ShortTermAuditSummary = FacadeEntry["types"]["ShortTermAuditSummary"];
import("@openclaw/memory-core/runtime-api.js").RepairShortTermPromotionArtifactsResult;
export type ShortTermAuditSummary =
import("@openclaw/memory-core/runtime-api.js").ShortTermAuditSummary;

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["openrouter"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/openrouter/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["vercel-ai-gateway"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/vercel-ai-gateway/api.js");
import {
createLazyFacadeObjectValue,
loadBundledPluginPublicSurfaceModuleSync,

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["xiaomi"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/xiaomi/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["zai"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/zai/api.js");
import { loadBundledPluginPublicSurfaceModuleSync } from "./facade-runtime.js";
function loadFacadeModule(): FacadeModule {

View File

@ -1,7 +1,5 @@
// Generated by scripts/generate-plugin-sdk-facades.mjs. Do not edit manually.
import type { PluginSdkFacadeTypeMap } from "../generated/plugin-sdk-facade-type-map.generated.js";
type FacadeEntry = PluginSdkFacadeTypeMap["zalo-setup"];
type FacadeModule = FacadeEntry["module"];
// Manual facade. Keep loader boundary explicit.
type FacadeModule = typeof import("@openclaw/zalo/api.js");
import {
createLazyFacadeObjectValue,
loadBundledPluginPublicSurfaceModuleSync,

View File

@ -240,17 +240,6 @@ async function readPackedRootPackageJson(archivePath: string): Promise<{
}
}
function readGeneratedFacadeTypeMap(): string {
return readFileSync(
resolve(REPO_ROOT, "src/generated/plugin-sdk-facade-type-map.generated.ts"),
"utf8",
);
}
function buildLegacyPluginSourceAlias(): string {
return ["openclaw", ["plugin", "source"].join("-")].join("/") + "/";
}
function collectExtensionFiles(dir: string): string[] {
const entries = readdirSync(dir, { withFileTypes: true });
const files: string[] = [];
@ -398,11 +387,6 @@ describe("plugin-sdk package contract guardrails", () => {
}
});
it("keeps generated facade types on package-style module specifiers", () => {
expect(readGeneratedFacadeTypeMap()).not.toContain("../../extensions/");
expect(readGeneratedFacadeTypeMap()).not.toContain(buildLegacyPluginSourceAlias());
});
it("keeps extension sources on public sdk or local package seams", () => {
expect(collectExtensionCoreImportLeaks()).toEqual([]);
});

View File

@ -165,7 +165,7 @@ function expectSourceOmitsImportPattern(subpath: string, specifier: string) {
function isGeneratedBundledFacadeSubpath(subpath: string): boolean {
const source = readPluginSdkSource(subpath);
return (
source.startsWith("// Generated by scripts/generate-plugin-sdk-facades.mjs.") &&
source.startsWith("// Manual facade.") &&
sourceMentionsIdentifier(source, "loadBundledPluginPublicSurfaceModuleSync")
);
}

View File

@ -1,5 +1,8 @@
import { resolveStateDir } from "../../config/paths.js";
import { loadBundledPluginPublicSurfaceModuleSync } from "../../plugin-sdk/facade-runtime.js";
import {
generateImage as generateRuntimeImage,
listRuntimeImageGenerationProviders,
} from "../../image-generation/runtime.js";
import { resolveGlobalSingleton } from "../../shared/global-singleton.js";
import {
createLazyRuntimeMethod,
@ -56,26 +59,10 @@ function createRuntimeMediaUnderstandingFacade(): PluginRuntime["mediaUnderstand
};
}
type RuntimeImageGenerationModule = Pick<
typeof import("../../plugin-sdk/image-generation-runtime.js"),
"generateImage" | "listRuntimeImageGenerationProviders"
>;
let cachedRuntimeImageGenerationModule: RuntimeImageGenerationModule | null = null;
function loadRuntimeImageGenerationModule(): RuntimeImageGenerationModule {
cachedRuntimeImageGenerationModule ??=
loadBundledPluginPublicSurfaceModuleSync<RuntimeImageGenerationModule>({
dirName: "image-generation-core",
artifactBasename: "runtime-api.js",
});
return cachedRuntimeImageGenerationModule;
}
function createRuntimeImageGeneration(): PluginRuntime["imageGeneration"] {
return {
generate: (params) => loadRuntimeImageGenerationModule().generateImage(params),
listProviders: (params) =>
loadRuntimeImageGenerationModule().listRuntimeImageGenerationProviders(params),
generate: (params) => generateRuntimeImage(params),
listProviders: (params) => listRuntimeImageGenerationProviders(params),
};
}

View File

@ -79,8 +79,8 @@ export type PluginRuntimeCore = {
transcribeAudioFile: typeof import("../../media-understanding/runtime.js").transcribeAudioFile;
};
imageGeneration: {
generate: typeof import("../../plugin-sdk/image-generation-runtime.js").generateImage;
listProviders: typeof import("../../plugin-sdk/image-generation-runtime.js").listRuntimeImageGenerationProviders;
generate: typeof import("../../image-generation/runtime.js").generateImage;
listProviders: typeof import("../../image-generation/runtime.js").listRuntimeImageGenerationProviders;
};
videoGeneration: {
generate: typeof import("../../video-generation/runtime.js").generateVideo;