From 4cb8dde894e3a85ce81b770869d7bd86e6b6e7a1 Mon Sep 17 00:00:00 2001 From: xieyongliang Date: Thu, 26 Mar 2026 09:45:06 +0800 Subject: [PATCH] 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 --- docs/.generated/plugin-sdk-api-baseline.json | 176 +++--- docs/.generated/plugin-sdk-api-baseline.jsonl | 176 +++--- extensions/lobster/src/lobster-tool.test.ts | 1 + package.json | 4 + scripts/lib/plugin-sdk-entrypoints.json | 1 + src/agents/openclaw-tools.ts | 6 + src/agents/pi-embedded-subscribe.tools.ts | 1 + src/agents/system-prompt.ts | 2 + src/agents/tool-catalog.ts | 8 + src/agents/tools/common.ts | 20 + src/agents/tools/image-generate-tool.ts | 23 +- src/agents/tools/video-generate-tool.ts | 239 ++++++++ src/auto-reply/reply/route-reply.test.ts | 1 + .../channel-setup/plugin-install.test.ts | 1 + src/gateway/server-plugins.test.ts | 1 + src/gateway/test-helpers.mocks.ts | 1 + src/image-generation/runtime.ts | 10 + src/image-generation/types.ts | 6 + src/plugin-sdk/video-generation.ts | 10 + src/plugins/captured-registration.ts | 7 + .../contracts/registry.contract.test.ts | 8 + src/plugins/contracts/registry.ts | 9 + src/plugins/contracts/shape.contract.test.ts | 1 + src/plugins/hooks.test-helpers.ts | 2 + src/plugins/loader.ts | 1 + src/plugins/registry-empty.ts | 1 + src/plugins/registry.ts | 22 + src/plugins/status.test-helpers.ts | 2 + src/plugins/status.test.ts | 518 +++++++++++++++--- src/plugins/status.ts | 2 + src/plugins/types.ts | 4 + src/test-utils/channel-plugins.ts | 1 + src/video-generation/provider-registry.ts | 80 +++ src/video-generation/runtime.ts | 179 ++++++ src/video-generation/types.ts | 62 +++ test/helpers/extensions/plugin-api.ts | 1 + test/setup.ts | 34 +- 37 files changed, 1380 insertions(+), 241 deletions(-) create mode 100644 src/agents/tools/video-generate-tool.ts create mode 100644 src/plugin-sdk/video-generation.ts create mode 100644 src/video-generation/provider-registry.ts create mode 100644 src/video-generation/runtime.ts create mode 100644 src/video-generation/types.ts diff --git a/docs/.generated/plugin-sdk-api-baseline.json b/docs/.generated/plugin-sdk-api-baseline.json index aeb01b07d87..44c5a729c2d 100644 --- a/docs/.generated/plugin-sdk-api-baseline.json +++ b/docs/.generated/plugin-sdk-api-baseline.json @@ -352,7 +352,7 @@ "exportName": "ImageGenerationProvider", "kind": "type", "source": { - "line": 66, + "line": 72, "path": "src/image-generation/types.ts" } }, @@ -379,7 +379,7 @@ "exportName": "ImageGenerationResult", "kind": "type", "source": { - "line": 36, + "line": 42, "path": "src/image-generation/types.ts" } }, @@ -397,7 +397,7 @@ "exportName": "MediaUnderstandingProviderPlugin", "kind": "type", "source": { - "line": 951, + "line": 952, "path": "src/plugins/types.ts" } }, @@ -415,7 +415,7 @@ "exportName": "OpenClawPluginApi", "kind": "type", "source": { - "line": 1314, + "line": 1316, "path": "src/plugins/types.ts" } }, @@ -424,7 +424,7 @@ "exportName": "OpenClawPluginConfigSchema", "kind": "type", "source": { - "line": 88, + "line": 89, "path": "src/plugins/types.ts" } }, @@ -433,7 +433,7 @@ "exportName": "PluginLogger", "kind": "type", "source": { - "line": 59, + "line": 60, "path": "src/plugins/types.ts" } }, @@ -451,7 +451,7 @@ "exportName": "ProviderAuthContext", "kind": "type", "source": { - "line": 155, + "line": 156, "path": "src/plugins/types.ts" } }, @@ -460,7 +460,7 @@ "exportName": "ProviderAuthResult", "kind": "type", "source": { - "line": 140, + "line": 141, "path": "src/plugins/types.ts" } }, @@ -469,7 +469,7 @@ "exportName": "ProviderRuntimeModel", "kind": "type", "source": { - "line": 295, + "line": 296, "path": "src/plugins/types.ts" } }, @@ -523,7 +523,7 @@ "exportName": "SpeechProviderPlugin", "kind": "type", "source": { - "line": 933, + "line": 934, "path": "src/plugins/types.ts" } }, @@ -3396,7 +3396,7 @@ "exportName": "MediaUnderstandingProviderPlugin", "kind": "type", "source": { - "line": 951, + "line": 952, "path": "src/plugins/types.ts" } }, @@ -3414,7 +3414,7 @@ "exportName": "OpenClawPluginApi", "kind": "type", "source": { - "line": 1314, + "line": 1316, "path": "src/plugins/types.ts" } }, @@ -3423,7 +3423,7 @@ "exportName": "OpenClawPluginCommandDefinition", "kind": "type", "source": { - "line": 1068, + "line": 1070, "path": "src/plugins/types.ts" } }, @@ -3432,7 +3432,7 @@ "exportName": "OpenClawPluginConfigSchema", "kind": "type", "source": { - "line": 88, + "line": 89, "path": "src/plugins/types.ts" } }, @@ -3441,7 +3441,7 @@ "exportName": "OpenClawPluginDefinition", "kind": "type", "source": { - "line": 1296, + "line": 1298, "path": "src/plugins/types.ts" } }, @@ -3450,7 +3450,7 @@ "exportName": "OpenClawPluginService", "kind": "type", "source": { - "line": 1285, + "line": 1287, "path": "src/plugins/types.ts" } }, @@ -3459,7 +3459,7 @@ "exportName": "OpenClawPluginServiceContext", "kind": "type", "source": { - "line": 1277, + "line": 1279, "path": "src/plugins/types.ts" } }, @@ -3468,7 +3468,7 @@ "exportName": "OpenClawPluginToolContext", "kind": "type", "source": { - "line": 103, + "line": 104, "path": "src/plugins/types.ts" } }, @@ -3477,7 +3477,7 @@ "exportName": "OpenClawPluginToolFactory", "kind": "type", "source": { - "line": 120, + "line": 121, "path": "src/plugins/types.ts" } }, @@ -3486,7 +3486,7 @@ "exportName": "PluginCommandContext", "kind": "type", "source": { - "line": 966, + "line": 968, "path": "src/plugins/types.ts" } }, @@ -3495,7 +3495,7 @@ "exportName": "PluginInteractiveTelegramHandlerContext", "kind": "type", "source": { - "line": 1097, + "line": 1099, "path": "src/plugins/types.ts" } }, @@ -3504,7 +3504,7 @@ "exportName": "PluginLogger", "kind": "type", "source": { - "line": 59, + "line": 60, "path": "src/plugins/types.ts" } }, @@ -3522,7 +3522,7 @@ "exportName": "ProviderAugmentModelCatalogContext", "kind": "type", "source": { - "line": 571, + "line": 572, "path": "src/plugins/types.ts" } }, @@ -3531,7 +3531,7 @@ "exportName": "ProviderAuthContext", "kind": "type", "source": { - "line": 155, + "line": 156, "path": "src/plugins/types.ts" } }, @@ -3540,7 +3540,7 @@ "exportName": "ProviderAuthDoctorHintContext", "kind": "type", "source": { - "line": 446, + "line": 447, "path": "src/plugins/types.ts" } }, @@ -3549,7 +3549,7 @@ "exportName": "ProviderAuthMethod", "kind": "type", "source": { - "line": 233, + "line": 234, "path": "src/plugins/types.ts" } }, @@ -3558,7 +3558,7 @@ "exportName": "ProviderAuthMethodNonInteractiveContext", "kind": "type", "source": { - "line": 217, + "line": 218, "path": "src/plugins/types.ts" } }, @@ -3567,7 +3567,7 @@ "exportName": "ProviderAuthResult", "kind": "type", "source": { - "line": 140, + "line": 141, "path": "src/plugins/types.ts" } }, @@ -3576,7 +3576,7 @@ "exportName": "ProviderBuildMissingAuthMessageContext", "kind": "type", "source": { - "line": 499, + "line": 500, "path": "src/plugins/types.ts" } }, @@ -3585,7 +3585,7 @@ "exportName": "ProviderBuiltInModelSuppressionContext", "kind": "type", "source": { - "line": 515, + "line": 516, "path": "src/plugins/types.ts" } }, @@ -3594,7 +3594,7 @@ "exportName": "ProviderBuiltInModelSuppressionResult", "kind": "type", "source": { - "line": 524, + "line": 525, "path": "src/plugins/types.ts" } }, @@ -3603,7 +3603,7 @@ "exportName": "ProviderCacheTtlEligibilityContext", "kind": "type", "source": { - "line": 487, + "line": 488, "path": "src/plugins/types.ts" } }, @@ -3612,7 +3612,7 @@ "exportName": "ProviderCatalogContext", "kind": "type", "source": { - "line": 254, + "line": 255, "path": "src/plugins/types.ts" } }, @@ -3621,7 +3621,7 @@ "exportName": "ProviderCatalogResult", "kind": "type", "source": { - "line": 277, + "line": 278, "path": "src/plugins/types.ts" } }, @@ -3630,7 +3630,7 @@ "exportName": "ProviderDefaultThinkingPolicyContext", "kind": "type", "source": { - "line": 548, + "line": 549, "path": "src/plugins/types.ts" } }, @@ -3639,7 +3639,7 @@ "exportName": "ProviderDiscoveryContext", "kind": "type", "source": { - "line": 587, + "line": 588, "path": "src/plugins/types.ts" } }, @@ -3648,7 +3648,7 @@ "exportName": "ProviderFetchUsageSnapshotContext", "kind": "type", "source": { - "line": 427, + "line": 428, "path": "src/plugins/types.ts" } }, @@ -3657,7 +3657,7 @@ "exportName": "ProviderModernModelPolicyContext", "kind": "type", "source": { - "line": 558, + "line": 559, "path": "src/plugins/types.ts" } }, @@ -3666,7 +3666,7 @@ "exportName": "ProviderNormalizeResolvedModelContext", "kind": "type", "source": { - "line": 338, + "line": 339, "path": "src/plugins/types.ts" } }, @@ -3675,7 +3675,7 @@ "exportName": "ProviderPreparedRuntimeAuth", "kind": "type", "source": { - "line": 374, + "line": 375, "path": "src/plugins/types.ts" } }, @@ -3684,7 +3684,7 @@ "exportName": "ProviderPrepareDynamicModelContext", "kind": "type", "source": { - "line": 329, + "line": 330, "path": "src/plugins/types.ts" } }, @@ -3693,7 +3693,7 @@ "exportName": "ProviderPrepareExtraParamsContext", "kind": "type", "source": { - "line": 460, + "line": 461, "path": "src/plugins/types.ts" } }, @@ -3702,7 +3702,7 @@ "exportName": "ProviderPrepareRuntimeAuthContext", "kind": "type", "source": { - "line": 353, + "line": 354, "path": "src/plugins/types.ts" } }, @@ -3711,7 +3711,7 @@ "exportName": "ProviderResolvedUsageAuth", "kind": "type", "source": { - "line": 414, + "line": 415, "path": "src/plugins/types.ts" } }, @@ -3720,7 +3720,7 @@ "exportName": "ProviderResolveDynamicModelContext", "kind": "type", "source": { - "line": 312, + "line": 313, "path": "src/plugins/types.ts" } }, @@ -3729,7 +3729,7 @@ "exportName": "ProviderResolveUsageAuthContext", "kind": "type", "source": { - "line": 395, + "line": 396, "path": "src/plugins/types.ts" } }, @@ -3738,7 +3738,7 @@ "exportName": "ProviderRuntimeModel", "kind": "type", "source": { - "line": 295, + "line": 296, "path": "src/plugins/types.ts" } }, @@ -3747,7 +3747,7 @@ "exportName": "ProviderThinkingPolicyContext", "kind": "type", "source": { - "line": 536, + "line": 537, "path": "src/plugins/types.ts" } }, @@ -3765,7 +3765,7 @@ "exportName": "ProviderWrapStreamFnContext", "kind": "type", "source": { - "line": 477, + "line": 478, "path": "src/plugins/types.ts" } }, @@ -3810,7 +3810,7 @@ "exportName": "SpeechProviderPlugin", "kind": "type", "source": { - "line": 933, + "line": 934, "path": "src/plugins/types.ts" } }, @@ -3902,7 +3902,7 @@ "exportName": "MediaUnderstandingProviderPlugin", "kind": "type", "source": { - "line": 951, + "line": 952, "path": "src/plugins/types.ts" } }, @@ -3920,7 +3920,7 @@ "exportName": "OpenClawPluginApi", "kind": "type", "source": { - "line": 1314, + "line": 1316, "path": "src/plugins/types.ts" } }, @@ -3929,7 +3929,7 @@ "exportName": "OpenClawPluginCommandDefinition", "kind": "type", "source": { - "line": 1068, + "line": 1070, "path": "src/plugins/types.ts" } }, @@ -3938,7 +3938,7 @@ "exportName": "OpenClawPluginConfigSchema", "kind": "type", "source": { - "line": 88, + "line": 89, "path": "src/plugins/types.ts" } }, @@ -3947,7 +3947,7 @@ "exportName": "OpenClawPluginDefinition", "kind": "type", "source": { - "line": 1296, + "line": 1298, "path": "src/plugins/types.ts" } }, @@ -3956,7 +3956,7 @@ "exportName": "OpenClawPluginService", "kind": "type", "source": { - "line": 1285, + "line": 1287, "path": "src/plugins/types.ts" } }, @@ -3965,7 +3965,7 @@ "exportName": "OpenClawPluginServiceContext", "kind": "type", "source": { - "line": 1277, + "line": 1279, "path": "src/plugins/types.ts" } }, @@ -3974,7 +3974,7 @@ "exportName": "PluginCommandContext", "kind": "type", "source": { - "line": 966, + "line": 968, "path": "src/plugins/types.ts" } }, @@ -3983,7 +3983,7 @@ "exportName": "PluginInteractiveTelegramHandlerContext", "kind": "type", "source": { - "line": 1097, + "line": 1099, "path": "src/plugins/types.ts" } }, @@ -3992,7 +3992,7 @@ "exportName": "PluginLogger", "kind": "type", "source": { - "line": 59, + "line": 60, "path": "src/plugins/types.ts" } }, @@ -4001,7 +4001,7 @@ "exportName": "ProviderAugmentModelCatalogContext", "kind": "type", "source": { - "line": 571, + "line": 572, "path": "src/plugins/types.ts" } }, @@ -4010,7 +4010,7 @@ "exportName": "ProviderAuthContext", "kind": "type", "source": { - "line": 155, + "line": 156, "path": "src/plugins/types.ts" } }, @@ -4019,7 +4019,7 @@ "exportName": "ProviderAuthDoctorHintContext", "kind": "type", "source": { - "line": 446, + "line": 447, "path": "src/plugins/types.ts" } }, @@ -4028,7 +4028,7 @@ "exportName": "ProviderAuthMethod", "kind": "type", "source": { - "line": 233, + "line": 234, "path": "src/plugins/types.ts" } }, @@ -4037,7 +4037,7 @@ "exportName": "ProviderAuthMethodNonInteractiveContext", "kind": "type", "source": { - "line": 217, + "line": 218, "path": "src/plugins/types.ts" } }, @@ -4046,7 +4046,7 @@ "exportName": "ProviderAuthResult", "kind": "type", "source": { - "line": 140, + "line": 141, "path": "src/plugins/types.ts" } }, @@ -4055,7 +4055,7 @@ "exportName": "ProviderBuildMissingAuthMessageContext", "kind": "type", "source": { - "line": 499, + "line": 500, "path": "src/plugins/types.ts" } }, @@ -4064,7 +4064,7 @@ "exportName": "ProviderBuiltInModelSuppressionContext", "kind": "type", "source": { - "line": 515, + "line": 516, "path": "src/plugins/types.ts" } }, @@ -4073,7 +4073,7 @@ "exportName": "ProviderBuiltInModelSuppressionResult", "kind": "type", "source": { - "line": 524, + "line": 525, "path": "src/plugins/types.ts" } }, @@ -4082,7 +4082,7 @@ "exportName": "ProviderCacheTtlEligibilityContext", "kind": "type", "source": { - "line": 487, + "line": 488, "path": "src/plugins/types.ts" } }, @@ -4091,7 +4091,7 @@ "exportName": "ProviderCatalogContext", "kind": "type", "source": { - "line": 254, + "line": 255, "path": "src/plugins/types.ts" } }, @@ -4100,7 +4100,7 @@ "exportName": "ProviderCatalogResult", "kind": "type", "source": { - "line": 277, + "line": 278, "path": "src/plugins/types.ts" } }, @@ -4109,7 +4109,7 @@ "exportName": "ProviderDefaultThinkingPolicyContext", "kind": "type", "source": { - "line": 548, + "line": 549, "path": "src/plugins/types.ts" } }, @@ -4118,7 +4118,7 @@ "exportName": "ProviderDiscoveryContext", "kind": "type", "source": { - "line": 587, + "line": 588, "path": "src/plugins/types.ts" } }, @@ -4127,7 +4127,7 @@ "exportName": "ProviderFetchUsageSnapshotContext", "kind": "type", "source": { - "line": 427, + "line": 428, "path": "src/plugins/types.ts" } }, @@ -4136,7 +4136,7 @@ "exportName": "ProviderModernModelPolicyContext", "kind": "type", "source": { - "line": 558, + "line": 559, "path": "src/plugins/types.ts" } }, @@ -4145,7 +4145,7 @@ "exportName": "ProviderNormalizeResolvedModelContext", "kind": "type", "source": { - "line": 338, + "line": 339, "path": "src/plugins/types.ts" } }, @@ -4154,7 +4154,7 @@ "exportName": "ProviderPreparedRuntimeAuth", "kind": "type", "source": { - "line": 374, + "line": 375, "path": "src/plugins/types.ts" } }, @@ -4163,7 +4163,7 @@ "exportName": "ProviderPrepareDynamicModelContext", "kind": "type", "source": { - "line": 329, + "line": 330, "path": "src/plugins/types.ts" } }, @@ -4172,7 +4172,7 @@ "exportName": "ProviderPrepareExtraParamsContext", "kind": "type", "source": { - "line": 460, + "line": 461, "path": "src/plugins/types.ts" } }, @@ -4181,7 +4181,7 @@ "exportName": "ProviderPrepareRuntimeAuthContext", "kind": "type", "source": { - "line": 353, + "line": 354, "path": "src/plugins/types.ts" } }, @@ -4190,7 +4190,7 @@ "exportName": "ProviderResolvedUsageAuth", "kind": "type", "source": { - "line": 414, + "line": 415, "path": "src/plugins/types.ts" } }, @@ -4199,7 +4199,7 @@ "exportName": "ProviderResolveDynamicModelContext", "kind": "type", "source": { - "line": 312, + "line": 313, "path": "src/plugins/types.ts" } }, @@ -4208,7 +4208,7 @@ "exportName": "ProviderResolveUsageAuthContext", "kind": "type", "source": { - "line": 395, + "line": 396, "path": "src/plugins/types.ts" } }, @@ -4217,7 +4217,7 @@ "exportName": "ProviderRuntimeModel", "kind": "type", "source": { - "line": 295, + "line": 296, "path": "src/plugins/types.ts" } }, @@ -4226,7 +4226,7 @@ "exportName": "ProviderThinkingPolicyContext", "kind": "type", "source": { - "line": 536, + "line": 537, "path": "src/plugins/types.ts" } }, @@ -4235,7 +4235,7 @@ "exportName": "ProviderWrapStreamFnContext", "kind": "type", "source": { - "line": 477, + "line": 478, "path": "src/plugins/types.ts" } }, @@ -4244,7 +4244,7 @@ "exportName": "SpeechProviderPlugin", "kind": "type", "source": { - "line": 933, + "line": 934, "path": "src/plugins/types.ts" } } diff --git a/docs/.generated/plugin-sdk-api-baseline.jsonl b/docs/.generated/plugin-sdk-api-baseline.jsonl index 389afd6a133..520603426b2 100644 --- a/docs/.generated/plugin-sdk-api-baseline.jsonl +++ b/docs/.generated/plugin-sdk-api-baseline.jsonl @@ -37,26 +37,26 @@ {"declaration":"export type DiagnosticEventPayload = DiagnosticEventPayload;","entrypoint":"index","exportName":"DiagnosticEventPayload","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":150,"sourcePath":"src/infra/diagnostic-events.ts"} {"declaration":"export type GeneratedImageAsset = GeneratedImageAsset;","entrypoint":"index","exportName":"GeneratedImageAsset","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/image-generation/types.ts"} {"declaration":"export type HookEntry = HookEntry;","entrypoint":"index","exportName":"HookEntry","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/hooks/types.ts"} -{"declaration":"export type ImageGenerationProvider = ImageGenerationProvider;","entrypoint":"index","exportName":"ImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":66,"sourcePath":"src/image-generation/types.ts"} +{"declaration":"export type ImageGenerationProvider = ImageGenerationProvider;","entrypoint":"index","exportName":"ImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":72,"sourcePath":"src/image-generation/types.ts"} {"declaration":"export type ImageGenerationRequest = ImageGenerationRequest;","entrypoint":"index","exportName":"ImageGenerationRequest","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/image-generation/types.ts"} {"declaration":"export type ImageGenerationResolution = ImageGenerationResolution;","entrypoint":"index","exportName":"ImageGenerationResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/image-generation/types.ts"} -{"declaration":"export type ImageGenerationResult = ImageGenerationResult;","entrypoint":"index","exportName":"ImageGenerationResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":36,"sourcePath":"src/image-generation/types.ts"} +{"declaration":"export type ImageGenerationResult = ImageGenerationResult;","entrypoint":"index","exportName":"ImageGenerationResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":42,"sourcePath":"src/image-generation/types.ts"} {"declaration":"export type ImageGenerationSourceImage = ImageGenerationSourceImage;","entrypoint":"index","exportName":"ImageGenerationSourceImage","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/image-generation/types.ts"} -{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":951,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":952,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} -{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1314,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1316,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":89,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"index","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"} -{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"index","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"index","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":156,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":141,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":296,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type ReplyPayload = ReplyPayload;","entrypoint":"index","exportName":"ReplyPayload","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":76,"sourcePath":"src/auto-reply/types.ts"} {"declaration":"export type RuntimeEnv = RuntimeEnv;","entrypoint":"index","exportName":"RuntimeEnv","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/runtime.ts"} {"declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"index","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/plugins/runtime/types-core.ts"} {"declaration":"export type SecretInput = SecretInput;","entrypoint":"index","exportName":"SecretInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.secrets.ts"} {"declaration":"export type SecretRef = SecretRef;","entrypoint":"index","exportName":"SecretRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":10,"sourcePath":"src/config/types.secrets.ts"} -{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":933,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":934,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type StatefulBindingTargetDescriptor = StatefulBindingTargetDescriptor;","entrypoint":"index","exportName":"StatefulBindingTargetDescriptor","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/binding-types.ts"} {"declaration":"export type StatefulBindingTargetDriver = StatefulBindingTargetDriver;","entrypoint":"index","exportName":"StatefulBindingTargetDriver","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"} {"declaration":"export type StatefulBindingTargetReadyResult = StatefulBindingTargetReadyResult;","entrypoint":"index","exportName":"StatefulBindingTargetReadyResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"} @@ -373,53 +373,53 @@ {"declaration":"export type ChannelPlugin = ChannelPlugin;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"} {"declaration":"export type GatewayBindUrlResult = GatewayBindUrlResult;","entrypoint":"core","exportName":"GatewayBindUrlResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/gateway-bind-url.ts"} {"declaration":"export type GatewayRequestHandlerOptions = GatewayRequestHandlerOptions;","entrypoint":"core","exportName":"GatewayRequestHandlerOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":112,"sourcePath":"src/gateway/server-methods/types.ts"} -{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":951,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":952,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} -{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1314,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1068,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1296,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1285,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1277,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":103,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":120,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":966,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1097,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1316,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1070,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":89,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1298,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1287,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1279,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":104,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":121,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":968,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1099,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"} -{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":571,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":446,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":499,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":487,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":277,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":548,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":338,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":374,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":329,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":460,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":353,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":414,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":572,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":156,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":447,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":234,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":218,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":141,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":500,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":516,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":525,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":488,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":255,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":278,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":549,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":588,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":428,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":559,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":339,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":375,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":330,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":461,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":354,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":415,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":313,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":396,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":296,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type ProviderUsageSnapshot = ProviderUsageSnapshot;","entrypoint":"core","exportName":"ProviderUsageSnapshot","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/provider-usage.types.ts"} -{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"core","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":477,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"core","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":478,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type RoutePeer = RoutePeer;","entrypoint":"core","exportName":"RoutePeer","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/routing/resolve-route.ts"} {"declaration":"export type RoutePeerKind = ChatType;","entrypoint":"core","exportName":"RoutePeerKind","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/routing/resolve-route.ts"} {"declaration":"export type SecretFileReadOptions = SecretFileReadOptions;","entrypoint":"core","exportName":"SecretFileReadOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/secret-file.ts"} {"declaration":"export type SecretFileReadResult = SecretFileReadResult;","entrypoint":"core","exportName":"SecretFileReadResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/infra/secret-file.ts"} -{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":933,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":934,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type TailscaleStatusCommandResult = TailscaleStatusCommandResult;","entrypoint":"core","exportName":"TailscaleStatusCommandResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/tailscale-status.ts"} {"declaration":"export type TailscaleStatusCommandRunner = TailscaleStatusCommandRunner;","entrypoint":"core","exportName":"TailscaleStatusCommandRunner","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/shared/tailscale-status.ts"} {"declaration":"export type UsageProviderId = UsageProviderId;","entrypoint":"core","exportName":"UsageProviderId","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":20,"sourcePath":"src/infra/provider-usage.types.ts"} @@ -429,45 +429,45 @@ {"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":88,"sourcePath":"src/plugin-sdk/plugin-entry.ts"} {"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"} {"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"plugin-entry","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"} -{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":951,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":952,"sourcePath":"src/plugins/types.ts"} {"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"plugin-entry","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"} -{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1314,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1068,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1296,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1285,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1277,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":966,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1097,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":571,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":446,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"plugin-entry","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"plugin-entry","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":499,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"plugin-entry","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":487,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"plugin-entry","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":277,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":548,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"plugin-entry","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"plugin-entry","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":338,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"plugin-entry","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":374,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":329,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":460,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":353,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"plugin-entry","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":414,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":477,"sourcePath":"src/plugins/types.ts"} -{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":933,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1316,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1070,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":89,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1298,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1287,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1279,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":968,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1099,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":572,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":156,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":447,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":234,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":218,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"plugin-entry","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":141,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"plugin-entry","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":500,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":516,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":525,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"plugin-entry","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":488,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":255,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"plugin-entry","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":278,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":549,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":588,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"plugin-entry","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":428,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":559,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"plugin-entry","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":339,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"plugin-entry","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":375,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":330,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":461,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":354,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"plugin-entry","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":415,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":313,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":396,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":296,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":478,"sourcePath":"src/plugins/types.ts"} +{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":934,"sourcePath":"src/plugins/types.ts"} {"category":"provider","entrypoint":"provider-onboard","importSpecifier":"openclaw/plugin-sdk/provider-onboard","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/provider-onboard.ts"} {"declaration":"export function applyAgentDefaultModelPrimary(cfg: OpenClawConfig, primary: string): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyAgentDefaultModelPrimary","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/plugins/provider-onboarding-config.ts"} {"declaration":"export function applyCloudflareAiGatewayConfig(cfg: OpenClawConfig, params?: { accountId?: string | undefined; gatewayId?: string | undefined; } | undefined): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyCloudflareAiGatewayConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":85,"sourcePath":"extensions/cloudflare-ai-gateway/onboard.ts"} diff --git a/extensions/lobster/src/lobster-tool.test.ts b/extensions/lobster/src/lobster-tool.test.ts index ff78b3728d3..40fd74769a3 100644 --- a/extensions/lobster/src/lobster-tool.test.ts +++ b/extensions/lobster/src/lobster-tool.test.ts @@ -48,6 +48,7 @@ function fakeApi(overrides: Partial = {}): OpenClawPluginApi registerSpeechProvider() {}, registerMediaUnderstandingProvider() {}, registerImageGenerationProvider() {}, + registerVideoGenerationProvider() {}, registerWebSearchProvider() {}, registerInteractiveHandler() {}, onConversationBindingResolved() {}, diff --git a/package.json b/package.json index 762f40bf3fd..32ecb859818 100644 --- a/package.json +++ b/package.json @@ -541,6 +541,10 @@ "types": "./dist/plugin-sdk/twitch.d.ts", "default": "./dist/plugin-sdk/twitch.js" }, + "./plugin-sdk/video-generation": { + "types": "./dist/plugin-sdk/video-generation.d.ts", + "default": "./dist/plugin-sdk/video-generation.js" + }, "./plugin-sdk/webhook-ingress": { "types": "./dist/plugin-sdk/webhook-ingress.d.ts", "default": "./dist/plugin-sdk/webhook-ingress.js" diff --git a/scripts/lib/plugin-sdk-entrypoints.json b/scripts/lib/plugin-sdk-entrypoints.json index f67c51a49a2..c8bf9d152e9 100644 --- a/scripts/lib/plugin-sdk-entrypoints.json +++ b/scripts/lib/plugin-sdk-entrypoints.json @@ -125,6 +125,7 @@ "tlon", "tool-send", "twitch", + "video-generation", "webhook-ingress", "webhook-path", "web-media", diff --git a/src/agents/openclaw-tools.ts b/src/agents/openclaw-tools.ts index aa08916e48c..3d8f51a7de4 100644 --- a/src/agents/openclaw-tools.ts +++ b/src/agents/openclaw-tools.ts @@ -26,6 +26,7 @@ import { createSessionsSpawnTool } from "./tools/sessions-spawn-tool.js"; import { createSessionsYieldTool } from "./tools/sessions-yield-tool.js"; import { createSubagentsTool } from "./tools/subagents-tool.js"; import { createTtsTool } from "./tools/tts-tool.js"; +import { createVideoGenerateTool } from "./tools/video-generate-tool.js"; import { createWebFetchTool, createWebSearchTool } from "./tools/web-tools.js"; import { resolveWorkspaceRoot } from "./workspace-dir.js"; @@ -124,6 +125,10 @@ export function createOpenClawTools( sandbox, fsPolicy: options?.fsPolicy, }); + const videoGenerateTool = createVideoGenerateTool({ + config: options?.config, + agentDir: options?.agentDir, + }); const pdfTool = options?.agentDir?.trim() ? createPdfTool({ config: options?.config, @@ -186,6 +191,7 @@ export function createOpenClawTools( config: options?.config, }), ...(imageGenerateTool ? [imageGenerateTool] : []), + ...(videoGenerateTool ? [videoGenerateTool] : []), createGatewayTool({ agentSessionKey: options?.agentSessionKey, config: options?.config, diff --git a/src/agents/pi-embedded-subscribe.tools.ts b/src/agents/pi-embedded-subscribe.tools.ts index ab969706d77..529c8319f0c 100644 --- a/src/agents/pi-embedded-subscribe.tools.ts +++ b/src/agents/pi-embedded-subscribe.tools.ts @@ -143,6 +143,7 @@ const TRUSTED_TOOL_RESULT_MEDIA = new Set([ "gateway", "image", "image_generate", + "video_generate", "memory_get", "memory_search", "message", diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index fc043effed5..dce94492166 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -256,6 +256,7 @@ export function buildAgentSystemPrompt(params: { "Show a /status-equivalent status card (usage + time + Reasoning/Verbose/Elevated); use for model-use questions (📊 session_status); optional per-session model override", image: "Analyze an image with the configured image model", image_generate: "Generate images with the configured image-generation model", + video_generate: "Generate short videos with the configured video-generation model", }; const toolOrder = [ @@ -284,6 +285,7 @@ export function buildAgentSystemPrompt(params: { "session_status", "image", "image_generate", + "video_generate", ]; const rawToolNames = (params.toolNames ?? []).map((tool) => tool.trim()); diff --git a/src/agents/tool-catalog.ts b/src/agents/tool-catalog.ts index 0d58c066928..cd8c1d07d8b 100644 --- a/src/agents/tool-catalog.ts +++ b/src/agents/tool-catalog.ts @@ -241,6 +241,14 @@ const CORE_TOOL_DEFINITIONS: CoreToolDefinition[] = [ profiles: ["coding"], includeInOpenClawGroup: true, }, + { + id: "video_generate", + label: "video_generate", + description: "Video generation", + sectionId: "media", + profiles: ["coding"], + includeInOpenClawGroup: true, + }, { id: "tts", label: "tts", diff --git a/src/agents/tools/common.ts b/src/agents/tools/common.ts index cff6d62a7a3..5e73469246e 100644 --- a/src/agents/tools/common.ts +++ b/src/agents/tools/common.ts @@ -142,6 +142,26 @@ export function readNumberParam( return integer ? Math.trunc(value) : value; } +export function readBooleanParam( + params: Record, + key: string, +): boolean | undefined { + const raw = readParamRaw(params, key); + if (typeof raw === "boolean") { + return raw; + } + if (typeof raw === "string") { + const trimmed = raw.trim().toLowerCase(); + if (trimmed === "true" || trimmed === "1") { + return true; + } + if (trimmed === "false" || trimmed === "0") { + return false; + } + } + return undefined; +} + export function readStringArrayParam( params: Record, key: string, diff --git a/src/agents/tools/image-generate-tool.ts b/src/agents/tools/image-generate-tool.ts index 9a0619ffca9..04078c34f24 100644 --- a/src/agents/tools/image-generate-tool.ts +++ b/src/agents/tools/image-generate-tool.ts @@ -16,7 +16,7 @@ import { saveMediaBuffer } from "../../media/store.js"; import { loadWebMedia } from "../../media/web-media.js"; import { getProviderEnvVars } from "../../secrets/provider-env-vars.js"; import { resolveUserPath } from "../../utils.js"; -import { ToolInputError, readNumberParam, readStringParam } from "./common.js"; +import { ToolInputError, readBooleanParam, readNumberParam, readStringParam } from "./common.js"; import { decodeDataUrl } from "./image-tool.helpers.js"; import { applyImageGenerationModelConfigDefaults, @@ -106,6 +106,18 @@ const ImageGenerateToolSchema = Type.Object({ maximum: MAX_COUNT, }), ), + seed: Type.Optional(Type.Number({ description: "Random seed for reproducibility." })), + watermark: Type.Optional(Type.Boolean({ description: "Add watermark to image." })), + guidanceScale: Type.Optional( + Type.Number({ + description: "Controls prompt adherence strength (1.0-20.0). Higher means stricter.", + minimum: 1, + maximum: 20, + }), + ), + optimizePrompt: Type.Optional( + Type.Boolean({ description: "Enable automatic prompt optimization for better results." }), + ), }); function getImageGenerationProviderAuthEnvVars(providerId: string): string[] { @@ -579,6 +591,11 @@ export function createImageGenerateTool(options?: { resolution, }); + const seed = readNumberParam(params, "seed", { integer: true }); + const watermark = readBooleanParam(params, "watermark"); + const guidanceScale = readNumberParam(params, "guidanceScale"); + const optimizePrompt = readBooleanParam(params, "optimizePrompt"); + const result = await generateImage({ cfg: effectiveCfg, prompt, @@ -589,6 +606,10 @@ export function createImageGenerateTool(options?: { resolution, count, inputImages, + seed, + watermark, + guidanceScale, + optimizePrompt, }); const savedImages = await Promise.all( diff --git a/src/agents/tools/video-generate-tool.ts b/src/agents/tools/video-generate-tool.ts new file mode 100644 index 00000000000..86e69b788c9 --- /dev/null +++ b/src/agents/tools/video-generate-tool.ts @@ -0,0 +1,239 @@ +import { Type } from "@sinclair/typebox"; +import type { OpenClawConfig } from "../../config/config.js"; +import { loadConfig } from "../../config/config.js"; +import { saveMediaBuffer } from "../../media/store.js"; +import { + generateVideo, + listRuntimeVideoGenerationProviders, +} from "../../video-generation/runtime.js"; +import type { VideoGenerationProvider } from "../../video-generation/types.js"; +import { ToolInputError, readBooleanParam, readNumberParam, readStringParam } from "./common.js"; +import type { AnyAgentTool } from "./tool-runtime.helpers.js"; + +const SUPPORTED_ASPECT_RATIOS = new Set(["1:1", "3:4", "4:3", "9:16", "16:9", "21:9"]); + +const VideoGenerateToolSchema = Type.Object({ + action: Type.Optional( + Type.String({ + description: + 'Optional action: "generate" (default) or "list" to inspect available providers/models.', + }), + ), + prompt: Type.Optional(Type.String({ description: "Video generation prompt." })), + model: Type.Optional( + Type.String({ + description: "Optional provider/model override, e.g. byteplus/seedance-1-5-pro-251215.", + }), + ), + duration: Type.Optional( + Type.Number({ + description: "Duration in seconds (typically 4-12).", + minimum: 1, + maximum: 60, + }), + ), + aspectRatio: Type.Optional( + Type.String({ + description: "Optional aspect ratio: 1:1, 3:4, 4:3, 9:16, 16:9, or 21:9.", + }), + ), + resolution: Type.Optional( + Type.String({ + description: "Optional resolution: 480p, 720p, or 1080p.", + }), + ), + seed: Type.Optional(Type.Number({ description: "Random seed for reproducibility." })), + watermark: Type.Optional(Type.Boolean({ description: "Add watermark to video." })), + firstFrameImageUrl: Type.Optional( + Type.String({ + description: "URL of the first frame reference image for image-to-video (I2V) generation.", + }), + ), + lastFrameImageUrl: Type.Optional( + Type.String({ + description: "URL of the last frame reference image for I2V generation.", + }), + ), + camerafixed: Type.Optional( + Type.Boolean({ description: "Fix camera position during generation." }), + ), + draft: Type.Optional( + Type.Boolean({ description: "Draft mode for faster generation (forces 480p)." }), + ), +}); + +function resolveAction(args: Record): "generate" | "list" { + const raw = readStringParam(args, "action"); + if (!raw) { + return "generate"; + } + const normalized = raw.trim().toLowerCase(); + if (normalized === "generate" || normalized === "list") { + return normalized; + } + throw new ToolInputError('action must be "generate" or "list"'); +} + +function buildListResponse(cfg?: OpenClawConfig): string { + const providers = listRuntimeVideoGenerationProviders({ config: cfg }); + if (providers.length === 0) { + return "No video generation providers available. Install a plugin that supports video generation."; + } + const lines: string[] = ["Available video generation providers:"]; + for (const provider of providers) { + const models = provider.models ?? (provider.defaultModel ? [provider.defaultModel] : []); + const capLines: string[] = []; + if (provider.capabilities.aspectRatios?.length) { + capLines.push(`aspect ratios: ${provider.capabilities.aspectRatios.join(", ")}`); + } + if (provider.capabilities.resolutions?.length) { + capLines.push(`resolutions: ${provider.capabilities.resolutions.join(", ")}`); + } + if (provider.capabilities.maxDurationSeconds) { + capLines.push( + `duration: ${provider.capabilities.minDurationSeconds ?? 1}-${provider.capabilities.maxDurationSeconds}s`, + ); + } + lines.push( + `- ${provider.id}${provider.label ? ` (${provider.label})` : ""}: ${models.join(", ")}${capLines.length > 0 ? ` [${capLines.join("; ")}]` : ""}`, + ); + } + return lines.join("\n"); +} + +function validateAspectRatio( + requested: string | undefined, + provider: VideoGenerationProvider | undefined, +): string | undefined { + if (!requested) { + return undefined; + } + const normalized = requested.trim(); + if (!SUPPORTED_ASPECT_RATIOS.has(normalized)) { + throw new ToolInputError( + `Unsupported aspect ratio "${normalized}". Supported: ${[...SUPPORTED_ASPECT_RATIOS].join(", ")}`, + ); + } + if ( + provider?.capabilities.aspectRatios?.length && + !provider.capabilities.aspectRatios.includes(normalized) + ) { + throw new ToolInputError( + `Provider does not support aspect ratio "${normalized}". Supported: ${provider.capabilities.aspectRatios.join(", ")}`, + ); + } + return normalized; +} + +export function createVideoGenerateTool(params: { + config?: OpenClawConfig; + agentDir?: string; +}): AnyAgentTool | null { + const providers = listRuntimeVideoGenerationProviders({ config: params.config }); + if (providers.length === 0) { + return null; + } + + return { + label: "Video Generation", + name: "video_generate", + description: + 'Generate a short video from a text prompt. Returns a saved video file path. Use action="list" to see available providers, models, and capabilities. Generated videos are delivered automatically from the tool result as MEDIA paths.', + parameters: VideoGenerateToolSchema, + execute: async (_toolCallId, args) => { + const rawArgs = args as Record; + const cfg = params.config ?? loadConfig(); + const action = resolveAction(rawArgs); + + if (action === "list") { + return { + content: [{ type: "text", text: buildListResponse(cfg) }], + details: {}, + }; + } + + const prompt = readStringParam(rawArgs, "prompt"); + if (!prompt?.trim()) { + throw new ToolInputError("prompt is required for video generation"); + } + + const modelOverride = readStringParam(rawArgs, "model"); + const duration = readNumberParam(rawArgs, "duration", { integer: true }); + const aspectRatio = readStringParam(rawArgs, "aspectRatio"); + const resolution = readStringParam(rawArgs, "resolution"); + const seed = readNumberParam(rawArgs, "seed", { integer: true }); + const watermark = readBooleanParam(rawArgs, "watermark"); + const firstFrameImageUrl = readStringParam(rawArgs, "firstFrameImageUrl"); + const lastFrameImageUrl = readStringParam(rawArgs, "lastFrameImageUrl"); + const camerafixed = readBooleanParam(rawArgs, "camerafixed"); + const draft = readBooleanParam(rawArgs, "draft"); + + const currentProviders = listRuntimeVideoGenerationProviders({ config: cfg }); + const parsedOverride = modelOverride?.includes("/") + ? { provider: modelOverride.split("/")[0] } + : null; + const validationProvider = parsedOverride + ? (currentProviders.find((p) => p.id === parsedOverride.provider) ?? currentProviders[0]) + : currentProviders[0]; + const validatedAspectRatio = validateAspectRatio(aspectRatio, validationProvider); + + const providerOptions: Record = {}; + if (camerafixed != null) { + providerOptions.camerafixed = camerafixed; + } + if (draft != null) { + providerOptions.draft = draft; + } + + const result = await generateVideo({ + cfg, + prompt: prompt.trim(), + agentDir: params.agentDir, + modelOverride, + durationSeconds: duration, + aspectRatio: validatedAspectRatio, + resolution: resolution?.trim(), + seed, + watermark, + firstFrameImageUrl, + lastFrameImageUrl, + providerOptions: Object.keys(providerOptions).length > 0 ? providerOptions : undefined, + }); + + const VIDEO_MAX_BYTES = 200 * 1024 * 1024; // 200MB for generated videos + const savedVideos = await Promise.all( + result.videos.map((video) => + saveMediaBuffer( + video.buffer, + video.mimeType, + "tool-video-generation", + VIDEO_MAX_BYTES, + video.fileName, + ), + ), + ); + + const lines = [ + `Generated ${savedVideos.length} video${savedVideos.length === 1 ? "" : "s"} with ${result.provider}/${result.model}.`, + ]; + + return { + content: [{ type: "text", text: lines.join("\n") }], + details: { + provider: result.provider, + model: result.model, + count: savedVideos.length, + media: { + mediaUrls: savedVideos.map((video) => video.path), + }, + paths: savedVideos.map((video) => video.path), + ...(duration ? { duration } : {}), + ...(validatedAspectRatio ? { aspectRatio: validatedAspectRatio } : {}), + ...(resolution ? { resolution } : {}), + attempts: result.attempts, + metadata: result.metadata, + }, + }; + }, + }; +} diff --git a/src/auto-reply/reply/route-reply.test.ts b/src/auto-reply/reply/route-reply.test.ts index 227d0c896b8..1c0f937db29 100644 --- a/src/auto-reply/reply/route-reply.test.ts +++ b/src/auto-reply/reply/route-reply.test.ts @@ -102,6 +102,7 @@ const createRegistry = (channels: PluginRegistry["channels"]): PluginRegistry => speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], gatewayHandlers: {}, httpRoutes: [], diff --git a/src/commands/channel-setup/plugin-install.test.ts b/src/commands/channel-setup/plugin-install.test.ts index 137609bc9d1..d842562d769 100644 --- a/src/commands/channel-setup/plugin-install.test.ts +++ b/src/commands/channel-setup/plugin-install.test.ts @@ -394,6 +394,7 @@ describe("ensureChannelSetupPluginInstalled", () => { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: [], gatewayMethods: [], cliCommands: [], diff --git a/src/gateway/server-plugins.test.ts b/src/gateway/server-plugins.test.ts index c59b14d7454..358c9efd7fa 100644 --- a/src/gateway/server-plugins.test.ts +++ b/src/gateway/server-plugins.test.ts @@ -62,6 +62,7 @@ const createRegistry = (diagnostics: PluginDiagnostic[]): PluginRegistry => ({ speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], gatewayHandlers: {}, httpRoutes: [], diff --git a/src/gateway/test-helpers.mocks.ts b/src/gateway/test-helpers.mocks.ts index 7f41104ba4f..de4c4a0e736 100644 --- a/src/gateway/test-helpers.mocks.ts +++ b/src/gateway/test-helpers.mocks.ts @@ -163,6 +163,7 @@ const createStubPluginRegistry = (): PluginRegistry => ({ ], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], gatewayHandlers: {}, httpRoutes: [], diff --git a/src/image-generation/runtime.ts b/src/image-generation/runtime.ts index 5b273988966..335d66670d6 100644 --- a/src/image-generation/runtime.ts +++ b/src/image-generation/runtime.ts @@ -30,6 +30,11 @@ export type GenerateImageParams = { aspectRatio?: string; resolution?: ImageGenerationResolution; inputImages?: ImageGenerationSourceImage[]; + seed?: number; + watermark?: boolean; + guidanceScale?: number; + optimizePrompt?: boolean; + providerOptions?: Record; }; export type GenerateImageRuntimeResult = { @@ -153,6 +158,11 @@ export async function generateImage( aspectRatio: params.aspectRatio, resolution: params.resolution, inputImages: params.inputImages, + seed: params.seed, + watermark: params.watermark, + guidanceScale: params.guidanceScale, + optimizePrompt: params.optimizePrompt, + providerOptions: params.providerOptions, }); if (!Array.isArray(result.images) || result.images.length === 0) { throw new Error("Image generation provider returned no images."); diff --git a/src/image-generation/types.ts b/src/image-generation/types.ts index 8e1a8fa0136..cfb2efce7b2 100644 --- a/src/image-generation/types.ts +++ b/src/image-generation/types.ts @@ -31,6 +31,12 @@ export type ImageGenerationRequest = { aspectRatio?: string; resolution?: ImageGenerationResolution; inputImages?: ImageGenerationSourceImage[]; + seed?: number; + watermark?: boolean; + guidanceScale?: number; + optimizePrompt?: boolean; + /** Provider-specific options (e.g. sequential generation). */ + providerOptions?: Record; }; export type ImageGenerationResult = { diff --git a/src/plugin-sdk/video-generation.ts b/src/plugin-sdk/video-generation.ts new file mode 100644 index 00000000000..43a7f01183b --- /dev/null +++ b/src/plugin-sdk/video-generation.ts @@ -0,0 +1,10 @@ +// Public video-generation helpers and types for provider plugins. + +export type { + GeneratedVideoAsset, + VideoGenerationProvider, + VideoGenerationProviderCapabilities, + VideoGenerationRequest, + VideoGenerationResult, + VideoGenerationSourceImage, +} from "../video-generation/types.js"; diff --git a/src/plugins/captured-registration.ts b/src/plugins/captured-registration.ts index fd2c359b463..0f2bfa73dd8 100644 --- a/src/plugins/captured-registration.ts +++ b/src/plugins/captured-registration.ts @@ -5,6 +5,7 @@ import type { OpenClawPluginApi, ProviderPlugin, SpeechProviderPlugin, + VideoGenerationProviderPlugin, WebSearchProviderPlugin, } from "./types.js"; @@ -14,6 +15,7 @@ export type CapturedPluginRegistration = { speechProviders: SpeechProviderPlugin[]; mediaUnderstandingProviders: MediaUnderstandingProviderPlugin[]; imageGenerationProviders: ImageGenerationProviderPlugin[]; + videoGenerationProviders: VideoGenerationProviderPlugin[]; webSearchProviders: WebSearchProviderPlugin[]; tools: AnyAgentTool[]; }; @@ -23,6 +25,7 @@ export function createCapturedPluginRegistration(): CapturedPluginRegistration { const speechProviders: SpeechProviderPlugin[] = []; const mediaUnderstandingProviders: MediaUnderstandingProviderPlugin[] = []; const imageGenerationProviders: ImageGenerationProviderPlugin[] = []; + const videoGenerationProviders: VideoGenerationProviderPlugin[] = []; const webSearchProviders: WebSearchProviderPlugin[] = []; const tools: AnyAgentTool[] = []; @@ -31,6 +34,7 @@ export function createCapturedPluginRegistration(): CapturedPluginRegistration { speechProviders, mediaUnderstandingProviders, imageGenerationProviders, + videoGenerationProviders, webSearchProviders, tools, api: { @@ -46,6 +50,9 @@ export function createCapturedPluginRegistration(): CapturedPluginRegistration { registerImageGenerationProvider(provider: ImageGenerationProviderPlugin) { imageGenerationProviders.push(provider); }, + registerVideoGenerationProvider(provider: VideoGenerationProviderPlugin) { + videoGenerationProviders.push(provider); + }, registerWebSearchProvider(provider: WebSearchProviderPlugin) { webSearchProviders.push(provider); }, diff --git a/src/plugins/contracts/registry.contract.test.ts b/src/plugins/contracts/registry.contract.test.ts index 6215a366777..fb32d20b53b 100644 --- a/src/plugins/contracts/registry.contract.test.ts +++ b/src/plugins/contracts/registry.contract.test.ts @@ -182,6 +182,7 @@ describe("plugin contract registry", () => { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: ["exa"], toolNames: [], }); @@ -190,6 +191,7 @@ describe("plugin contract registry", () => { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: ["firecrawl"], toolNames: ["firecrawl_search", "firecrawl_scrape"], }); @@ -198,6 +200,7 @@ describe("plugin contract registry", () => { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: ["tavily"], toolNames: ["tavily_search", "tavily_extract"], }); @@ -209,6 +212,7 @@ describe("plugin contract registry", () => { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: ["fal"], + videoGenerationProviderIds: [], webSearchProviderIds: [], }); expect(findRegistrationForPlugin("google")).toMatchObject({ @@ -216,6 +220,7 @@ describe("plugin contract registry", () => { speechProviderIds: [], mediaUnderstandingProviderIds: ["google"], imageGenerationProviderIds: ["google"], + videoGenerationProviderIds: [], webSearchProviderIds: ["gemini"], }); expect(findRegistrationForPlugin("openai")).toMatchObject({ @@ -223,18 +228,21 @@ describe("plugin contract registry", () => { speechProviderIds: ["openai"], mediaUnderstandingProviderIds: ["openai"], imageGenerationProviderIds: ["openai"], + videoGenerationProviderIds: [], }); expect(findRegistrationForPlugin("elevenlabs")).toMatchObject({ providerIds: [], speechProviderIds: ["elevenlabs"], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], }); expect(findRegistrationForPlugin("microsoft")).toMatchObject({ providerIds: [], speechProviderIds: ["microsoft"], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], }); }); diff --git a/src/plugins/contracts/registry.ts b/src/plugins/contracts/registry.ts index 17bb9d5a91c..621ebb209d9 100644 --- a/src/plugins/contracts/registry.ts +++ b/src/plugins/contracts/registry.ts @@ -75,6 +75,7 @@ type PluginRegistrationContractEntry = { speechProviderIds: string[]; mediaUnderstandingProviderIds: string[]; imageGenerationProviderIds: string[]; + videoGenerationProviderIds: string[]; webSearchProviderIds: string[]; toolNames: string[]; }; @@ -419,6 +420,10 @@ function upsertPluginRegistrationContractEntry( existing.imageGenerationProviderIds, next.imageGenerationProviderIds, ); + existing.videoGenerationProviderIds = mergeIds( + existing.videoGenerationProviderIds, + next.videoGenerationProviderIds, + ); existing.webSearchProviderIds = mergeIds( existing.webSearchProviderIds, next.webSearchProviderIds, @@ -443,6 +448,7 @@ function mergeProviderContractRegistrations( speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: [], toolNames: [], }); @@ -464,6 +470,9 @@ function loadPluginRegistrationContractRegistry(): PluginRegistrationContractEnt imageGenerationProviderIds: captured.imageGenerationProviders.map( (provider) => provider.id, ), + videoGenerationProviderIds: captured.videoGenerationProviders.map( + (provider) => provider.id, + ), webSearchProviderIds: captured.webSearchProviders.map((provider) => provider.id), toolNames: captured.tools.map((tool) => tool.name), }); diff --git a/src/plugins/contracts/shape.contract.test.ts b/src/plugins/contracts/shape.contract.test.ts index c5726c4fd0b..455d1c8de26 100644 --- a/src/plugins/contracts/shape.contract.test.ts +++ b/src/plugins/contracts/shape.contract.test.ts @@ -20,6 +20,7 @@ function createPluginRecord(id: string, name: string): PluginRecord { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: [], gatewayMethods: [], cliCommands: [], diff --git a/src/plugins/hooks.test-helpers.ts b/src/plugins/hooks.test-helpers.ts index 559f70a1dc7..dfdceb2b100 100644 --- a/src/plugins/hooks.test-helpers.ts +++ b/src/plugins/hooks.test-helpers.ts @@ -20,6 +20,7 @@ export function createMockPluginRegistry( speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: [], gatewayMethods: [], cliCommands: [], @@ -45,6 +46,7 @@ export function createMockPluginRegistry( speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], httpRoutes: [], gatewayHandlers: {}, diff --git a/src/plugins/loader.ts b/src/plugins/loader.ts index 1472cd2cfee..e52b054f034 100644 --- a/src/plugins/loader.ts +++ b/src/plugins/loader.ts @@ -351,6 +351,7 @@ function createPluginRecord(params: { speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: [], gatewayMethods: [], cliCommands: [], diff --git a/src/plugins/registry-empty.ts b/src/plugins/registry-empty.ts index fa78dac7536..d717d2f298e 100644 --- a/src/plugins/registry-empty.ts +++ b/src/plugins/registry-empty.ts @@ -12,6 +12,7 @@ export function createEmptyPluginRegistry(): PluginRegistry { speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], gatewayHandlers: {}, httpRoutes: [], diff --git a/src/plugins/registry.ts b/src/plugins/registry.ts index 10f7c1f520b..f022dbf0671 100644 --- a/src/plugins/registry.ts +++ b/src/plugins/registry.ts @@ -26,6 +26,7 @@ import { } from "./types.js"; import type { ImageGenerationProviderPlugin, + VideoGenerationProviderPlugin, OpenClawPluginApi, OpenClawPluginChannelRegistration, OpenClawPluginCliRegistrar, @@ -123,6 +124,8 @@ export type PluginMediaUnderstandingProviderRegistration = PluginOwnedProviderRegistration; export type PluginImageGenerationProviderRegistration = PluginOwnedProviderRegistration; +export type PluginVideoGenerationProviderRegistration = + PluginOwnedProviderRegistration; export type PluginWebSearchProviderRegistration = PluginOwnedProviderRegistration; @@ -182,6 +185,7 @@ export type PluginRecord = { speechProviderIds: string[]; mediaUnderstandingProviderIds: string[]; imageGenerationProviderIds: string[]; + videoGenerationProviderIds: string[]; webSearchProviderIds: string[]; gatewayMethods: string[]; cliCommands: string[]; @@ -205,6 +209,7 @@ export type PluginRegistry = { speechProviders: PluginSpeechProviderRegistration[]; mediaUnderstandingProviders: PluginMediaUnderstandingProviderRegistration[]; imageGenerationProviders: PluginImageGenerationProviderRegistration[]; + videoGenerationProviders: PluginVideoGenerationProviderRegistration[]; webSearchProviders: PluginWebSearchProviderRegistration[]; gatewayHandlers: GatewayRequestHandlers; httpRoutes: PluginHttpRouteRegistration[]; @@ -644,6 +649,19 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) { }); }; + const registerVideoGenerationProvider = ( + record: PluginRecord, + provider: VideoGenerationProviderPlugin, + ) => { + registerUniqueProviderLike({ + record, + provider, + kindLabel: "video-generation provider", + registrations: registry.videoGenerationProviders, + ownedIds: record.videoGenerationProviderIds, + }); + }; + const registerWebSearchProvider = (record: PluginRecord, provider: WebSearchProviderPlugin) => { registerUniqueProviderLike({ record, @@ -918,6 +936,10 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) { registrationMode === "full" ? (provider) => registerImageGenerationProvider(record, provider) : () => {}, + registerVideoGenerationProvider: + registrationMode === "full" + ? (provider) => registerVideoGenerationProvider(record, provider) + : () => {}, registerWebSearchProvider: registrationMode === "full" ? (provider) => registerWebSearchProvider(record, provider) diff --git a/src/plugins/status.test-helpers.ts b/src/plugins/status.test-helpers.ts index 0704e334fc5..8e284466aec 100644 --- a/src/plugins/status.test-helpers.ts +++ b/src/plugins/status.test-helpers.ts @@ -47,6 +47,7 @@ export function createPluginRecord( speechProviderIds: [], mediaUnderstandingProviderIds: [], imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: [], gatewayMethods: [], cliCommands: [], @@ -110,6 +111,7 @@ export function createPluginLoadResult( speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], tools: [], hooks: [], diff --git a/src/plugins/status.test.ts b/src/plugins/status.test.ts index 0a9c599cc3e..fe63e51b9e6 100644 --- a/src/plugins/status.test.ts +++ b/src/plugins/status.test.ts @@ -1,13 +1,4 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import { - createCompatibilityNotice, - createCustomHook, - createPluginLoadResult, - createPluginRecord, - createTypedHook, - HOOK_ONLY_MESSAGE, - LEGACY_BEFORE_AGENT_START_MESSAGE, -} from "./status.test-helpers.js"; const loadConfigMock = vi.fn(); const loadOpenClawPluginsMock = vi.fn(); @@ -36,22 +27,32 @@ vi.mock("../agents/workspace.js", () => ({ resolveDefaultAgentWorkspaceDir: () => "/default-workspace", })); -function setPluginLoadResult(overrides: Partial>) { - loadOpenClawPluginsMock.mockReturnValue( - createPluginLoadResult({ - plugins: [], - ...overrides, - }), - ); -} - describe("buildPluginStatusReport", () => { beforeEach(async () => { vi.resetModules(); loadConfigMock.mockReset(); loadOpenClawPluginsMock.mockReset(); loadConfigMock.mockReturnValue({}); - setPluginLoadResult({ plugins: [] }); + loadOpenClawPluginsMock.mockReturnValue({ + plugins: [], + diagnostics: [], + channels: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [], + channelSetups: [], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], + }); ({ buildAllPluginInspectReports, buildPluginCompatibilityNotices, @@ -82,17 +83,52 @@ describe("buildPluginStatusReport", () => { }); it("normalizes bundled plugin versions to the core base release", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "whatsapp", name: "WhatsApp", description: "Bundled channel plugin", version: "2026.3.22", + source: "/tmp/whatsapp/index.ts", origin: "bundled", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], channelIds: ["whatsapp"], - }), + providerIds: [], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, + hookCount: 0, + configSchema: false, + }, ], + diagnostics: [], + channels: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [], + channelSetups: [], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); const report = buildPluginStatusReport({ @@ -119,21 +155,58 @@ describe("buildPluginStatusReport", () => { }, }, }); - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "google", name: "Google", description: "Google provider plugin", + source: "/tmp/google/index.ts", origin: "bundled", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], providerIds: ["google"], + speechProviderIds: [], mediaUnderstandingProviderIds: ["google"], imageGenerationProviderIds: ["google"], + videoGenerationProviderIds: [], webSearchProviderIds: ["google"], - }), + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, + hookCount: 0, + configSchema: false, + }, ], diagnostics: [{ level: "warn", pluginId: "google", message: "watch this surface" }], - typedHooks: [createTypedHook({ pluginId: "google", hookName: "before_agent_start" })], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [ + { + pluginId: "google", + hookName: "before_agent_start", + handler: () => undefined, + source: "/tmp/google/index.ts", + }, + ], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); const inspect = buildPluginInspectReport({ id: "google" }); @@ -149,7 +222,13 @@ describe("buildPluginStatusReport", () => { ]); expect(inspect?.usesLegacyBeforeAgentStart).toBe(true); expect(inspect?.compatibility).toEqual([ - createCompatibilityNotice({ pluginId: "google", code: "legacy-before-agent-start" }), + { + pluginId: "google", + code: "legacy-before-agent-start", + severity: "warn", + message: + "still uses legacy before_agent_start; keep regression coverage on this plugin, and prefer before_model_resolve/before_prompt_build for new work.", + }, ]); expect(inspect?.policy).toEqual({ allowPromptInjection: false, @@ -163,25 +242,94 @@ describe("buildPluginStatusReport", () => { }); it("builds inspect reports for every loaded plugin", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "lca", name: "LCA", description: "Legacy hook plugin", + source: "/tmp/lca/index.ts", + origin: "workspace", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], + providerIds: [], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, hookCount: 1, - }), - createPluginRecord({ + configSchema: false, + }, + { id: "microsoft", name: "Microsoft", description: "Hybrid capability plugin", + source: "/tmp/microsoft/index.ts", origin: "bundled", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], providerIds: ["microsoft"], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], webSearchProviderIds: ["microsoft"], - }), + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, + hookCount: 0, + configSchema: false, + }, ], - hooks: [createCustomHook({ pluginId: "lca", events: ["message"] })], - typedHooks: [createTypedHook({ pluginId: "lca", hookName: "before_agent_start" })], + diagnostics: [], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [ + { + pluginId: "lca", + events: ["message"], + entry: { + hook: { + name: "legacy", + handler: () => undefined, + }, + }, + }, + ], + typedHooks: [ + { + pluginId: "lca", + hookName: "before_agent_start", + handler: () => undefined, + source: "/tmp/lca/index.ts", + }, + ], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); const inspect = buildAllPluginInspectReports(); @@ -196,58 +344,221 @@ describe("buildPluginStatusReport", () => { }); it("builds compatibility warnings for legacy compatibility paths", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "lca", name: "LCA", description: "Legacy hook plugin", + source: "/tmp/lca/index.ts", + origin: "workspace", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], + providerIds: [], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, hookCount: 1, - }), + configSchema: false, + }, ], - typedHooks: [createTypedHook({ pluginId: "lca", hookName: "before_agent_start" })], + diagnostics: [], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [ + { + pluginId: "lca", + hookName: "before_agent_start", + handler: () => undefined, + source: "/tmp/lca/index.ts", + }, + ], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); expect(buildPluginCompatibilityWarnings()).toEqual([ - `lca ${LEGACY_BEFORE_AGENT_START_MESSAGE}`, - `lca ${HOOK_ONLY_MESSAGE}`, + "lca still uses legacy before_agent_start; keep regression coverage on this plugin, and prefer before_model_resolve/before_prompt_build for new work.", + "lca is hook-only. This remains a supported compatibility path, but it has not migrated to explicit capability registration yet.", ]); }); it("builds structured compatibility notices with deterministic ordering", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "hook-only", name: "Hook Only", + description: "", + source: "/tmp/hook-only/index.ts", + origin: "workspace", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], + providerIds: [], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, hookCount: 1, - }), - createPluginRecord({ + configSchema: false, + }, + { id: "legacy-only", name: "Legacy Only", + description: "", + source: "/tmp/legacy-only/index.ts", + origin: "workspace", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], providerIds: ["legacy-only"], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, hookCount: 1, - }), + configSchema: false, + }, ], - hooks: [createCustomHook({ pluginId: "hook-only", events: ["message"] })], - typedHooks: [createTypedHook({ pluginId: "legacy-only", hookName: "before_agent_start" })], + diagnostics: [], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [ + { + pluginId: "hook-only", + events: ["message"], + entry: { + hook: { + name: "legacy", + handler: () => undefined, + }, + }, + }, + ], + typedHooks: [ + { + pluginId: "legacy-only", + hookName: "before_agent_start", + handler: () => undefined, + source: "/tmp/legacy-only/index.ts", + }, + ], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); expect(buildPluginCompatibilityNotices()).toEqual([ - createCompatibilityNotice({ pluginId: "hook-only", code: "hook-only" }), - createCompatibilityNotice({ pluginId: "legacy-only", code: "legacy-before-agent-start" }), + { + pluginId: "hook-only", + code: "hook-only", + severity: "info", + message: + "is hook-only. This remains a supported compatibility path, but it has not migrated to explicit capability registration yet.", + }, + { + pluginId: "legacy-only", + code: "legacy-before-agent-start", + severity: "warn", + message: + "still uses legacy before_agent_start; keep regression coverage on this plugin, and prefer before_model_resolve/before_prompt_build for new work.", + }, ]); }); it("returns no compatibility warnings for modern capability plugins", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "modern", name: "Modern", + description: "", + source: "/tmp/modern/index.ts", + origin: "workspace", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], providerIds: ["modern"], - }), + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, + hookCount: 0, + configSchema: false, + }, ], + diagnostics: [], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); expect(buildPluginCompatibilityNotices()).toEqual([]); @@ -255,19 +566,55 @@ describe("buildPluginStatusReport", () => { }); it("populates bundleCapabilities from plugin record", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "claude-bundle", name: "Claude Bundle", description: "A bundle plugin with skills and commands", source: "/tmp/claude-bundle/.claude-plugin/plugin.json", + origin: "workspace", + enabled: true, + status: "loaded", format: "bundle", bundleFormat: "claude", bundleCapabilities: ["skills", "commands", "agents", "settings"], rootDir: "/tmp/claude-bundle", - }), + toolNames: [], + hookNames: [], + channelIds: [], + providerIds: [], + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, + hookCount: 0, + configSchema: false, + }, ], + diagnostics: [], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); const inspect = buildPluginInspectReport({ id: "claude-bundle" }); @@ -279,15 +626,51 @@ describe("buildPluginStatusReport", () => { }); it("returns empty bundleCapabilities and mcpServers for non-bundle plugins", () => { - setPluginLoadResult({ + loadOpenClawPluginsMock.mockReturnValue({ plugins: [ - createPluginRecord({ + { id: "plain-plugin", name: "Plain Plugin", description: "A regular plugin", + source: "/tmp/plain-plugin/index.ts", + origin: "workspace", + enabled: true, + status: "loaded", + toolNames: [], + hookNames: [], + channelIds: [], providerIds: ["plain"], - }), + speechProviderIds: [], + mediaUnderstandingProviderIds: [], + imageGenerationProviderIds: [], + videoGenerationProviderIds: [], + webSearchProviderIds: [], + gatewayMethods: [], + cliCommands: [], + services: [], + commands: [], + httpRoutes: 0, + hookCount: 0, + configSchema: false, + }, ], + diagnostics: [], + channels: [], + channelSetups: [], + providers: [], + speechProviders: [], + mediaUnderstandingProviders: [], + imageGenerationProviders: [], + videoGenerationProviders: [], + webSearchProviders: [], + tools: [], + hooks: [], + typedHooks: [], + httpRoutes: [], + gatewayHandlers: {}, + cliRegistrars: [], + services: [], + commands: [], }); const inspect = buildPluginInspectReport({ id: "plain-plugin" }); @@ -298,18 +681,27 @@ describe("buildPluginStatusReport", () => { }); it("formats and summarizes compatibility notices", () => { - const notice = createCompatibilityNotice({ + const notice = { pluginId: "legacy-plugin", - code: "legacy-before-agent-start", - }); + code: "legacy-before-agent-start" as const, + severity: "warn" as const, + message: + "still uses legacy before_agent_start; keep regression coverage on this plugin, and prefer before_model_resolve/before_prompt_build for new work.", + }; expect(formatPluginCompatibilityNotice(notice)).toBe( - `legacy-plugin ${LEGACY_BEFORE_AGENT_START_MESSAGE}`, + "legacy-plugin still uses legacy before_agent_start; keep regression coverage on this plugin, and prefer before_model_resolve/before_prompt_build for new work.", ); expect( summarizePluginCompatibility([ notice, - createCompatibilityNotice({ pluginId: "legacy-plugin", code: "hook-only" }), + { + pluginId: "legacy-plugin", + code: "hook-only", + severity: "info", + message: + "is hook-only. This remains a supported compatibility path, but it has not migrated to explicit capability registration yet.", + }, ]), ).toEqual({ noticeCount: 2, diff --git a/src/plugins/status.ts b/src/plugins/status.ts index 7ad0bcd8347..1dc29eb014b 100644 --- a/src/plugins/status.ts +++ b/src/plugins/status.ts @@ -21,6 +21,7 @@ export type PluginCapabilityKind = | "speech" | "media-understanding" | "image-generation" + | "video-generation" | "web-search" | "channel"; @@ -165,6 +166,7 @@ function buildCapabilityEntries(plugin: PluginRegistry["plugins"][number]) { { kind: "speech" as const, ids: plugin.speechProviderIds }, { kind: "media-understanding" as const, ids: plugin.mediaUnderstandingProviderIds }, { kind: "image-generation" as const, ids: plugin.imageGenerationProviderIds }, + { kind: "video-generation" as const, ids: plugin.videoGenerationProviderIds }, { kind: "web-search" as const, ids: plugin.webSearchProviderIds }, { kind: "channel" as const, ids: plugin.channelIds }, ].filter((entry) => entry.ids.length > 0); diff --git a/src/plugins/types.ts b/src/plugins/types.ts index 1db03c29979..b97e9d0cf7e 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -40,6 +40,7 @@ import type { SpeechTelephonySynthesisResult, SpeechVoiceOption, } from "../tts/provider-types.js"; +import type { VideoGenerationProvider } from "../video-generation/types.js"; import type { WizardPrompter } from "../wizard/prompts.js"; import type { SecretInputMode } from "./provider-auth-types.js"; import type { createVpsAwareOAuthHandlers } from "./provider-oauth-flow.js"; @@ -950,6 +951,7 @@ export type PluginSpeechProviderEntry = SpeechProviderPlugin & { export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider; export type ImageGenerationProviderPlugin = ImageGenerationProvider; +export type VideoGenerationProviderPlugin = VideoGenerationProvider; export type OpenClawPluginGatewayMethod = { method: string; @@ -1352,6 +1354,8 @@ export type OpenClawPluginApi = { registerMediaUnderstandingProvider: (provider: MediaUnderstandingProviderPlugin) => void; /** Register an image generation provider (image generation capability). */ registerImageGenerationProvider: (provider: ImageGenerationProviderPlugin) => void; + /** Register a video generation provider (video generation capability). */ + registerVideoGenerationProvider: (provider: VideoGenerationProviderPlugin) => void; /** Register a web search provider (web search capability). */ registerWebSearchProvider: (provider: WebSearchProviderPlugin) => void; registerInteractiveHandler: (registration: PluginInteractiveHandlerRegistration) => void; diff --git a/src/test-utils/channel-plugins.ts b/src/test-utils/channel-plugins.ts index 713d331335a..3e1a844d9d6 100644 --- a/src/test-utils/channel-plugins.ts +++ b/src/test-utils/channel-plugins.ts @@ -29,6 +29,7 @@ export const createTestRegistry = (channels: TestChannelRegistration[] = []): Pl speechProviders: [], mediaUnderstandingProviders: [], imageGenerationProviders: [], + videoGenerationProviders: [], webSearchProviders: [], gatewayHandlers: {}, httpRoutes: [], diff --git a/src/video-generation/provider-registry.ts b/src/video-generation/provider-registry.ts new file mode 100644 index 00000000000..c7caacbe9fe --- /dev/null +++ b/src/video-generation/provider-registry.ts @@ -0,0 +1,80 @@ +import { normalizeProviderId } from "../agents/model-selection.js"; +import type { OpenClawConfig } from "../config/config.js"; +import { isBlockedObjectKey } from "../infra/prototype-keys.js"; +import { loadOpenClawPlugins } from "../plugins/loader.js"; +import { getActivePluginRegistry, getActivePluginRegistryKey } from "../plugins/runtime.js"; +import type { VideoGenerationProviderPlugin } from "../plugins/types.js"; + +const BUILTIN_VIDEO_GENERATION_PROVIDERS: readonly VideoGenerationProviderPlugin[] = []; +const UNSAFE_PROVIDER_IDS = new Set(["__proto__", "constructor", "prototype"]); + +function normalizeVideoGenerationProviderId(id: string | undefined): string | undefined { + const normalized = normalizeProviderId(id ?? ""); + if (!normalized || isBlockedObjectKey(normalized)) { + return undefined; + } + return normalized; +} + +function isSafeVideoGenerationProviderId(id: string | undefined): id is string { + return Boolean(id && !UNSAFE_PROVIDER_IDS.has(id)); +} + +function resolvePluginVideoGenerationProviders( + cfg?: OpenClawConfig, +): VideoGenerationProviderPlugin[] { + const active = getActivePluginRegistry(); + const registry = + (active?.videoGenerationProviders?.length ?? 0) > 0 || getActivePluginRegistryKey() || !cfg + ? active + : loadOpenClawPlugins({ config: cfg }); + return registry?.videoGenerationProviders?.map((entry) => entry.provider) ?? []; +} + +function buildProviderMaps(cfg?: OpenClawConfig): { + canonical: Map; + aliases: Map; +} { + const canonical = new Map(); + const aliases = new Map(); + const register = (provider: VideoGenerationProviderPlugin) => { + const id = normalizeVideoGenerationProviderId(provider.id); + if (!isSafeVideoGenerationProviderId(id)) { + return; + } + canonical.set(id, provider); + aliases.set(id, provider); + for (const alias of provider.aliases ?? []) { + const normalizedAlias = normalizeVideoGenerationProviderId(alias); + if (isSafeVideoGenerationProviderId(normalizedAlias)) { + aliases.set(normalizedAlias, provider); + } + } + }; + + for (const provider of BUILTIN_VIDEO_GENERATION_PROVIDERS) { + register(provider); + } + for (const provider of resolvePluginVideoGenerationProviders(cfg)) { + register(provider); + } + + return { canonical, aliases }; +} + +export function listVideoGenerationProviders( + cfg?: OpenClawConfig, +): VideoGenerationProviderPlugin[] { + return [...buildProviderMaps(cfg).canonical.values()]; +} + +export function getVideoGenerationProvider( + providerId: string | undefined, + cfg?: OpenClawConfig, +): VideoGenerationProviderPlugin | undefined { + const normalized = normalizeVideoGenerationProviderId(providerId); + if (!normalized) { + return undefined; + } + return buildProviderMaps(cfg).aliases.get(normalized); +} diff --git a/src/video-generation/runtime.ts b/src/video-generation/runtime.ts new file mode 100644 index 00000000000..696662a98fa --- /dev/null +++ b/src/video-generation/runtime.ts @@ -0,0 +1,179 @@ +import type { AuthProfileStore } from "../agents/auth-profiles.js"; +import { describeFailoverError, isFailoverError } from "../agents/failover-error.js"; +import type { FallbackAttempt } from "../agents/model-fallback.types.js"; +import type { OpenClawConfig } from "../config/config.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; +import { getVideoGenerationProvider, listVideoGenerationProviders } from "./provider-registry.js"; +import type { GeneratedVideoAsset, VideoGenerationResult } from "./types.js"; + +const log = createSubsystemLogger("video-generation"); + +export type GenerateVideoParams = { + cfg: OpenClawConfig; + prompt: string; + agentDir?: string; + authStore?: AuthProfileStore; + modelOverride?: string; + durationSeconds?: number; + aspectRatio?: string; + resolution?: string; + seed?: number; + watermark?: boolean; + firstFrameImageUrl?: string; + lastFrameImageUrl?: string; + providerOptions?: Record; +}; + +export type GenerateVideoRuntimeResult = { + videos: GeneratedVideoAsset[]; + provider: string; + model: string; + attempts: FallbackAttempt[]; + metadata?: Record; +}; + +function parseModelRef(raw: string | undefined): { provider: string; model: string } | null { + const trimmed = raw?.trim(); + if (!trimmed) { + return null; + } + const slashIndex = trimmed.indexOf("/"); + if (slashIndex <= 0 || slashIndex === trimmed.length - 1) { + return null; + } + return { + provider: trimmed.slice(0, slashIndex).trim(), + model: trimmed.slice(slashIndex + 1).trim(), + }; +} + +function resolveVideoGenerationCandidates(params: { + cfg: OpenClawConfig; + modelOverride?: string; +}): Array<{ provider: string; model: string }> { + const candidates: Array<{ provider: string; model: string }> = []; + const seen = new Set(); + const add = (raw: string | undefined) => { + const parsed = parseModelRef(raw); + if (!parsed) { + return; + } + const key = `${parsed.provider}/${parsed.model}`; + if (seen.has(key)) { + return; + } + seen.add(key); + candidates.push(parsed); + }; + + add(params.modelOverride); + + // Fall back to first registered provider's default model + if (candidates.length === 0) { + const providers = listVideoGenerationProviders(params.cfg); + for (const provider of providers) { + if (provider.defaultModel) { + add(`${provider.id}/${provider.defaultModel}`); + break; + } + } + } + + return candidates; +} + +function throwVideoGenerationFailure(params: { + attempts: FallbackAttempt[]; + lastError: unknown; +}): never { + if (params.attempts.length <= 1 && params.lastError) { + throw params.lastError; + } + const summary = + params.attempts.length > 0 + ? params.attempts + .map((attempt) => `${attempt.provider}/${attempt.model}: ${attempt.error}`) + .join(" | ") + : "unknown"; + throw new Error(`All video generation models failed (${params.attempts.length}): ${summary}`, { + cause: params.lastError instanceof Error ? params.lastError : undefined, + }); +} + +export function listRuntimeVideoGenerationProviders(params?: { config?: OpenClawConfig }) { + return listVideoGenerationProviders(params?.config); +} + +export async function generateVideo( + params: GenerateVideoParams, +): Promise { + const candidates = resolveVideoGenerationCandidates({ + cfg: params.cfg, + modelOverride: params.modelOverride, + }); + if (candidates.length === 0) { + throw new Error( + "No video-generation model configured. Install a provider plugin that supports video generation (e.g. @openclaw/byteplus-provider).", + ); + } + + const attempts: FallbackAttempt[] = []; + let lastError: unknown; + + for (const candidate of candidates) { + const provider = getVideoGenerationProvider(candidate.provider, params.cfg); + if (!provider) { + const error = `No video-generation provider registered for ${candidate.provider}`; + attempts.push({ provider: candidate.provider, model: candidate.model, error }); + lastError = new Error(error); + continue; + } + + try { + const result: VideoGenerationResult = await provider.generateVideo({ + provider: candidate.provider, + model: candidate.model, + prompt: params.prompt, + cfg: params.cfg, + agentDir: params.agentDir, + authStore: params.authStore, + durationSeconds: params.durationSeconds, + aspectRatio: params.aspectRatio, + resolution: params.resolution, + seed: params.seed, + watermark: params.watermark, + firstFrameImage: params.firstFrameImageUrl + ? { url: params.firstFrameImageUrl, role: "first_frame" } + : undefined, + lastFrameImage: params.lastFrameImageUrl + ? { url: params.lastFrameImageUrl, role: "last_frame" } + : undefined, + providerOptions: params.providerOptions, + }); + if (!Array.isArray(result.videos) || result.videos.length === 0) { + throw new Error("Video generation provider returned no videos."); + } + return { + videos: result.videos, + provider: candidate.provider, + model: result.model ?? candidate.model, + attempts, + metadata: result.metadata, + }; + } catch (err) { + lastError = err; + const described = isFailoverError(err) ? describeFailoverError(err) : undefined; + attempts.push({ + provider: candidate.provider, + model: candidate.model, + error: described?.message ?? (err instanceof Error ? err.message : String(err)), + reason: described?.reason, + status: described?.status, + code: described?.code, + }); + log.debug(`video-generation candidate failed: ${candidate.provider}/${candidate.model}`); + } + } + + throwVideoGenerationFailure({ attempts, lastError }); +} diff --git a/src/video-generation/types.ts b/src/video-generation/types.ts new file mode 100644 index 00000000000..1be4ae25624 --- /dev/null +++ b/src/video-generation/types.ts @@ -0,0 +1,62 @@ +import type { AuthProfileStore } from "../agents/auth-profiles.js"; +import type { OpenClawConfig } from "../config/config.js"; + +export type GeneratedVideoAsset = { + buffer: Buffer; + mimeType: string; + fileName?: string; + durationSeconds?: number; + metadata?: Record; +}; + +export type VideoGenerationSourceImage = { + url?: string; + buffer?: Buffer; + mimeType?: string; + role: "first_frame" | "last_frame"; +}; + +export type VideoGenerationRequest = { + provider: string; + model: string; + prompt: string; + cfg: OpenClawConfig; + agentDir?: string; + authStore?: AuthProfileStore; + timeoutMs?: number; + durationSeconds?: number; + aspectRatio?: string; + resolution?: string; + seed?: number; + watermark?: boolean; + firstFrameImage?: VideoGenerationSourceImage; + lastFrameImage?: VideoGenerationSourceImage; + /** Provider-specific options (e.g. camerafixed, draft). */ + providerOptions?: Record; +}; + +export type VideoGenerationResult = { + videos: GeneratedVideoAsset[]; + model?: string; + metadata?: Record; +}; + +export type VideoGenerationProviderCapabilities = { + supportsDuration?: boolean; + supportsAspectRatio?: boolean; + supportsResolution?: boolean; + maxDurationSeconds?: number; + minDurationSeconds?: number; + aspectRatios?: string[]; + resolutions?: string[]; +}; + +export type VideoGenerationProvider = { + id: string; + aliases?: string[]; + label?: string; + defaultModel?: string; + models?: string[]; + capabilities: VideoGenerationProviderCapabilities; + generateVideo: (req: VideoGenerationRequest) => Promise; +}; diff --git a/test/helpers/extensions/plugin-api.ts b/test/helpers/extensions/plugin-api.ts index 9fe8ac80ed3..eb2442bc26e 100644 --- a/test/helpers/extensions/plugin-api.ts +++ b/test/helpers/extensions/plugin-api.ts @@ -18,6 +18,7 @@ export function createTestPluginApi(api: TestPluginApiInput): OpenClawPluginApi registerSpeechProvider() {}, registerMediaUnderstandingProvider() {}, registerImageGenerationProvider() {}, + registerVideoGenerationProvider() {}, registerWebSearchProvider() {}, registerInteractiveHandler() {}, onConversationBindingResolved() {}, diff --git a/test/setup.ts b/test/setup.ts index e37fd124a55..1ec07cbe1fa 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -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([ {