feat: add video generation core infrastructure and extend image generation parameters (#53681)

* feat: add video generation core infrastructure and extend image generation parameters

Add full video generation capability to OpenClaw core:

- New `video_generate` agent tool with support for prompt, duration, aspect ratio,
  resolution, seed, watermark, I2V (first/last frame), camerafixed, and draft mode
- New `VideoGenerationProvider` plugin SDK type and `registerVideoGenerationProvider` API
- New `src/video-generation/` module (types, runtime with fallback, provider registry)
- New `openclaw/plugin-sdk/video-generation` export for external plugins
- 200MB max file size for generated videos (vs default 5MB for images)

Extend image generation with additional parameters:
- `seed`, `watermark`, `guidanceScale`, `optimizePrompt`, `providerOptions`
- New `readBooleanParam()` helper in tool common utilities

Update plugin registry, contracts, and all test mocks to include
`videoGenerationProviders` and `videoGenerationProviderIds`.

Made-with: Cursor

* fix: validate aspect ratio against target provider when model override is set

* cleanup: remove redundant ?? undefined from video/image generate tools

* chore: regenerate plugin SDK API baseline after video generation additions

---------

Co-authored-by: yongliang.xie <yongliang.xie@bytedance.com>
This commit is contained in:
xieyongliang
2026-03-26 09:45:06 +08:00
committed by GitHub
parent 39fbfd9b28
commit 4cb8dde894
37 changed files with 1380 additions and 241 deletions

View File

@@ -18,6 +18,7 @@ export function createTestPluginApi(api: TestPluginApiInput): OpenClawPluginApi
registerSpeechProvider() {},
registerMediaUnderstandingProvider() {},
registerImageGenerationProvider() {},
registerVideoGenerationProvider() {},
registerWebSearchProvider() {},
registerInteractiveHandler() {},
onConversationBindingResolved() {},

View File

@@ -59,7 +59,6 @@ import type { OpenClawConfig } from "../src/config/config.js";
import type { OutboundSendDeps } from "../src/infra/outbound/deliver.js";
import { installProcessWarningFilter } from "../src/infra/warning-filter.js";
import type { PluginRegistry } from "../src/plugins/registry.js";
import { createTestRegistry } from "../src/test-utils/channel-plugins.js";
import { cleanupSessionStateForTest } from "../src/test-utils/session-state-cleanup.js";
import { withIsolatedTestHome } from "./test-env.js";
@@ -78,6 +77,12 @@ type RegistryState = {
version: number;
};
type TestChannelRegistration = {
pluginId: string;
plugin: unknown;
source: string;
};
const globalRegistryState = (() => {
const globalState = globalThis as typeof globalThis & {
[REGISTRY_STATE]?: RegistryState;
@@ -219,6 +224,33 @@ const createStubPlugin = (params: {
outbound: createStubOutbound(params.id, params.deliveryMode),
});
const createTestRegistry = (channels: TestChannelRegistration[] = []): PluginRegistry => ({
plugins: [],
tools: [],
hooks: [],
typedHooks: [],
channels: channels as unknown as PluginRegistry["channels"],
channelSetups: channels.map((entry) => ({
pluginId: entry.pluginId,
plugin: entry.plugin as PluginRegistry["channelSetups"][number]["plugin"],
source: entry.source,
enabled: true,
})),
providers: [],
speechProviders: [],
mediaUnderstandingProviders: [],
imageGenerationProviders: [],
videoGenerationProviders: [],
webSearchProviders: [],
gatewayHandlers: {},
httpRoutes: [],
cliRegistrars: [],
services: [],
commands: [],
conversationBindingResolvedHandlers: [],
diagnostics: [],
});
const createDefaultRegistry = () =>
createTestRegistry([
{