mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-28 10:22:32 +00:00
refactor: plugin-own speech provider config
This commit is contained in:
@@ -244,7 +244,7 @@
|
||||
"exportName": "CliBackendPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1292,
|
||||
"line": 1305,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -388,7 +388,7 @@
|
||||
"exportName": "MediaUnderstandingProviderPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 951,
|
||||
"line": 964,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -406,7 +406,7 @@
|
||||
"exportName": "OpenClawPluginApi",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1336,
|
||||
"line": 1349,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -415,7 +415,7 @@
|
||||
"exportName": "OpenClawPluginConfigSchema",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 88,
|
||||
"line": 94,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -424,7 +424,7 @@
|
||||
"exportName": "PluginLogger",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 59,
|
||||
"line": 65,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -442,7 +442,7 @@
|
||||
"exportName": "ProviderAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 155,
|
||||
"line": 161,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -451,7 +451,7 @@
|
||||
"exportName": "ProviderAuthResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 140,
|
||||
"line": 146,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -460,7 +460,7 @@
|
||||
"exportName": "ProviderRuntimeModel",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 295,
|
||||
"line": 301,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -514,7 +514,7 @@
|
||||
"exportName": "SpeechProviderPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 933,
|
||||
"line": 939,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3405,7 +3405,7 @@
|
||||
"exportName": "MediaUnderstandingProviderPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 951,
|
||||
"line": 964,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3423,7 +3423,7 @@
|
||||
"exportName": "OpenClawPluginApi",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1336,
|
||||
"line": 1349,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3432,7 +3432,7 @@
|
||||
"exportName": "OpenClawPluginCommandDefinition",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1068,
|
||||
"line": 1081,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3441,7 +3441,7 @@
|
||||
"exportName": "OpenClawPluginConfigSchema",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 88,
|
||||
"line": 94,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3450,7 +3450,7 @@
|
||||
"exportName": "OpenClawPluginDefinition",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1318,
|
||||
"line": 1331,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3459,7 +3459,7 @@
|
||||
"exportName": "OpenClawPluginService",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1285,
|
||||
"line": 1298,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3468,7 +3468,7 @@
|
||||
"exportName": "OpenClawPluginServiceContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1277,
|
||||
"line": 1290,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3477,7 +3477,7 @@
|
||||
"exportName": "OpenClawPluginToolContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 103,
|
||||
"line": 109,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3486,7 +3486,7 @@
|
||||
"exportName": "OpenClawPluginToolFactory",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 120,
|
||||
"line": 126,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3495,7 +3495,7 @@
|
||||
"exportName": "PluginCommandContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 966,
|
||||
"line": 979,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3504,7 +3504,7 @@
|
||||
"exportName": "PluginInteractiveTelegramHandlerContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1097,
|
||||
"line": 1110,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3513,7 +3513,7 @@
|
||||
"exportName": "PluginLogger",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 59,
|
||||
"line": 65,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3531,7 +3531,7 @@
|
||||
"exportName": "ProviderAugmentModelCatalogContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 571,
|
||||
"line": 577,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3540,7 +3540,7 @@
|
||||
"exportName": "ProviderAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 155,
|
||||
"line": 161,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3549,7 +3549,7 @@
|
||||
"exportName": "ProviderAuthDoctorHintContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 446,
|
||||
"line": 452,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3558,7 +3558,7 @@
|
||||
"exportName": "ProviderAuthMethod",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 233,
|
||||
"line": 239,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3567,7 +3567,7 @@
|
||||
"exportName": "ProviderAuthMethodNonInteractiveContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 217,
|
||||
"line": 223,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3576,7 +3576,7 @@
|
||||
"exportName": "ProviderAuthResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 140,
|
||||
"line": 146,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3585,7 +3585,7 @@
|
||||
"exportName": "ProviderBuildMissingAuthMessageContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 499,
|
||||
"line": 505,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3594,7 +3594,7 @@
|
||||
"exportName": "ProviderBuiltInModelSuppressionContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 515,
|
||||
"line": 521,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3603,7 +3603,7 @@
|
||||
"exportName": "ProviderBuiltInModelSuppressionResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 524,
|
||||
"line": 530,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3612,7 +3612,7 @@
|
||||
"exportName": "ProviderCacheTtlEligibilityContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 487,
|
||||
"line": 493,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3621,7 +3621,7 @@
|
||||
"exportName": "ProviderCatalogContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 254,
|
||||
"line": 260,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3630,7 +3630,7 @@
|
||||
"exportName": "ProviderCatalogResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 277,
|
||||
"line": 283,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3639,7 +3639,7 @@
|
||||
"exportName": "ProviderDefaultThinkingPolicyContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 548,
|
||||
"line": 554,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3648,7 +3648,7 @@
|
||||
"exportName": "ProviderDiscoveryContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 587,
|
||||
"line": 593,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3657,7 +3657,7 @@
|
||||
"exportName": "ProviderFetchUsageSnapshotContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 427,
|
||||
"line": 433,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3666,7 +3666,7 @@
|
||||
"exportName": "ProviderModernModelPolicyContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 558,
|
||||
"line": 564,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3675,7 +3675,7 @@
|
||||
"exportName": "ProviderNormalizeResolvedModelContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 338,
|
||||
"line": 344,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3684,7 +3684,7 @@
|
||||
"exportName": "ProviderPreparedRuntimeAuth",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 374,
|
||||
"line": 380,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3693,7 +3693,7 @@
|
||||
"exportName": "ProviderPrepareDynamicModelContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 329,
|
||||
"line": 335,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3702,7 +3702,7 @@
|
||||
"exportName": "ProviderPrepareExtraParamsContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 460,
|
||||
"line": 466,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3711,7 +3711,7 @@
|
||||
"exportName": "ProviderPrepareRuntimeAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 353,
|
||||
"line": 359,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3720,7 +3720,7 @@
|
||||
"exportName": "ProviderResolvedUsageAuth",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 414,
|
||||
"line": 420,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3729,7 +3729,7 @@
|
||||
"exportName": "ProviderResolveDynamicModelContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 312,
|
||||
"line": 318,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3738,7 +3738,7 @@
|
||||
"exportName": "ProviderResolveUsageAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 395,
|
||||
"line": 401,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3747,7 +3747,7 @@
|
||||
"exportName": "ProviderRuntimeModel",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 295,
|
||||
"line": 301,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3756,7 +3756,7 @@
|
||||
"exportName": "ProviderThinkingPolicyContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 536,
|
||||
"line": 542,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3774,7 +3774,7 @@
|
||||
"exportName": "ProviderWrapStreamFnContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 477,
|
||||
"line": 483,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3819,7 +3819,7 @@
|
||||
"exportName": "SpeechProviderPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 933,
|
||||
"line": 939,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3911,7 +3911,7 @@
|
||||
"exportName": "MediaUnderstandingProviderPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 951,
|
||||
"line": 964,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3929,7 +3929,7 @@
|
||||
"exportName": "OpenClawPluginApi",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1336,
|
||||
"line": 1349,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3938,7 +3938,7 @@
|
||||
"exportName": "OpenClawPluginCommandDefinition",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1068,
|
||||
"line": 1081,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3947,7 +3947,7 @@
|
||||
"exportName": "OpenClawPluginConfigSchema",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 88,
|
||||
"line": 94,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3956,7 +3956,7 @@
|
||||
"exportName": "OpenClawPluginDefinition",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1318,
|
||||
"line": 1331,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3965,7 +3965,7 @@
|
||||
"exportName": "OpenClawPluginService",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1285,
|
||||
"line": 1298,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3974,7 +3974,7 @@
|
||||
"exportName": "OpenClawPluginServiceContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1277,
|
||||
"line": 1290,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3983,7 +3983,7 @@
|
||||
"exportName": "PluginCommandContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 966,
|
||||
"line": 979,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -3992,7 +3992,7 @@
|
||||
"exportName": "PluginInteractiveTelegramHandlerContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 1097,
|
||||
"line": 1110,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4001,7 +4001,7 @@
|
||||
"exportName": "PluginLogger",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 59,
|
||||
"line": 65,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4010,7 +4010,7 @@
|
||||
"exportName": "ProviderAugmentModelCatalogContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 571,
|
||||
"line": 577,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4019,7 +4019,7 @@
|
||||
"exportName": "ProviderAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 155,
|
||||
"line": 161,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4028,7 +4028,7 @@
|
||||
"exportName": "ProviderAuthDoctorHintContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 446,
|
||||
"line": 452,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4037,7 +4037,7 @@
|
||||
"exportName": "ProviderAuthMethod",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 233,
|
||||
"line": 239,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4046,7 +4046,7 @@
|
||||
"exportName": "ProviderAuthMethodNonInteractiveContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 217,
|
||||
"line": 223,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4055,7 +4055,7 @@
|
||||
"exportName": "ProviderAuthResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 140,
|
||||
"line": 146,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4064,7 +4064,7 @@
|
||||
"exportName": "ProviderBuildMissingAuthMessageContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 499,
|
||||
"line": 505,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4073,7 +4073,7 @@
|
||||
"exportName": "ProviderBuiltInModelSuppressionContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 515,
|
||||
"line": 521,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4082,7 +4082,7 @@
|
||||
"exportName": "ProviderBuiltInModelSuppressionResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 524,
|
||||
"line": 530,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4091,7 +4091,7 @@
|
||||
"exportName": "ProviderCacheTtlEligibilityContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 487,
|
||||
"line": 493,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4100,7 +4100,7 @@
|
||||
"exportName": "ProviderCatalogContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 254,
|
||||
"line": 260,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4109,7 +4109,7 @@
|
||||
"exportName": "ProviderCatalogResult",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 277,
|
||||
"line": 283,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4118,7 +4118,7 @@
|
||||
"exportName": "ProviderDefaultThinkingPolicyContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 548,
|
||||
"line": 554,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4127,7 +4127,7 @@
|
||||
"exportName": "ProviderDiscoveryContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 587,
|
||||
"line": 593,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4136,7 +4136,7 @@
|
||||
"exportName": "ProviderFetchUsageSnapshotContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 427,
|
||||
"line": 433,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4145,7 +4145,7 @@
|
||||
"exportName": "ProviderModernModelPolicyContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 558,
|
||||
"line": 564,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4154,7 +4154,7 @@
|
||||
"exportName": "ProviderNormalizeResolvedModelContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 338,
|
||||
"line": 344,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4163,7 +4163,7 @@
|
||||
"exportName": "ProviderPreparedRuntimeAuth",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 374,
|
||||
"line": 380,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4172,7 +4172,7 @@
|
||||
"exportName": "ProviderPrepareDynamicModelContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 329,
|
||||
"line": 335,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4181,7 +4181,7 @@
|
||||
"exportName": "ProviderPrepareExtraParamsContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 460,
|
||||
"line": 466,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4190,7 +4190,7 @@
|
||||
"exportName": "ProviderPrepareRuntimeAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 353,
|
||||
"line": 359,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4199,7 +4199,7 @@
|
||||
"exportName": "ProviderResolvedUsageAuth",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 414,
|
||||
"line": 420,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4208,7 +4208,7 @@
|
||||
"exportName": "ProviderResolveDynamicModelContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 312,
|
||||
"line": 318,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4217,7 +4217,7 @@
|
||||
"exportName": "ProviderResolveUsageAuthContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 395,
|
||||
"line": 401,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4226,7 +4226,7 @@
|
||||
"exportName": "ProviderRuntimeModel",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 295,
|
||||
"line": 301,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4235,7 +4235,7 @@
|
||||
"exportName": "ProviderThinkingPolicyContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 536,
|
||||
"line": 542,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4244,7 +4244,7 @@
|
||||
"exportName": "ProviderWrapStreamFnContext",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 477,
|
||||
"line": 483,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
},
|
||||
@@ -4253,7 +4253,7 @@
|
||||
"exportName": "SpeechProviderPlugin",
|
||||
"kind": "type",
|
||||
"source": {
|
||||
"line": 933,
|
||||
"line": 939,
|
||||
"path": "src/plugins/types.ts"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"index","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
|
||||
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"ClawdbotConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
|
||||
{"declaration":"export type CliBackendConfig = CliBackendConfig;","entrypoint":"index","exportName":"CliBackendConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/config/types.agent-defaults.ts"}
|
||||
{"declaration":"export type CliBackendPlugin = CliBackendPlugin;","entrypoint":"index","exportName":"CliBackendPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type CliBackendPlugin = CliBackendPlugin;","entrypoint":"index","exportName":"CliBackendPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1305,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type CompiledConfiguredBinding = CompiledConfiguredBinding;","entrypoint":"index","exportName":"CompiledConfiguredBinding","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":38,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
{"declaration":"export type ConfiguredBindingConversation = ConversationRef;","entrypoint":"index","exportName":"ConfiguredBindingConversation","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
{"declaration":"export type ConfiguredBindingResolution = ConfiguredBindingResolution;","entrypoint":"index","exportName":"ConfiguredBindingResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/binding-types.ts"}
|
||||
@@ -41,21 +41,21 @@
|
||||
{"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 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":964,"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":1336,"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":1349,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":94,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":65,"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":161,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":146,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":301,"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":939,"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"}
|
||||
@@ -374,53 +374,53 @@
|
||||
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","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":964,"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":1336,"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":1318,"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":1349,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1081,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":94,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1331,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1298,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1290,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":109,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":126,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":979,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1110,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":65,"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":577,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":161,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":452,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":239,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":223,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":146,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":505,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":521,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":530,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":493,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":260,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":283,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":554,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":593,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":433,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":564,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":344,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":380,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":335,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":466,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":359,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":420,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":318,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":401,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":301,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":542,"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":483,"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":939,"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"}
|
||||
@@ -430,45 +430,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":964,"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":1336,"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":1318,"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":1349,"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":1081,"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":94,"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":1331,"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":1298,"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":1290,"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":979,"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":1110,"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":65,"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":577,"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":161,"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":452,"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":239,"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":223,"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":146,"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":505,"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":521,"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":530,"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":493,"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":260,"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":283,"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":554,"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":593,"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":433,"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":564,"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":344,"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":380,"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":335,"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":466,"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":359,"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":420,"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":318,"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":401,"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":301,"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":542,"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":483,"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":939,"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"}
|
||||
|
||||
@@ -645,11 +645,10 @@ export class DiscordVoiceManager {
|
||||
cfg: this.params.cfg,
|
||||
override: this.params.discordConfig.voice?.tts,
|
||||
});
|
||||
const directive = parseTtsDirectives(
|
||||
replyText,
|
||||
ttsConfig.modelOverrides,
|
||||
ttsConfig.openai.baseUrl,
|
||||
);
|
||||
const directive = parseTtsDirectives(replyText, ttsConfig.modelOverrides, {
|
||||
cfg: ttsCfg,
|
||||
providerConfigs: ttsConfig.providerConfigs,
|
||||
});
|
||||
const speakText = directive.overrides.ttsText ?? directive.cleanedText.trim();
|
||||
if (!speakText) {
|
||||
logVoiceVerbose(
|
||||
|
||||
@@ -1,16 +1,309 @@
|
||||
import type { SpeechProviderPlugin } from "openclaw/plugin-sdk/core";
|
||||
import type { SpeechVoiceOption } from "openclaw/plugin-sdk/speech";
|
||||
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
||||
import type {
|
||||
SpeechDirectiveTokenParseContext,
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderOverrides,
|
||||
SpeechProviderPlugin,
|
||||
SpeechVoiceOption,
|
||||
} from "openclaw/plugin-sdk/speech-core";
|
||||
import {
|
||||
normalizeApplyTextNormalization,
|
||||
normalizeLanguageCode,
|
||||
normalizeSeed,
|
||||
requireInRange,
|
||||
} from "openclaw/plugin-sdk/speech-core";
|
||||
import { elevenLabsTTS } from "./tts.js";
|
||||
|
||||
const DEFAULT_ELEVENLABS_BASE_URL = "https://api.elevenlabs.io";
|
||||
const DEFAULT_ELEVENLABS_VOICE_ID = "pMsXgVXv3BLzUgSXRplE";
|
||||
const DEFAULT_ELEVENLABS_MODEL_ID = "eleven_multilingual_v2";
|
||||
const DEFAULT_ELEVENLABS_VOICE_SETTINGS = {
|
||||
stability: 0.5,
|
||||
similarityBoost: 0.75,
|
||||
style: 0.0,
|
||||
useSpeakerBoost: true,
|
||||
speed: 1.0,
|
||||
};
|
||||
|
||||
const ELEVENLABS_TTS_MODELS = [
|
||||
"eleven_multilingual_v2",
|
||||
"eleven_turbo_v2_5",
|
||||
"eleven_monolingual_v1",
|
||||
] as const;
|
||||
|
||||
type ElevenLabsProviderConfig = {
|
||||
apiKey?: string;
|
||||
baseUrl: string;
|
||||
voiceId: string;
|
||||
modelId: string;
|
||||
seed?: number;
|
||||
applyTextNormalization?: "auto" | "on" | "off";
|
||||
languageCode?: string;
|
||||
voiceSettings: {
|
||||
stability: number;
|
||||
similarityBoost: number;
|
||||
style: number;
|
||||
useSpeakerBoost: boolean;
|
||||
speed: number;
|
||||
};
|
||||
};
|
||||
|
||||
function trimToUndefined(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
function asNumber(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
|
||||
function asBoolean(value: unknown): boolean | undefined {
|
||||
return typeof value === "boolean" ? value : undefined;
|
||||
}
|
||||
|
||||
function asObject(value: unknown): Record<string, unknown> | undefined {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function parseBooleanValue(value: string): boolean | undefined {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (["true", "1", "yes", "on"].includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
if (["false", "0", "no", "off"].includes(normalized)) {
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseNumberValue(value: string): number | undefined {
|
||||
const parsed = Number.parseFloat(value);
|
||||
return Number.isFinite(parsed) ? parsed : undefined;
|
||||
}
|
||||
|
||||
export function isValidVoiceId(voiceId: string): boolean {
|
||||
return /^[a-zA-Z0-9]{10,40}$/.test(voiceId);
|
||||
}
|
||||
|
||||
function normalizeElevenLabsBaseUrl(baseUrl: string | undefined): string {
|
||||
const trimmed = baseUrl?.trim();
|
||||
return trimmed?.replace(/\/+$/, "") || "https://api.elevenlabs.io";
|
||||
return trimmed?.replace(/\/+$/, "") || DEFAULT_ELEVENLABS_BASE_URL;
|
||||
}
|
||||
|
||||
function normalizeElevenLabsProviderConfig(
|
||||
rawConfig: Record<string, unknown>,
|
||||
): ElevenLabsProviderConfig {
|
||||
const raw = asObject(rawConfig.elevenlabs);
|
||||
const rawVoiceSettings = asObject(raw?.voiceSettings);
|
||||
return {
|
||||
apiKey: normalizeResolvedSecretInputString({
|
||||
value: raw?.apiKey,
|
||||
path: "messages.tts.elevenlabs.apiKey",
|
||||
}),
|
||||
baseUrl: normalizeElevenLabsBaseUrl(trimToUndefined(raw?.baseUrl)),
|
||||
voiceId: trimToUndefined(raw?.voiceId) ?? DEFAULT_ELEVENLABS_VOICE_ID,
|
||||
modelId: trimToUndefined(raw?.modelId) ?? DEFAULT_ELEVENLABS_MODEL_ID,
|
||||
seed: asNumber(raw?.seed),
|
||||
applyTextNormalization: trimToUndefined(raw?.applyTextNormalization) as
|
||||
| "auto"
|
||||
| "on"
|
||||
| "off"
|
||||
| undefined,
|
||||
languageCode: trimToUndefined(raw?.languageCode),
|
||||
voiceSettings: {
|
||||
stability:
|
||||
asNumber(rawVoiceSettings?.stability) ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.stability,
|
||||
similarityBoost:
|
||||
asNumber(rawVoiceSettings?.similarityBoost) ??
|
||||
DEFAULT_ELEVENLABS_VOICE_SETTINGS.similarityBoost,
|
||||
style: asNumber(rawVoiceSettings?.style) ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.style,
|
||||
useSpeakerBoost:
|
||||
asBoolean(rawVoiceSettings?.useSpeakerBoost) ??
|
||||
DEFAULT_ELEVENLABS_VOICE_SETTINGS.useSpeakerBoost,
|
||||
speed: asNumber(rawVoiceSettings?.speed) ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.speed,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function readElevenLabsProviderConfig(config: SpeechProviderConfig): ElevenLabsProviderConfig {
|
||||
const defaults = normalizeElevenLabsProviderConfig({});
|
||||
const voiceSettings = asObject(config.voiceSettings);
|
||||
return {
|
||||
apiKey: trimToUndefined(config.apiKey) ?? defaults.apiKey,
|
||||
baseUrl: normalizeElevenLabsBaseUrl(trimToUndefined(config.baseUrl) ?? defaults.baseUrl),
|
||||
voiceId: trimToUndefined(config.voiceId) ?? defaults.voiceId,
|
||||
modelId: trimToUndefined(config.modelId) ?? defaults.modelId,
|
||||
seed: asNumber(config.seed) ?? defaults.seed,
|
||||
applyTextNormalization:
|
||||
(trimToUndefined(config.applyTextNormalization) as "auto" | "on" | "off" | undefined) ??
|
||||
defaults.applyTextNormalization,
|
||||
languageCode: trimToUndefined(config.languageCode) ?? defaults.languageCode,
|
||||
voiceSettings: {
|
||||
stability: asNumber(voiceSettings?.stability) ?? defaults.voiceSettings.stability,
|
||||
similarityBoost:
|
||||
asNumber(voiceSettings?.similarityBoost) ?? defaults.voiceSettings.similarityBoost,
|
||||
style: asNumber(voiceSettings?.style) ?? defaults.voiceSettings.style,
|
||||
useSpeakerBoost:
|
||||
asBoolean(voiceSettings?.useSpeakerBoost) ?? defaults.voiceSettings.useSpeakerBoost,
|
||||
speed: asNumber(voiceSettings?.speed) ?? defaults.voiceSettings.speed,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function mergeVoiceSettingsOverride(
|
||||
ctx: SpeechDirectiveTokenParseContext,
|
||||
next: Record<string, unknown>,
|
||||
): SpeechProviderOverrides {
|
||||
return {
|
||||
...(ctx.currentOverrides ?? {}),
|
||||
voiceSettings: {
|
||||
...(asObject(ctx.currentOverrides?.voiceSettings) ?? {}),
|
||||
...next,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function parseDirectiveToken(ctx: SpeechDirectiveTokenParseContext) {
|
||||
try {
|
||||
switch (ctx.key) {
|
||||
case "voiceid":
|
||||
case "voice_id":
|
||||
case "elevenlabs_voice":
|
||||
case "elevenlabsvoice":
|
||||
if (!ctx.policy.allowVoice) {
|
||||
return { handled: true };
|
||||
}
|
||||
if (!isValidVoiceId(ctx.value)) {
|
||||
return { handled: true, warnings: [`invalid ElevenLabs voiceId "${ctx.value}"`] };
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
overrides: { ...(ctx.currentOverrides ?? {}), voiceId: ctx.value },
|
||||
};
|
||||
case "model":
|
||||
case "modelid":
|
||||
case "model_id":
|
||||
case "elevenlabs_model":
|
||||
case "elevenlabsmodel":
|
||||
if (!ctx.policy.allowModelId) {
|
||||
return { handled: true };
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
overrides: { ...(ctx.currentOverrides ?? {}), modelId: ctx.value },
|
||||
};
|
||||
case "stability": {
|
||||
if (!ctx.policy.allowVoiceSettings) {
|
||||
return { handled: true };
|
||||
}
|
||||
const value = parseNumberValue(ctx.value);
|
||||
if (value == null) {
|
||||
return { handled: true, warnings: ["invalid stability value"] };
|
||||
}
|
||||
requireInRange(value, 0, 1, "stability");
|
||||
return { handled: true, overrides: mergeVoiceSettingsOverride(ctx, { stability: value }) };
|
||||
}
|
||||
case "similarity":
|
||||
case "similarityboost":
|
||||
case "similarity_boost": {
|
||||
if (!ctx.policy.allowVoiceSettings) {
|
||||
return { handled: true };
|
||||
}
|
||||
const value = parseNumberValue(ctx.value);
|
||||
if (value == null) {
|
||||
return { handled: true, warnings: ["invalid similarityBoost value"] };
|
||||
}
|
||||
requireInRange(value, 0, 1, "similarityBoost");
|
||||
return {
|
||||
handled: true,
|
||||
overrides: mergeVoiceSettingsOverride(ctx, { similarityBoost: value }),
|
||||
};
|
||||
}
|
||||
case "style": {
|
||||
if (!ctx.policy.allowVoiceSettings) {
|
||||
return { handled: true };
|
||||
}
|
||||
const value = parseNumberValue(ctx.value);
|
||||
if (value == null) {
|
||||
return { handled: true, warnings: ["invalid style value"] };
|
||||
}
|
||||
requireInRange(value, 0, 1, "style");
|
||||
return { handled: true, overrides: mergeVoiceSettingsOverride(ctx, { style: value }) };
|
||||
}
|
||||
case "speed": {
|
||||
if (!ctx.policy.allowVoiceSettings) {
|
||||
return { handled: true };
|
||||
}
|
||||
const value = parseNumberValue(ctx.value);
|
||||
if (value == null) {
|
||||
return { handled: true, warnings: ["invalid speed value"] };
|
||||
}
|
||||
requireInRange(value, 0.5, 2, "speed");
|
||||
return { handled: true, overrides: mergeVoiceSettingsOverride(ctx, { speed: value }) };
|
||||
}
|
||||
case "speakerboost":
|
||||
case "speaker_boost":
|
||||
case "usespeakerboost":
|
||||
case "use_speaker_boost": {
|
||||
if (!ctx.policy.allowVoiceSettings) {
|
||||
return { handled: true };
|
||||
}
|
||||
const value = parseBooleanValue(ctx.value);
|
||||
if (value == null) {
|
||||
return { handled: true, warnings: ["invalid useSpeakerBoost value"] };
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
overrides: mergeVoiceSettingsOverride(ctx, { useSpeakerBoost: value }),
|
||||
};
|
||||
}
|
||||
case "normalize":
|
||||
case "applytextnormalization":
|
||||
case "apply_text_normalization":
|
||||
if (!ctx.policy.allowNormalization) {
|
||||
return { handled: true };
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
overrides: {
|
||||
...(ctx.currentOverrides ?? {}),
|
||||
applyTextNormalization: normalizeApplyTextNormalization(ctx.value),
|
||||
},
|
||||
};
|
||||
case "language":
|
||||
case "languagecode":
|
||||
case "language_code":
|
||||
if (!ctx.policy.allowNormalization) {
|
||||
return { handled: true };
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
overrides: {
|
||||
...(ctx.currentOverrides ?? {}),
|
||||
languageCode: normalizeLanguageCode(ctx.value),
|
||||
},
|
||||
};
|
||||
case "seed":
|
||||
if (!ctx.policy.allowSeed) {
|
||||
return { handled: true };
|
||||
}
|
||||
return {
|
||||
handled: true,
|
||||
overrides: {
|
||||
...(ctx.currentOverrides ?? {}),
|
||||
seed: normalizeSeed(Number.parseInt(ctx.value, 10)),
|
||||
},
|
||||
};
|
||||
default:
|
||||
return { handled: false };
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
handled: true,
|
||||
warnings: [error instanceof Error ? error.message : String(error)],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function listElevenLabsVoices(params: {
|
||||
@@ -49,49 +342,164 @@ export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
return {
|
||||
id: "elevenlabs",
|
||||
label: "ElevenLabs",
|
||||
autoSelectOrder: 20,
|
||||
models: ELEVENLABS_TTS_MODELS,
|
||||
resolveConfig: ({ rawConfig }) => normalizeElevenLabsProviderConfig(rawConfig),
|
||||
parseDirectiveToken,
|
||||
resolveTalkConfig: ({ baseTtsConfig, talkProviderConfig }) => {
|
||||
const base = normalizeElevenLabsProviderConfig(baseTtsConfig);
|
||||
const talkVoiceSettings = asObject(talkProviderConfig.voiceSettings);
|
||||
return {
|
||||
...base,
|
||||
...(talkProviderConfig.apiKey === undefined
|
||||
? {}
|
||||
: {
|
||||
apiKey: normalizeResolvedSecretInputString({
|
||||
value: talkProviderConfig.apiKey,
|
||||
path: "talk.providers.elevenlabs.apiKey",
|
||||
}),
|
||||
}),
|
||||
...(trimToUndefined(talkProviderConfig.baseUrl) == null
|
||||
? {}
|
||||
: { baseUrl: normalizeElevenLabsBaseUrl(trimToUndefined(talkProviderConfig.baseUrl)) }),
|
||||
...(trimToUndefined(talkProviderConfig.voiceId) == null
|
||||
? {}
|
||||
: { voiceId: trimToUndefined(talkProviderConfig.voiceId) }),
|
||||
...(trimToUndefined(talkProviderConfig.modelId) == null
|
||||
? {}
|
||||
: { modelId: trimToUndefined(talkProviderConfig.modelId) }),
|
||||
...(asNumber(talkProviderConfig.seed) == null
|
||||
? {}
|
||||
: { seed: asNumber(talkProviderConfig.seed) }),
|
||||
...(trimToUndefined(talkProviderConfig.applyTextNormalization) == null
|
||||
? {}
|
||||
: {
|
||||
applyTextNormalization: normalizeApplyTextNormalization(
|
||||
trimToUndefined(talkProviderConfig.applyTextNormalization),
|
||||
),
|
||||
}),
|
||||
...(trimToUndefined(talkProviderConfig.languageCode) == null
|
||||
? {}
|
||||
: {
|
||||
languageCode: normalizeLanguageCode(trimToUndefined(talkProviderConfig.languageCode)),
|
||||
}),
|
||||
voiceSettings: {
|
||||
...base.voiceSettings,
|
||||
...(asNumber(talkVoiceSettings?.stability) == null
|
||||
? {}
|
||||
: { stability: asNumber(talkVoiceSettings?.stability) }),
|
||||
...(asNumber(talkVoiceSettings?.similarityBoost) == null
|
||||
? {}
|
||||
: { similarityBoost: asNumber(talkVoiceSettings?.similarityBoost) }),
|
||||
...(asNumber(talkVoiceSettings?.style) == null
|
||||
? {}
|
||||
: { style: asNumber(talkVoiceSettings?.style) }),
|
||||
...(asBoolean(talkVoiceSettings?.useSpeakerBoost) == null
|
||||
? {}
|
||||
: { useSpeakerBoost: asBoolean(talkVoiceSettings?.useSpeakerBoost) }),
|
||||
...(asNumber(talkVoiceSettings?.speed) == null
|
||||
? {}
|
||||
: { speed: asNumber(talkVoiceSettings?.speed) }),
|
||||
},
|
||||
};
|
||||
},
|
||||
resolveTalkOverrides: ({ params }) => {
|
||||
const normalize = trimToUndefined(params.normalize);
|
||||
const language = trimToUndefined(params.language)?.toLowerCase();
|
||||
const voiceSettings = {
|
||||
...(asNumber(params.speed) == null ? {} : { speed: asNumber(params.speed) }),
|
||||
...(asNumber(params.stability) == null ? {} : { stability: asNumber(params.stability) }),
|
||||
...(asNumber(params.similarity) == null
|
||||
? {}
|
||||
: { similarityBoost: asNumber(params.similarity) }),
|
||||
...(asNumber(params.style) == null ? {} : { style: asNumber(params.style) }),
|
||||
...(asBoolean(params.speakerBoost) == null
|
||||
? {}
|
||||
: { useSpeakerBoost: asBoolean(params.speakerBoost) }),
|
||||
};
|
||||
return {
|
||||
...(trimToUndefined(params.voiceId) == null
|
||||
? {}
|
||||
: { voiceId: trimToUndefined(params.voiceId) }),
|
||||
...(trimToUndefined(params.modelId) == null
|
||||
? {}
|
||||
: { modelId: trimToUndefined(params.modelId) }),
|
||||
...(trimToUndefined(params.outputFormat) == null
|
||||
? {}
|
||||
: { outputFormat: trimToUndefined(params.outputFormat) }),
|
||||
...(asNumber(params.seed) == null ? {} : { seed: asNumber(params.seed) }),
|
||||
...(normalize == null
|
||||
? {}
|
||||
: { applyTextNormalization: normalizeApplyTextNormalization(normalize) }),
|
||||
...(language == null ? {} : { languageCode: normalizeLanguageCode(language) }),
|
||||
...(Object.keys(voiceSettings).length === 0 ? {} : { voiceSettings }),
|
||||
};
|
||||
},
|
||||
listVoices: async (req) => {
|
||||
const config = req.providerConfig
|
||||
? readElevenLabsProviderConfig(req.providerConfig)
|
||||
: undefined;
|
||||
const apiKey =
|
||||
req.apiKey ||
|
||||
req.config?.elevenlabs.apiKey ||
|
||||
process.env.ELEVENLABS_API_KEY ||
|
||||
process.env.XI_API_KEY;
|
||||
req.apiKey || config?.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
return listElevenLabsVoices({
|
||||
apiKey,
|
||||
baseUrl: req.baseUrl ?? req.config?.elevenlabs.baseUrl,
|
||||
baseUrl: req.baseUrl ?? config?.baseUrl,
|
||||
});
|
||||
},
|
||||
isConfigured: ({ config }) =>
|
||||
Boolean(config.elevenlabs.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY),
|
||||
isConfigured: ({ providerConfig }) =>
|
||||
Boolean(
|
||||
readElevenLabsProviderConfig(providerConfig).apiKey ||
|
||||
process.env.ELEVENLABS_API_KEY ||
|
||||
process.env.XI_API_KEY,
|
||||
),
|
||||
synthesize: async (req) => {
|
||||
const apiKey =
|
||||
req.config.elevenlabs.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
|
||||
const config = readElevenLabsProviderConfig(req.providerConfig);
|
||||
const overrides = req.providerOverrides ?? {};
|
||||
const apiKey = config.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
const outputFormat =
|
||||
req.overrides?.elevenlabs?.outputFormat ??
|
||||
trimToUndefined(overrides.outputFormat) ??
|
||||
(req.target === "voice-note" ? "opus_48000_64" : "mp3_44100_128");
|
||||
const overrideVoiceSettings = asObject(overrides.voiceSettings);
|
||||
const audioBuffer = await elevenLabsTTS({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: req.config.elevenlabs.baseUrl,
|
||||
voiceId: req.overrides?.elevenlabs?.voiceId ?? req.config.elevenlabs.voiceId,
|
||||
modelId: req.overrides?.elevenlabs?.modelId ?? req.config.elevenlabs.modelId,
|
||||
baseUrl: config.baseUrl,
|
||||
voiceId: trimToUndefined(overrides.voiceId) ?? config.voiceId,
|
||||
modelId: trimToUndefined(overrides.modelId) ?? config.modelId,
|
||||
outputFormat,
|
||||
seed: req.overrides?.elevenlabs?.seed ?? req.config.elevenlabs.seed,
|
||||
seed: asNumber(overrides.seed) ?? config.seed,
|
||||
applyTextNormalization:
|
||||
req.overrides?.elevenlabs?.applyTextNormalization ??
|
||||
req.config.elevenlabs.applyTextNormalization,
|
||||
languageCode: req.overrides?.elevenlabs?.languageCode ?? req.config.elevenlabs.languageCode,
|
||||
(trimToUndefined(overrides.applyTextNormalization) as
|
||||
| "auto"
|
||||
| "on"
|
||||
| "off"
|
||||
| undefined) ?? config.applyTextNormalization,
|
||||
languageCode: trimToUndefined(overrides.languageCode) ?? config.languageCode,
|
||||
voiceSettings: {
|
||||
...req.config.elevenlabs.voiceSettings,
|
||||
...req.overrides?.elevenlabs?.voiceSettings,
|
||||
...config.voiceSettings,
|
||||
...(asNumber(overrideVoiceSettings?.stability) == null
|
||||
? {}
|
||||
: { stability: asNumber(overrideVoiceSettings?.stability) }),
|
||||
...(asNumber(overrideVoiceSettings?.similarityBoost) == null
|
||||
? {}
|
||||
: { similarityBoost: asNumber(overrideVoiceSettings?.similarityBoost) }),
|
||||
...(asNumber(overrideVoiceSettings?.style) == null
|
||||
? {}
|
||||
: { style: asNumber(overrideVoiceSettings?.style) }),
|
||||
...(asBoolean(overrideVoiceSettings?.useSpeakerBoost) == null
|
||||
? {}
|
||||
: { useSpeakerBoost: asBoolean(overrideVoiceSettings?.useSpeakerBoost) }),
|
||||
...(asNumber(overrideVoiceSettings?.speed) == null
|
||||
? {}
|
||||
: { speed: asNumber(overrideVoiceSettings?.speed) }),
|
||||
},
|
||||
timeoutMs: req.config.timeoutMs,
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
return {
|
||||
audioBuffer,
|
||||
@@ -101,8 +509,8 @@ export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
};
|
||||
},
|
||||
synthesizeTelephony: async (req) => {
|
||||
const apiKey =
|
||||
req.config.elevenlabs.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
|
||||
const config = readElevenLabsProviderConfig(req.providerConfig);
|
||||
const apiKey = config.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("ElevenLabs API key missing");
|
||||
}
|
||||
@@ -111,15 +519,15 @@ export function buildElevenLabsSpeechProvider(): SpeechProviderPlugin {
|
||||
const audioBuffer = await elevenLabsTTS({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: req.config.elevenlabs.baseUrl,
|
||||
voiceId: req.config.elevenlabs.voiceId,
|
||||
modelId: req.config.elevenlabs.modelId,
|
||||
baseUrl: config.baseUrl,
|
||||
voiceId: config.voiceId,
|
||||
modelId: config.modelId,
|
||||
outputFormat,
|
||||
seed: req.config.elevenlabs.seed,
|
||||
applyTextNormalization: req.config.elevenlabs.applyTextNormalization,
|
||||
languageCode: req.config.elevenlabs.languageCode,
|
||||
voiceSettings: req.config.elevenlabs.voiceSettings,
|
||||
timeoutMs: req.config.timeoutMs,
|
||||
seed: config.seed,
|
||||
applyTextNormalization: config.applyTextNormalization,
|
||||
languageCode: config.languageCode,
|
||||
voiceSettings: config.voiceSettings,
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
return { audioBuffer, outputFormat, sampleRate };
|
||||
},
|
||||
|
||||
@@ -5,14 +5,33 @@ import {
|
||||
TRUSTED_CLIENT_TOKEN,
|
||||
generateSecMsGecToken,
|
||||
} from "node-edge-tts/dist/drm.js";
|
||||
import type { SpeechProviderPlugin } from "openclaw/plugin-sdk/core";
|
||||
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/llm-task";
|
||||
import { isVoiceCompatibleAudio } from "openclaw/plugin-sdk/media-runtime";
|
||||
import type { SpeechVoiceOption } from "openclaw/plugin-sdk/speech";
|
||||
import type {
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderPlugin,
|
||||
SpeechVoiceOption,
|
||||
} from "openclaw/plugin-sdk/speech-core";
|
||||
import { edgeTTS, inferEdgeExtension } from "./tts.js";
|
||||
|
||||
const DEFAULT_EDGE_VOICE = "en-US-MichelleNeural";
|
||||
const DEFAULT_EDGE_LANG = "en-US";
|
||||
const DEFAULT_EDGE_OUTPUT_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
|
||||
|
||||
type MicrosoftProviderConfig = {
|
||||
enabled: boolean;
|
||||
voice: string;
|
||||
lang: string;
|
||||
outputFormat: string;
|
||||
outputFormatConfigured: boolean;
|
||||
pitch?: string;
|
||||
rate?: string;
|
||||
volume?: string;
|
||||
saveSubtitles: boolean;
|
||||
proxy?: string;
|
||||
timeoutMs?: number;
|
||||
};
|
||||
|
||||
type MicrosoftVoiceListEntry = {
|
||||
ShortName?: string;
|
||||
FriendlyName?: string;
|
||||
@@ -24,6 +43,64 @@ type MicrosoftVoiceListEntry = {
|
||||
};
|
||||
};
|
||||
|
||||
function trimToUndefined(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
function asBoolean(value: unknown): boolean | undefined {
|
||||
return typeof value === "boolean" ? value : undefined;
|
||||
}
|
||||
|
||||
function asNumber(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
|
||||
function asObject(value: unknown): Record<string, unknown> | undefined {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function normalizeMicrosoftProviderConfig(
|
||||
rawConfig: Record<string, unknown>,
|
||||
): MicrosoftProviderConfig {
|
||||
const rawEdge = asObject(rawConfig.edge);
|
||||
const rawMicrosoft = asObject(rawConfig.microsoft);
|
||||
const raw = { ...(rawEdge ?? {}), ...(rawMicrosoft ?? {}) };
|
||||
const outputFormat = trimToUndefined(raw.outputFormat);
|
||||
return {
|
||||
enabled: asBoolean(raw.enabled) ?? true,
|
||||
voice: trimToUndefined(raw.voice) ?? DEFAULT_EDGE_VOICE,
|
||||
lang: trimToUndefined(raw.lang) ?? DEFAULT_EDGE_LANG,
|
||||
outputFormat: outputFormat ?? DEFAULT_EDGE_OUTPUT_FORMAT,
|
||||
outputFormatConfigured: Boolean(outputFormat),
|
||||
pitch: trimToUndefined(raw.pitch),
|
||||
rate: trimToUndefined(raw.rate),
|
||||
volume: trimToUndefined(raw.volume),
|
||||
saveSubtitles: asBoolean(raw.saveSubtitles) ?? false,
|
||||
proxy: trimToUndefined(raw.proxy),
|
||||
timeoutMs: asNumber(raw.timeoutMs),
|
||||
};
|
||||
}
|
||||
|
||||
function readMicrosoftProviderConfig(config: SpeechProviderConfig): MicrosoftProviderConfig {
|
||||
const defaults = normalizeMicrosoftProviderConfig({});
|
||||
return {
|
||||
enabled: asBoolean(config.enabled) ?? defaults.enabled,
|
||||
voice: trimToUndefined(config.voice) ?? defaults.voice,
|
||||
lang: trimToUndefined(config.lang) ?? defaults.lang,
|
||||
outputFormat: trimToUndefined(config.outputFormat) ?? defaults.outputFormat,
|
||||
outputFormatConfigured:
|
||||
asBoolean(config.outputFormatConfigured) ?? defaults.outputFormatConfigured,
|
||||
pitch: trimToUndefined(config.pitch) ?? defaults.pitch,
|
||||
rate: trimToUndefined(config.rate) ?? defaults.rate,
|
||||
volume: trimToUndefined(config.volume) ?? defaults.volume,
|
||||
saveSubtitles: asBoolean(config.saveSubtitles) ?? defaults.saveSubtitles,
|
||||
proxy: trimToUndefined(config.proxy) ?? defaults.proxy,
|
||||
timeoutMs: asNumber(config.timeoutMs) ?? defaults.timeoutMs,
|
||||
};
|
||||
}
|
||||
|
||||
function buildMicrosoftVoiceHeaders(): Record<string, string> {
|
||||
const major = CHROMIUM_FULL_VERSION.split(".")[0] || "0";
|
||||
return {
|
||||
@@ -77,13 +154,57 @@ export function buildMicrosoftSpeechProvider(): SpeechProviderPlugin {
|
||||
id: "microsoft",
|
||||
label: "Microsoft",
|
||||
aliases: ["edge"],
|
||||
autoSelectOrder: 30,
|
||||
resolveConfig: ({ rawConfig }) => normalizeMicrosoftProviderConfig(rawConfig),
|
||||
resolveTalkConfig: ({ baseTtsConfig, talkProviderConfig }) => {
|
||||
const base = normalizeMicrosoftProviderConfig(baseTtsConfig);
|
||||
return {
|
||||
...base,
|
||||
enabled: true,
|
||||
...(trimToUndefined(talkProviderConfig.voiceId) == null
|
||||
? {}
|
||||
: { voice: trimToUndefined(talkProviderConfig.voiceId) }),
|
||||
...(trimToUndefined(talkProviderConfig.languageCode) == null
|
||||
? {}
|
||||
: { lang: trimToUndefined(talkProviderConfig.languageCode) }),
|
||||
...(trimToUndefined(talkProviderConfig.outputFormat) == null
|
||||
? {}
|
||||
: { outputFormat: trimToUndefined(talkProviderConfig.outputFormat) }),
|
||||
...(trimToUndefined(talkProviderConfig.pitch) == null
|
||||
? {}
|
||||
: { pitch: trimToUndefined(talkProviderConfig.pitch) }),
|
||||
...(trimToUndefined(talkProviderConfig.rate) == null
|
||||
? {}
|
||||
: { rate: trimToUndefined(talkProviderConfig.rate) }),
|
||||
...(trimToUndefined(talkProviderConfig.volume) == null
|
||||
? {}
|
||||
: { volume: trimToUndefined(talkProviderConfig.volume) }),
|
||||
...(trimToUndefined(talkProviderConfig.proxy) == null
|
||||
? {}
|
||||
: { proxy: trimToUndefined(talkProviderConfig.proxy) }),
|
||||
...(asNumber(talkProviderConfig.timeoutMs) == null
|
||||
? {}
|
||||
: { timeoutMs: asNumber(talkProviderConfig.timeoutMs) }),
|
||||
};
|
||||
},
|
||||
resolveTalkOverrides: ({ params }) => ({
|
||||
...(trimToUndefined(params.voiceId) == null
|
||||
? {}
|
||||
: { voice: trimToUndefined(params.voiceId) }),
|
||||
...(trimToUndefined(params.outputFormat) == null
|
||||
? {}
|
||||
: { outputFormat: trimToUndefined(params.outputFormat) }),
|
||||
}),
|
||||
listVoices: async () => await listMicrosoftVoices(),
|
||||
isConfigured: ({ config }) => config.edge.enabled,
|
||||
isConfigured: ({ providerConfig }) => readMicrosoftProviderConfig(providerConfig).enabled,
|
||||
synthesize: async (req) => {
|
||||
const config = readMicrosoftProviderConfig(req.providerConfig);
|
||||
const tempRoot = resolvePreferredOpenClawTmpDir();
|
||||
mkdirSync(tempRoot, { recursive: true, mode: 0o700 });
|
||||
const tempDir = mkdtempSync(path.join(tempRoot, "tts-microsoft-"));
|
||||
let outputFormat = req.overrides?.microsoft?.outputFormat ?? req.config.edge.outputFormat;
|
||||
const overrideVoice = trimToUndefined(req.providerOverrides?.voice);
|
||||
let outputFormat =
|
||||
trimToUndefined(req.providerOverrides?.outputFormat) ?? config.outputFormat;
|
||||
const fallbackOutputFormat =
|
||||
outputFormat !== DEFAULT_EDGE_OUTPUT_FORMAT ? DEFAULT_EDGE_OUTPUT_FORMAT : undefined;
|
||||
|
||||
@@ -95,11 +216,11 @@ export function buildMicrosoftSpeechProvider(): SpeechProviderPlugin {
|
||||
text: req.text,
|
||||
outputPath,
|
||||
config: {
|
||||
...req.config.edge,
|
||||
voice: req.overrides?.microsoft?.voice ?? req.config.edge.voice,
|
||||
...config,
|
||||
voice: overrideVoice ?? config.voice,
|
||||
outputFormat: format,
|
||||
},
|
||||
timeoutMs: req.config.timeoutMs,
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
const audioBuffer = readFileSync(outputPath);
|
||||
return {
|
||||
@@ -112,9 +233,9 @@ export function buildMicrosoftSpeechProvider(): SpeechProviderPlugin {
|
||||
|
||||
try {
|
||||
return await runEdge(outputFormat);
|
||||
} catch (err) {
|
||||
} catch (error) {
|
||||
if (!fallbackOutputFormat || fallbackOutputFormat === outputFormat) {
|
||||
throw err;
|
||||
throw error;
|
||||
}
|
||||
outputFormat = fallbackOutputFormat;
|
||||
return await runEdge(outputFormat);
|
||||
|
||||
@@ -137,32 +137,14 @@ function createLiveTtsConfig(): ResolvedTtsConfig {
|
||||
allowNormalization: true,
|
||||
allowSeed: true,
|
||||
},
|
||||
elevenlabs: {
|
||||
baseUrl: "https://api.elevenlabs.io",
|
||||
voiceId: "",
|
||||
modelId: "eleven_multilingual_v2",
|
||||
voiceSettings: {
|
||||
stability: 0.5,
|
||||
similarityBoost: 0.75,
|
||||
style: 0,
|
||||
useSpeakerBoost: true,
|
||||
speed: 1,
|
||||
providerConfigs: {
|
||||
openai: {
|
||||
apiKey: OPENAI_API_KEY,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
model: "gpt-4o-mini-tts",
|
||||
voice: "alloy",
|
||||
},
|
||||
},
|
||||
openai: {
|
||||
apiKey: OPENAI_API_KEY,
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
model: "gpt-4o-mini-tts",
|
||||
voice: "alloy",
|
||||
},
|
||||
edge: {
|
||||
enabled: false,
|
||||
voice: "en-US-AriaNeural",
|
||||
lang: "en-US",
|
||||
outputFormat: "audio-24khz-48kbitrate-mono-mp3",
|
||||
outputFormatConfigured: false,
|
||||
saveSubtitles: false,
|
||||
},
|
||||
maxTextLength: 4_000,
|
||||
timeoutMs: 30_000,
|
||||
};
|
||||
@@ -358,8 +340,9 @@ describeLive("openai plugin live", () => {
|
||||
const audioFile = await speechProvider.synthesize({
|
||||
text: "OpenClaw integration test OK.",
|
||||
cfg,
|
||||
config: ttsConfig,
|
||||
providerConfig: ttsConfig.providerConfigs.openai ?? {},
|
||||
target: "audio-file",
|
||||
timeoutMs: ttsConfig.timeoutMs,
|
||||
});
|
||||
expect(audioFile.outputFormat).toBe("mp3");
|
||||
expect(audioFile.fileExtension).toBe(".mp3");
|
||||
@@ -368,7 +351,8 @@ describeLive("openai plugin live", () => {
|
||||
const telephony = await speechProvider.synthesizeTelephony?.({
|
||||
text: "Telephony check OK.",
|
||||
cfg,
|
||||
config: ttsConfig,
|
||||
providerConfig: ttsConfig.providerConfigs.openai ?? {},
|
||||
timeoutMs: ttsConfig.timeoutMs,
|
||||
});
|
||||
expect(telephony?.outputFormat).toBe("pcm");
|
||||
expect(telephony?.sampleRate).toBe(24_000);
|
||||
@@ -386,8 +370,9 @@ describeLive("openai plugin live", () => {
|
||||
const synthesized = await speechProvider.synthesize({
|
||||
text: "OpenClaw integration test OK.",
|
||||
cfg,
|
||||
config: ttsConfig,
|
||||
providerConfig: ttsConfig.providerConfigs.openai ?? {},
|
||||
target: "audio-file",
|
||||
timeoutMs: ttsConfig.timeoutMs,
|
||||
});
|
||||
|
||||
const transcription = await mediaProvider.transcribeAudio?.({
|
||||
|
||||
@@ -1,16 +1,181 @@
|
||||
import type { SpeechProviderPlugin } from "openclaw/plugin-sdk/core";
|
||||
import { OPENAI_TTS_MODELS, OPENAI_TTS_VOICES, openaiTTS } from "./tts.js";
|
||||
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
|
||||
import type {
|
||||
SpeechDirectiveTokenParseContext,
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderOverrides,
|
||||
SpeechProviderPlugin,
|
||||
} from "openclaw/plugin-sdk/speech-core";
|
||||
import {
|
||||
DEFAULT_OPENAI_BASE_URL,
|
||||
isValidOpenAIModel,
|
||||
isValidOpenAIVoice,
|
||||
normalizeOpenAITtsBaseUrl,
|
||||
OPENAI_TTS_MODELS,
|
||||
OPENAI_TTS_VOICES,
|
||||
openaiTTS,
|
||||
} from "./tts.js";
|
||||
|
||||
type OpenAITtsProviderConfig = {
|
||||
apiKey?: string;
|
||||
baseUrl: string;
|
||||
model: string;
|
||||
voice: string;
|
||||
speed?: number;
|
||||
instructions?: string;
|
||||
};
|
||||
|
||||
type OpenAITtsProviderOverrides = {
|
||||
model?: string;
|
||||
voice?: string;
|
||||
speed?: number;
|
||||
};
|
||||
|
||||
function trimToUndefined(value: unknown): string | undefined {
|
||||
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
}
|
||||
|
||||
function asNumber(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
|
||||
function asObject(value: unknown): Record<string, unknown> | undefined {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function normalizeOpenAIProviderConfig(
|
||||
rawConfig: Record<string, unknown>,
|
||||
): OpenAITtsProviderConfig {
|
||||
const raw = asObject(rawConfig.openai);
|
||||
return {
|
||||
apiKey: normalizeResolvedSecretInputString({
|
||||
value: raw?.apiKey,
|
||||
path: "messages.tts.openai.apiKey",
|
||||
}),
|
||||
baseUrl: normalizeOpenAITtsBaseUrl(
|
||||
trimToUndefined(raw?.baseUrl) ??
|
||||
trimToUndefined(process.env.OPENAI_TTS_BASE_URL) ??
|
||||
DEFAULT_OPENAI_BASE_URL,
|
||||
),
|
||||
model: trimToUndefined(raw?.model) ?? "gpt-4o-mini-tts",
|
||||
voice: trimToUndefined(raw?.voice) ?? "coral",
|
||||
speed: asNumber(raw?.speed),
|
||||
instructions: trimToUndefined(raw?.instructions),
|
||||
};
|
||||
}
|
||||
|
||||
function readOpenAIProviderConfig(config: SpeechProviderConfig): OpenAITtsProviderConfig {
|
||||
const normalized = normalizeOpenAIProviderConfig({});
|
||||
return {
|
||||
apiKey: trimToUndefined(config.apiKey) ?? normalized.apiKey,
|
||||
baseUrl: trimToUndefined(config.baseUrl) ?? normalized.baseUrl,
|
||||
model: trimToUndefined(config.model) ?? normalized.model,
|
||||
voice: trimToUndefined(config.voice) ?? normalized.voice,
|
||||
speed: asNumber(config.speed) ?? normalized.speed,
|
||||
instructions: trimToUndefined(config.instructions) ?? normalized.instructions,
|
||||
};
|
||||
}
|
||||
|
||||
function readOpenAIOverrides(
|
||||
overrides: SpeechProviderOverrides | undefined,
|
||||
): OpenAITtsProviderOverrides {
|
||||
if (!overrides) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
model: trimToUndefined(overrides.model),
|
||||
voice: trimToUndefined(overrides.voice),
|
||||
speed: asNumber(overrides.speed),
|
||||
};
|
||||
}
|
||||
|
||||
function parseDirectiveToken(ctx: SpeechDirectiveTokenParseContext): {
|
||||
handled: boolean;
|
||||
overrides?: SpeechProviderOverrides;
|
||||
warnings?: string[];
|
||||
} {
|
||||
const baseUrl = trimToUndefined(ctx.providerConfig?.baseUrl);
|
||||
switch (ctx.key) {
|
||||
case "voice":
|
||||
case "openai_voice":
|
||||
case "openaivoice":
|
||||
if (!ctx.policy.allowVoice) {
|
||||
return { handled: true };
|
||||
}
|
||||
if (!isValidOpenAIVoice(ctx.value, baseUrl)) {
|
||||
return { handled: true, warnings: [`invalid OpenAI voice "${ctx.value}"`] };
|
||||
}
|
||||
return { handled: true, overrides: { voice: ctx.value } };
|
||||
case "model":
|
||||
case "openai_model":
|
||||
case "openaimodel":
|
||||
if (!ctx.policy.allowModelId) {
|
||||
return { handled: true };
|
||||
}
|
||||
if (!isValidOpenAIModel(ctx.value, baseUrl)) {
|
||||
return { handled: false };
|
||||
}
|
||||
return { handled: true, overrides: { model: ctx.value } };
|
||||
default:
|
||||
return { handled: false };
|
||||
}
|
||||
}
|
||||
|
||||
export function buildOpenAISpeechProvider(): SpeechProviderPlugin {
|
||||
return {
|
||||
id: "openai",
|
||||
label: "OpenAI",
|
||||
autoSelectOrder: 10,
|
||||
models: OPENAI_TTS_MODELS,
|
||||
voices: OPENAI_TTS_VOICES,
|
||||
resolveConfig: ({ rawConfig }) => normalizeOpenAIProviderConfig(rawConfig),
|
||||
parseDirectiveToken,
|
||||
resolveTalkConfig: ({ baseTtsConfig, talkProviderConfig }) => {
|
||||
const base = normalizeOpenAIProviderConfig(baseTtsConfig);
|
||||
return {
|
||||
...base,
|
||||
...(talkProviderConfig.apiKey === undefined
|
||||
? {}
|
||||
: {
|
||||
apiKey: normalizeResolvedSecretInputString({
|
||||
value: talkProviderConfig.apiKey,
|
||||
path: "talk.providers.openai.apiKey",
|
||||
}),
|
||||
}),
|
||||
...(trimToUndefined(talkProviderConfig.baseUrl) == null
|
||||
? {}
|
||||
: { baseUrl: trimToUndefined(talkProviderConfig.baseUrl) }),
|
||||
...(trimToUndefined(talkProviderConfig.modelId) == null
|
||||
? {}
|
||||
: { model: trimToUndefined(talkProviderConfig.modelId) }),
|
||||
...(trimToUndefined(talkProviderConfig.voiceId) == null
|
||||
? {}
|
||||
: { voice: trimToUndefined(talkProviderConfig.voiceId) }),
|
||||
...(asNumber(talkProviderConfig.speed) == null
|
||||
? {}
|
||||
: { speed: asNumber(talkProviderConfig.speed) }),
|
||||
...(trimToUndefined(talkProviderConfig.instructions) == null
|
||||
? {}
|
||||
: { instructions: trimToUndefined(talkProviderConfig.instructions) }),
|
||||
};
|
||||
},
|
||||
resolveTalkOverrides: ({ params }) => ({
|
||||
...(trimToUndefined(params.voiceId) == null
|
||||
? {}
|
||||
: { voice: trimToUndefined(params.voiceId) }),
|
||||
...(trimToUndefined(params.modelId) == null
|
||||
? {}
|
||||
: { model: trimToUndefined(params.modelId) }),
|
||||
...(asNumber(params.speed) == null ? {} : { speed: asNumber(params.speed) }),
|
||||
}),
|
||||
listVoices: async () => OPENAI_TTS_VOICES.map((voice) => ({ id: voice, name: voice })),
|
||||
isConfigured: ({ config }) => Boolean(config.openai.apiKey || process.env.OPENAI_API_KEY),
|
||||
isConfigured: ({ providerConfig }) =>
|
||||
Boolean(readOpenAIProviderConfig(providerConfig).apiKey || process.env.OPENAI_API_KEY),
|
||||
synthesize: async (req) => {
|
||||
const apiKey = req.config.openai.apiKey || process.env.OPENAI_API_KEY;
|
||||
const config = readOpenAIProviderConfig(req.providerConfig);
|
||||
const overrides = readOpenAIOverrides(req.providerOverrides);
|
||||
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("OpenAI API key missing");
|
||||
}
|
||||
@@ -18,13 +183,13 @@ export function buildOpenAISpeechProvider(): SpeechProviderPlugin {
|
||||
const audioBuffer = await openaiTTS({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: req.config.openai.baseUrl,
|
||||
model: req.overrides?.openai?.model ?? req.config.openai.model,
|
||||
voice: req.overrides?.openai?.voice ?? req.config.openai.voice,
|
||||
speed: req.overrides?.openai?.speed ?? req.config.openai.speed,
|
||||
instructions: req.config.openai.instructions,
|
||||
baseUrl: config.baseUrl,
|
||||
model: overrides.model ?? config.model,
|
||||
voice: overrides.voice ?? config.voice,
|
||||
speed: overrides.speed ?? config.speed,
|
||||
instructions: config.instructions,
|
||||
responseFormat,
|
||||
timeoutMs: req.config.timeoutMs,
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
return {
|
||||
audioBuffer,
|
||||
@@ -34,7 +199,8 @@ export function buildOpenAISpeechProvider(): SpeechProviderPlugin {
|
||||
};
|
||||
},
|
||||
synthesizeTelephony: async (req) => {
|
||||
const apiKey = req.config.openai.apiKey || process.env.OPENAI_API_KEY;
|
||||
const config = readOpenAIProviderConfig(req.providerConfig);
|
||||
const apiKey = config.apiKey || process.env.OPENAI_API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error("OpenAI API key missing");
|
||||
}
|
||||
@@ -43,13 +209,13 @@ export function buildOpenAISpeechProvider(): SpeechProviderPlugin {
|
||||
const audioBuffer = await openaiTTS({
|
||||
text: req.text,
|
||||
apiKey,
|
||||
baseUrl: req.config.openai.baseUrl,
|
||||
model: req.config.openai.model,
|
||||
voice: req.config.openai.voice,
|
||||
speed: req.config.openai.speed,
|
||||
instructions: req.config.openai.instructions,
|
||||
baseUrl: config.baseUrl,
|
||||
model: config.model,
|
||||
voice: config.voice,
|
||||
speed: config.speed,
|
||||
instructions: config.instructions,
|
||||
responseFormat: outputFormat,
|
||||
timeoutMs: req.config.timeoutMs,
|
||||
timeoutMs: req.timeoutMs,
|
||||
});
|
||||
return { audioBuffer, outputFormat, sampleRate };
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
||||
export const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
||||
|
||||
export const OPENAI_TTS_MODELS = ["gpt-4o-mini-tts", "tts-1", "tts-1-hd"] as const;
|
||||
|
||||
@@ -21,7 +21,7 @@ export const OPENAI_TTS_VOICES = [
|
||||
|
||||
type OpenAiTtsVoice = (typeof OPENAI_TTS_VOICES)[number];
|
||||
|
||||
function normalizeOpenAITtsBaseUrl(baseUrl?: string): string {
|
||||
export function normalizeOpenAITtsBaseUrl(baseUrl?: string): string {
|
||||
const trimmed = baseUrl?.trim();
|
||||
if (!trimmed) {
|
||||
return DEFAULT_OPENAI_BASE_URL;
|
||||
@@ -36,21 +36,24 @@ function isCustomOpenAIEndpoint(baseUrl?: string): boolean {
|
||||
return normalizeOpenAITtsBaseUrl(process.env.OPENAI_TTS_BASE_URL) !== DEFAULT_OPENAI_BASE_URL;
|
||||
}
|
||||
|
||||
function isValidOpenAIModel(model: string, baseUrl?: string): boolean {
|
||||
export function isValidOpenAIModel(model: string, baseUrl?: string): boolean {
|
||||
if (isCustomOpenAIEndpoint(baseUrl)) {
|
||||
return true;
|
||||
}
|
||||
return OPENAI_TTS_MODELS.includes(model as (typeof OPENAI_TTS_MODELS)[number]);
|
||||
}
|
||||
|
||||
function isValidOpenAIVoice(voice: string, baseUrl?: string): voice is OpenAiTtsVoice {
|
||||
export function isValidOpenAIVoice(voice: string, baseUrl?: string): voice is OpenAiTtsVoice {
|
||||
if (isCustomOpenAIEndpoint(baseUrl)) {
|
||||
return true;
|
||||
}
|
||||
return OPENAI_TTS_VOICES.includes(voice as OpenAiTtsVoice);
|
||||
}
|
||||
|
||||
function resolveOpenAITtsInstructions(model: string, instructions?: string): string | undefined {
|
||||
export function resolveOpenAITtsInstructions(
|
||||
model: string,
|
||||
instructions?: string,
|
||||
): string | undefined {
|
||||
const next = instructions?.trim();
|
||||
return next && model.includes("gpt-4o-mini-tts") ? next : undefined;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { resolveOpenAITtsInstructions } from "../../api.js";
|
||||
import { convertPcmToMulaw8k } from "../telephony-audio.js";
|
||||
|
||||
/**
|
||||
@@ -72,6 +71,11 @@ function trimToUndefined(value: string | undefined): string | undefined {
|
||||
return trimmed ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function resolveOpenAITtsInstructions(model: string, instructions?: string): string | undefined {
|
||||
const next = trimToUndefined(instructions);
|
||||
return next && model.includes("gpt-4o-mini-tts") ? next : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenAI TTS Provider for generating speech audio.
|
||||
*/
|
||||
|
||||
@@ -8,13 +8,6 @@ const DEFAULT_OUTPUT_PATH = "src/plugins/bundled-plugin-metadata.generated.ts";
|
||||
const DEFAULT_ENTRIES_OUTPUT_PATH = "src/generated/bundled-plugin-entries.generated.ts";
|
||||
const MANIFEST_KEY = "openclaw";
|
||||
const FORMATTER_CWD = path.resolve(import.meta.dirname, "..");
|
||||
const CANONICAL_PACKAGE_ID_ALIASES = {
|
||||
"elevenlabs-speech": "elevenlabs",
|
||||
"microsoft-speech": "microsoft",
|
||||
"ollama-provider": "ollama",
|
||||
"sglang-provider": "sglang",
|
||||
"vllm-provider": "vllm",
|
||||
};
|
||||
|
||||
function rewriteEntryToBuiltPath(entry) {
|
||||
if (typeof entry !== "string" || entry.trim().length === 0) {
|
||||
@@ -24,8 +17,12 @@ function rewriteEntryToBuiltPath(entry) {
|
||||
return normalized.replace(/\.[^.]+$/u, ".js");
|
||||
}
|
||||
|
||||
function deriveIdHint({ filePath, packageName, hasMultipleExtensions }) {
|
||||
function deriveIdHint({ filePath, manifestId, packageName, hasMultipleExtensions }) {
|
||||
const base = path.basename(filePath, path.extname(filePath));
|
||||
const normalizedManifestId = manifestId?.trim();
|
||||
if (normalizedManifestId) {
|
||||
return hasMultipleExtensions ? `${normalizedManifestId}/${base}` : normalizedManifestId;
|
||||
}
|
||||
const rawPackageName = packageName?.trim();
|
||||
if (!rawPackageName) {
|
||||
return base;
|
||||
@@ -34,11 +31,10 @@ function deriveIdHint({ filePath, packageName, hasMultipleExtensions }) {
|
||||
const unscoped = rawPackageName.includes("/")
|
||||
? (rawPackageName.split("/").pop() ?? rawPackageName)
|
||||
: rawPackageName;
|
||||
const canonicalPackageId = CANONICAL_PACKAGE_ID_ALIASES[unscoped] ?? unscoped;
|
||||
const normalizedPackageId =
|
||||
canonicalPackageId.endsWith("-provider") && canonicalPackageId.length > "-provider".length
|
||||
? canonicalPackageId.slice(0, -"-provider".length)
|
||||
: canonicalPackageId;
|
||||
unscoped.endsWith("-provider") && unscoped.length > "-provider".length
|
||||
? unscoped.slice(0, -"-provider".length)
|
||||
: unscoped;
|
||||
|
||||
if (!hasMultipleExtensions) {
|
||||
return normalizedPackageId;
|
||||
@@ -184,6 +180,7 @@ export function collectBundledPluginMetadata(params = {}) {
|
||||
dirName: source.dirName,
|
||||
idHint: deriveIdHint({
|
||||
filePath: sourceEntry,
|
||||
manifestId: manifest.id,
|
||||
packageName: typeof packageJson.name === "string" ? packageJson.name : undefined,
|
||||
hasMultipleExtensions: extensions.length > 1,
|
||||
}),
|
||||
@@ -219,19 +216,34 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = ${JSON.stringify(entries, null,
|
||||
export function renderBundledPluginEntriesModule(entries) {
|
||||
const imports = entries
|
||||
.map((entry) => {
|
||||
const identifier = toIdentifier(entry.dirName);
|
||||
const importPath = normalizeGeneratedImportPath(entry.dirName, entry.source.built);
|
||||
return `import ${identifier} from "${importPath}";`;
|
||||
return ` import("${importPath}")`;
|
||||
})
|
||||
.join("\n");
|
||||
const identifiers = entries.map((entry) => toIdentifier(entry.dirName)).join(",\n ");
|
||||
.join(",\n");
|
||||
const bindings = entries
|
||||
.map((entry) => {
|
||||
const identifier = toIdentifier(entry.dirName);
|
||||
return `${identifier}Module`;
|
||||
})
|
||||
.join(",\n ");
|
||||
const identifiers = entries
|
||||
.map((entry) => {
|
||||
const identifier = toIdentifier(entry.dirName);
|
||||
return `${identifier}Module.default`;
|
||||
})
|
||||
.join(",\n ");
|
||||
return `// Auto-generated by ${GENERATED_BY}. Do not edit directly.
|
||||
|
||||
export async function loadGeneratedBundledPluginEntries() {
|
||||
const [
|
||||
${bindings}
|
||||
] = await Promise.all([
|
||||
${imports}
|
||||
|
||||
export const GENERATED_BUNDLED_PLUGIN_ENTRIES = [
|
||||
${identifiers}
|
||||
] as const;
|
||||
]);
|
||||
return [
|
||||
${identifiers}
|
||||
] as const;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ export function buildBuiltinChatCommands(): ChatCommandDefinition[] {
|
||||
"• On – Enable TTS for responses\n" +
|
||||
"• Off – Disable TTS\n" +
|
||||
"• Status – Show current settings\n" +
|
||||
"• Provider – Set voice provider (edge, elevenlabs, openai)\n" +
|
||||
"• Provider – Show or set the voice provider\n" +
|
||||
"• Limit – Set max characters for TTS\n" +
|
||||
"• Summary – Toggle AI summary for long texts\n" +
|
||||
"• Audio – Generate TTS from custom text\n" +
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { logVerbose } from "../../globals.js";
|
||||
import { getSpeechProvider, normalizeSpeechProviderId } from "../../tts/provider-registry.js";
|
||||
import {
|
||||
canonicalizeSpeechProviderId,
|
||||
getSpeechProvider,
|
||||
listSpeechProviders,
|
||||
} from "../../tts/provider-registry.js";
|
||||
import {
|
||||
getResolvedSpeechProviderConfig,
|
||||
getLastTtsAttempt,
|
||||
getTtsMaxLength,
|
||||
getTtsProvider,
|
||||
isSummarizationEnabled,
|
||||
isTtsEnabled,
|
||||
isTtsProviderConfigured,
|
||||
resolveTtsApiKey,
|
||||
resolveTtsConfig,
|
||||
resolveTtsPrefsPath,
|
||||
setLastTtsAttempt,
|
||||
@@ -55,15 +59,13 @@ function ttsUsage(): ReplyPayload {
|
||||
`• /tts summary [on|off] — View/change auto-summary\n` +
|
||||
`• /tts audio <text> — Generate audio from text\n\n` +
|
||||
`**Providers:**\n` +
|
||||
`• microsoft — Microsoft Edge-backed speech (default fallback)\n` +
|
||||
`• openai — High quality (requires API key)\n` +
|
||||
`• elevenlabs — Premium voices (requires API key)\n\n` +
|
||||
`Use /tts provider to list the registered speech providers and their status.\n\n` +
|
||||
`**Text Limit (default: 1500, max: 4096):**\n` +
|
||||
`When text exceeds the limit:\n` +
|
||||
`• Summary ON: AI summarizes, then generates audio\n` +
|
||||
`• Summary OFF: Truncates text, then generates audio\n\n` +
|
||||
`**Examples:**\n` +
|
||||
`/tts provider microsoft\n` +
|
||||
`/tts provider <id>\n` +
|
||||
`/tts limit 2000\n` +
|
||||
`/tts audio Hello, this is a test!`,
|
||||
};
|
||||
@@ -160,30 +162,44 @@ export const handleTtsCommands: CommandHandler = async (params, allowTextCommand
|
||||
if (action === "provider") {
|
||||
const currentProvider = getTtsProvider(config, prefsPath);
|
||||
if (!args.trim()) {
|
||||
const hasOpenAI = Boolean(resolveTtsApiKey(config, "openai"));
|
||||
const hasElevenLabs = Boolean(resolveTtsApiKey(config, "elevenlabs"));
|
||||
const hasMicrosoft = isTtsProviderConfigured(config, "microsoft", params.cfg);
|
||||
const providers = listSpeechProviders(params.cfg);
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: {
|
||||
text:
|
||||
`🎙️ TTS provider\n` +
|
||||
`Primary: ${currentProvider}\n` +
|
||||
`OpenAI key: ${hasOpenAI ? "✅" : "❌"}\n` +
|
||||
`ElevenLabs key: ${hasElevenLabs ? "✅" : "❌"}\n` +
|
||||
`Microsoft enabled: ${hasMicrosoft ? "✅" : "❌"}\n` +
|
||||
`Usage: /tts provider openai | elevenlabs | microsoft`,
|
||||
providers
|
||||
.map(
|
||||
(provider) =>
|
||||
`${provider.label}: ${
|
||||
provider.isConfigured({
|
||||
cfg: params.cfg,
|
||||
providerConfig: getResolvedSpeechProviderConfig(
|
||||
config,
|
||||
provider.id,
|
||||
params.cfg,
|
||||
),
|
||||
timeoutMs: config.timeoutMs,
|
||||
})
|
||||
? "✅"
|
||||
: "❌"
|
||||
}`,
|
||||
)
|
||||
.join("\n") +
|
||||
`\nUsage: /tts provider <id>`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const requested = args.trim().toLowerCase();
|
||||
if (requested !== "edge" && !getSpeechProvider(requested, params.cfg)) {
|
||||
const resolvedProvider = getSpeechProvider(requested, params.cfg);
|
||||
if (!resolvedProvider) {
|
||||
return { shouldContinue: false, reply: ttsUsage() };
|
||||
}
|
||||
|
||||
const nextProvider = normalizeSpeechProviderId(requested) ?? requested;
|
||||
setTtsProvider(prefsPath, requested);
|
||||
const nextProvider = canonicalizeSpeechProviderId(requested, params.cfg) ?? resolvedProvider.id;
|
||||
setTtsProvider(prefsPath, nextProvider);
|
||||
return {
|
||||
shouldContinue: false,
|
||||
reply: { text: `✅ TTS provider set to ${nextProvider}.` },
|
||||
|
||||
@@ -3,7 +3,7 @@ import { redactConfigObject } from "../../config/redact-snapshot.js";
|
||||
import { buildTalkConfigResponse, resolveActiveTalkProviderConfig } from "../../config/talk.js";
|
||||
import type { TalkProviderConfig } from "../../config/types.gateway.js";
|
||||
import type { OpenClawConfig, TtsConfig } from "../../config/types.js";
|
||||
import { normalizeSpeechProviderId } from "../../tts/provider-registry.js";
|
||||
import { canonicalizeSpeechProviderId, getSpeechProvider } from "../../tts/provider-registry.js";
|
||||
import { synthesizeSpeech, type TtsDirectiveOverrides } from "../../tts/tts.js";
|
||||
import {
|
||||
ErrorCodes,
|
||||
@@ -18,7 +18,6 @@ import type { GatewayRequestHandlers } from "./types.js";
|
||||
|
||||
const ADMIN_SCOPE = "operator.admin";
|
||||
const TALK_SECRETS_SCOPE = "operator.talk.secrets";
|
||||
type ElevenLabsVoiceSettings = NonNullable<NonNullable<TtsConfig["elevenlabs"]>["voiceSettings"]>;
|
||||
|
||||
function canReadTalkSecrets(client: { connect?: { scopes?: string[] } } | null): boolean {
|
||||
const scopes = Array.isArray(client?.connect?.scopes) ? client.connect.scopes : [];
|
||||
@@ -33,27 +32,6 @@ function trimString(value: unknown): string | undefined {
|
||||
return trimmed.length > 0 ? trimmed : undefined;
|
||||
}
|
||||
|
||||
function finiteNumber(value: unknown): number | undefined {
|
||||
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
||||
}
|
||||
|
||||
function optionalBoolean(value: unknown): boolean | undefined {
|
||||
return typeof value === "boolean" ? value : undefined;
|
||||
}
|
||||
|
||||
function plainObject(value: unknown): Record<string, unknown> | undefined {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value)
|
||||
? (value as Record<string, unknown>)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function normalizeTextNormalization(value: unknown): "auto" | "on" | "off" | undefined {
|
||||
const normalized = trimString(value)?.toLowerCase();
|
||||
return normalized === "auto" || normalized === "on" || normalized === "off"
|
||||
? normalized
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function normalizeAliasKey(value: string): string {
|
||||
return value.trim().toLowerCase();
|
||||
}
|
||||
@@ -78,100 +56,39 @@ function resolveTalkVoiceId(
|
||||
return requested;
|
||||
}
|
||||
|
||||
function readTalkVoiceSettings(
|
||||
providerConfig: TalkProviderConfig,
|
||||
): ElevenLabsVoiceSettings | undefined {
|
||||
const source = plainObject(providerConfig.voiceSettings);
|
||||
if (!source) {
|
||||
return undefined;
|
||||
}
|
||||
const stability = finiteNumber(source.stability);
|
||||
const similarityBoost = finiteNumber(source.similarityBoost);
|
||||
const style = finiteNumber(source.style);
|
||||
const useSpeakerBoost = optionalBoolean(source.useSpeakerBoost);
|
||||
const speed = finiteNumber(source.speed);
|
||||
const voiceSettings = {
|
||||
...(stability == null ? {} : { stability }),
|
||||
...(similarityBoost == null ? {} : { similarityBoost }),
|
||||
...(style == null ? {} : { style }),
|
||||
...(useSpeakerBoost == null ? {} : { useSpeakerBoost }),
|
||||
...(speed == null ? {} : { speed }),
|
||||
};
|
||||
return Object.keys(voiceSettings).length > 0 ? voiceSettings : undefined;
|
||||
}
|
||||
|
||||
function buildTalkTtsConfig(
|
||||
config: OpenClawConfig,
|
||||
):
|
||||
| { cfg: OpenClawConfig; provider: string; providerConfig: TalkProviderConfig }
|
||||
| { error: string } {
|
||||
const resolved = resolveActiveTalkProviderConfig(config.talk);
|
||||
const provider = normalizeSpeechProviderId(resolved?.provider);
|
||||
const provider = canonicalizeSpeechProviderId(resolved?.provider, config);
|
||||
if (!resolved || !provider) {
|
||||
return { error: "talk.speak unavailable: talk provider not configured" };
|
||||
}
|
||||
|
||||
const speechProvider = getSpeechProvider(provider, config);
|
||||
if (!speechProvider) {
|
||||
return {
|
||||
error: `talk.speak unavailable: speech provider "${provider}" does not support Talk mode`,
|
||||
};
|
||||
}
|
||||
|
||||
const baseTts = config.messages?.tts ?? {};
|
||||
const providerConfig = resolved.config;
|
||||
const resolvedProviderConfig =
|
||||
speechProvider.resolveTalkConfig?.({
|
||||
cfg: config,
|
||||
baseTtsConfig: baseTts as Record<string, unknown>,
|
||||
talkProviderConfig: providerConfig,
|
||||
timeoutMs: baseTts.timeoutMs ?? 30_000,
|
||||
}) ?? providerConfig;
|
||||
const talkTts: TtsConfig = {
|
||||
...baseTts,
|
||||
auto: "always",
|
||||
provider,
|
||||
[provider]: resolvedProviderConfig,
|
||||
};
|
||||
const baseUrl = trimString(providerConfig.baseUrl);
|
||||
const voiceId = trimString(providerConfig.voiceId);
|
||||
const modelId = trimString(providerConfig.modelId);
|
||||
const languageCode = trimString(providerConfig.languageCode);
|
||||
|
||||
if (provider === "elevenlabs") {
|
||||
const seed = finiteNumber(providerConfig.seed);
|
||||
const applyTextNormalization = normalizeTextNormalization(
|
||||
providerConfig.applyTextNormalization,
|
||||
);
|
||||
const voiceSettings = readTalkVoiceSettings(providerConfig);
|
||||
talkTts.elevenlabs = {
|
||||
...baseTts.elevenlabs,
|
||||
...(providerConfig.apiKey === undefined ? {} : { apiKey: providerConfig.apiKey }),
|
||||
...(baseUrl == null ? {} : { baseUrl }),
|
||||
...(voiceId == null ? {} : { voiceId }),
|
||||
...(modelId == null ? {} : { modelId }),
|
||||
...(seed == null ? {} : { seed }),
|
||||
...(applyTextNormalization == null ? {} : { applyTextNormalization }),
|
||||
...(languageCode == null ? {} : { languageCode }),
|
||||
...(voiceSettings == null ? {} : { voiceSettings }),
|
||||
};
|
||||
} else if (provider === "openai") {
|
||||
const speed = finiteNumber(providerConfig.speed);
|
||||
const instructions = trimString(providerConfig.instructions);
|
||||
talkTts.openai = {
|
||||
...baseTts.openai,
|
||||
...(providerConfig.apiKey === undefined ? {} : { apiKey: providerConfig.apiKey }),
|
||||
...(baseUrl == null ? {} : { baseUrl }),
|
||||
...(modelId == null ? {} : { model: modelId }),
|
||||
...(voiceId == null ? {} : { voice: voiceId }),
|
||||
...(speed == null ? {} : { speed }),
|
||||
...(instructions == null ? {} : { instructions }),
|
||||
};
|
||||
} else if (provider === "microsoft") {
|
||||
const outputFormat = trimString(providerConfig.outputFormat);
|
||||
const pitch = trimString(providerConfig.pitch);
|
||||
const rate = trimString(providerConfig.rate);
|
||||
const volume = trimString(providerConfig.volume);
|
||||
const proxy = trimString(providerConfig.proxy);
|
||||
const timeoutMs = finiteNumber(providerConfig.timeoutMs);
|
||||
talkTts.microsoft = {
|
||||
...baseTts.microsoft,
|
||||
enabled: true,
|
||||
...(voiceId == null ? {} : { voice: voiceId }),
|
||||
...(languageCode == null ? {} : { lang: languageCode }),
|
||||
...(outputFormat == null ? {} : { outputFormat }),
|
||||
...(pitch == null ? {} : { pitch }),
|
||||
...(rate == null ? {} : { rate }),
|
||||
...(volume == null ? {} : { volume }),
|
||||
...(proxy == null ? {} : { proxy }),
|
||||
...(timeoutMs == null ? {} : { timeoutMs }),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
provider,
|
||||
@@ -189,60 +106,31 @@ function buildTalkTtsConfig(
|
||||
function buildTalkSpeakOverrides(
|
||||
provider: string,
|
||||
providerConfig: TalkProviderConfig,
|
||||
config: OpenClawConfig,
|
||||
params: Record<string, unknown>,
|
||||
): TtsDirectiveOverrides {
|
||||
const voiceId = resolveTalkVoiceId(providerConfig, trimString(params.voiceId));
|
||||
const modelId = trimString(params.modelId);
|
||||
const outputFormat = trimString(params.outputFormat);
|
||||
const speed = finiteNumber(params.speed);
|
||||
const seed = finiteNumber(params.seed);
|
||||
const normalize = normalizeTextNormalization(params.normalize);
|
||||
const language = trimString(params.language)?.toLowerCase();
|
||||
const overrides: TtsDirectiveOverrides = { provider };
|
||||
|
||||
if (provider === "elevenlabs") {
|
||||
const voiceSettings = {
|
||||
...(speed == null ? {} : { speed }),
|
||||
...(finiteNumber(params.stability) == null
|
||||
? {}
|
||||
: { stability: finiteNumber(params.stability) }),
|
||||
...(finiteNumber(params.similarity) == null
|
||||
? {}
|
||||
: { similarityBoost: finiteNumber(params.similarity) }),
|
||||
...(finiteNumber(params.style) == null ? {} : { style: finiteNumber(params.style) }),
|
||||
...(optionalBoolean(params.speakerBoost) == null
|
||||
? {}
|
||||
: { useSpeakerBoost: optionalBoolean(params.speakerBoost) }),
|
||||
};
|
||||
overrides.elevenlabs = {
|
||||
...(voiceId == null ? {} : { voiceId }),
|
||||
...(modelId == null ? {} : { modelId }),
|
||||
...(outputFormat == null ? {} : { outputFormat }),
|
||||
...(seed == null ? {} : { seed }),
|
||||
...(normalize == null ? {} : { applyTextNormalization: normalize }),
|
||||
...(language == null ? {} : { languageCode: language }),
|
||||
...(Object.keys(voiceSettings).length === 0 ? {} : { voiceSettings }),
|
||||
};
|
||||
return overrides;
|
||||
const speechProvider = getSpeechProvider(provider, config);
|
||||
if (!speechProvider?.resolveTalkOverrides) {
|
||||
return { provider };
|
||||
}
|
||||
|
||||
if (provider === "openai") {
|
||||
overrides.openai = {
|
||||
...(voiceId == null ? {} : { voice: voiceId }),
|
||||
...(modelId == null ? {} : { model: modelId }),
|
||||
...(speed == null ? {} : { speed }),
|
||||
};
|
||||
return overrides;
|
||||
const providerOverrides = speechProvider.resolveTalkOverrides({
|
||||
talkProviderConfig: providerConfig,
|
||||
params: {
|
||||
...params,
|
||||
...(resolveTalkVoiceId(providerConfig, trimString(params.voiceId)) == null
|
||||
? {}
|
||||
: { voiceId: resolveTalkVoiceId(providerConfig, trimString(params.voiceId)) }),
|
||||
},
|
||||
});
|
||||
if (!providerOverrides || Object.keys(providerOverrides).length === 0) {
|
||||
return { provider };
|
||||
}
|
||||
|
||||
if (provider === "microsoft") {
|
||||
overrides.microsoft = {
|
||||
...(voiceId == null ? {} : { voice: voiceId }),
|
||||
...(outputFormat == null ? {} : { outputFormat }),
|
||||
};
|
||||
}
|
||||
|
||||
return overrides;
|
||||
return {
|
||||
provider,
|
||||
providerOverrides: {
|
||||
[provider]: providerOverrides,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function inferMimeType(
|
||||
@@ -350,7 +238,12 @@ export const talkHandlers: GatewayRequestHandlers = {
|
||||
return;
|
||||
}
|
||||
|
||||
const overrides = buildTalkSpeakOverrides(setup.provider, setup.providerConfig, params);
|
||||
const overrides = buildTalkSpeakOverrides(
|
||||
setup.provider,
|
||||
setup.providerConfig,
|
||||
snapshot.config,
|
||||
params,
|
||||
);
|
||||
const result = await synthesizeSpeech({
|
||||
text,
|
||||
cfg: setup.cfg,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { loadConfig } from "../../config/config.js";
|
||||
import {
|
||||
canonicalizeSpeechProviderId,
|
||||
getSpeechProvider,
|
||||
listSpeechProviders,
|
||||
normalizeSpeechProviderId,
|
||||
} from "../../tts/provider-registry.js";
|
||||
import {
|
||||
getResolvedSpeechProviderConfig,
|
||||
getTtsProvider,
|
||||
isTtsEnabled,
|
||||
isTtsProviderConfigured,
|
||||
resolveTtsAutoMode,
|
||||
resolveTtsApiKey,
|
||||
resolveTtsConfig,
|
||||
resolveTtsPrefsPath,
|
||||
resolveTtsProviderOrder,
|
||||
@@ -32,6 +32,15 @@ export const ttsHandlers: GatewayRequestHandlers = {
|
||||
const fallbackProviders = resolveTtsProviderOrder(provider, cfg)
|
||||
.slice(1)
|
||||
.filter((candidate) => isTtsProviderConfigured(config, candidate, cfg));
|
||||
const providerStates = listSpeechProviders(cfg).map((candidate) => ({
|
||||
id: candidate.id,
|
||||
label: candidate.label,
|
||||
configured: candidate.isConfigured({
|
||||
cfg,
|
||||
providerConfig: getResolvedSpeechProviderConfig(config, candidate.id, cfg),
|
||||
timeoutMs: config.timeoutMs,
|
||||
}),
|
||||
}));
|
||||
respond(true, {
|
||||
enabled: isTtsEnabled(config, prefsPath),
|
||||
auto: autoMode,
|
||||
@@ -39,9 +48,7 @@ export const ttsHandlers: GatewayRequestHandlers = {
|
||||
fallbackProvider: fallbackProviders[0] ?? null,
|
||||
fallbackProviders,
|
||||
prefsPath,
|
||||
hasOpenAIKey: Boolean(resolveTtsApiKey(config, "openai")),
|
||||
hasElevenLabsKey: Boolean(resolveTtsApiKey(config, "elevenlabs")),
|
||||
microsoftEnabled: isTtsProviderConfigured(config, "microsoft", cfg),
|
||||
providerStates,
|
||||
});
|
||||
} catch (err) {
|
||||
respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, formatForLog(err)));
|
||||
@@ -102,17 +109,18 @@ export const ttsHandlers: GatewayRequestHandlers = {
|
||||
}
|
||||
},
|
||||
"tts.setProvider": async ({ params, respond }) => {
|
||||
const provider = normalizeSpeechProviderId(
|
||||
typeof params.provider === "string" ? params.provider.trim() : "",
|
||||
);
|
||||
const cfg = loadConfig();
|
||||
const provider = canonicalizeSpeechProviderId(
|
||||
typeof params.provider === "string" ? params.provider.trim() : "",
|
||||
cfg,
|
||||
);
|
||||
if (!provider || !getSpeechProvider(provider, cfg)) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(
|
||||
ErrorCodes.INVALID_REQUEST,
|
||||
"Invalid provider. Use a registered TTS provider id such as openai, elevenlabs, or microsoft.",
|
||||
"Invalid provider. Use a registered TTS provider id.",
|
||||
),
|
||||
);
|
||||
return;
|
||||
@@ -135,7 +143,11 @@ export const ttsHandlers: GatewayRequestHandlers = {
|
||||
providers: listSpeechProviders(cfg).map((provider) => ({
|
||||
id: provider.id,
|
||||
name: provider.label,
|
||||
configured: provider.isConfigured({ cfg, config }),
|
||||
configured: provider.isConfigured({
|
||||
cfg,
|
||||
providerConfig: getResolvedSpeechProviderConfig(config, provider.id, cfg),
|
||||
timeoutMs: config.timeoutMs,
|
||||
}),
|
||||
models: [...(provider.models ?? [])],
|
||||
voices: [...(provider.voices ?? [])],
|
||||
})),
|
||||
|
||||
@@ -1,157 +1,237 @@
|
||||
// Auto-generated by scripts/generate-bundled-plugin-metadata.mjs. Do not edit directly.
|
||||
|
||||
import acpxPlugin from "../../extensions/acpx/index.js";
|
||||
import amazonBedrockPlugin from "../../extensions/amazon-bedrock/index.js";
|
||||
import anthropicPlugin from "../../extensions/anthropic/index.js";
|
||||
import bluebubblesPlugin from "../../extensions/bluebubbles/index.js";
|
||||
import bravePlugin from "../../extensions/brave/index.js";
|
||||
import byteplusPlugin from "../../extensions/byteplus/index.js";
|
||||
import chutesPlugin from "../../extensions/chutes/index.js";
|
||||
import cloudflareAiGatewayPlugin from "../../extensions/cloudflare-ai-gateway/index.js";
|
||||
import copilotProxyPlugin from "../../extensions/copilot-proxy/index.js";
|
||||
import deepgramPlugin from "../../extensions/deepgram/index.js";
|
||||
import deepseekPlugin from "../../extensions/deepseek/index.js";
|
||||
import diagnosticsOtelPlugin from "../../extensions/diagnostics-otel/index.js";
|
||||
import diffsPlugin from "../../extensions/diffs/index.js";
|
||||
import discordPlugin from "../../extensions/discord/index.js";
|
||||
import duckduckgoPlugin from "../../extensions/duckduckgo/index.js";
|
||||
import elevenlabsPlugin from "../../extensions/elevenlabs/index.js";
|
||||
import exaPlugin from "../../extensions/exa/index.js";
|
||||
import falPlugin from "../../extensions/fal/index.js";
|
||||
import feishuPlugin from "../../extensions/feishu/index.js";
|
||||
import firecrawlPlugin from "../../extensions/firecrawl/index.js";
|
||||
import githubCopilotPlugin from "../../extensions/github-copilot/index.js";
|
||||
import googlePlugin from "../../extensions/google/index.js";
|
||||
import googlechatPlugin from "../../extensions/googlechat/index.js";
|
||||
import groqPlugin from "../../extensions/groq/index.js";
|
||||
import huggingfacePlugin from "../../extensions/huggingface/index.js";
|
||||
import imessagePlugin from "../../extensions/imessage/index.js";
|
||||
import ircPlugin from "../../extensions/irc/index.js";
|
||||
import kilocodePlugin from "../../extensions/kilocode/index.js";
|
||||
import kimiCodingPlugin from "../../extensions/kimi-coding/index.js";
|
||||
import linePlugin from "../../extensions/line/index.js";
|
||||
import llmTaskPlugin from "../../extensions/llm-task/index.js";
|
||||
import lobsterPlugin from "../../extensions/lobster/index.js";
|
||||
import matrixPlugin from "../../extensions/matrix/index.js";
|
||||
import mattermostPlugin from "../../extensions/mattermost/index.js";
|
||||
import memoryCorePlugin from "../../extensions/memory-core/index.js";
|
||||
import memoryLancedbPlugin from "../../extensions/memory-lancedb/index.js";
|
||||
import microsoftFoundryPlugin from "../../extensions/microsoft-foundry/index.js";
|
||||
import microsoftPlugin from "../../extensions/microsoft/index.js";
|
||||
import minimaxPlugin from "../../extensions/minimax/index.js";
|
||||
import mistralPlugin from "../../extensions/mistral/index.js";
|
||||
import modelstudioPlugin from "../../extensions/modelstudio/index.js";
|
||||
import moonshotPlugin from "../../extensions/moonshot/index.js";
|
||||
import msteamsPlugin from "../../extensions/msteams/index.js";
|
||||
import nextcloudTalkPlugin from "../../extensions/nextcloud-talk/index.js";
|
||||
import nostrPlugin from "../../extensions/nostr/index.js";
|
||||
import nvidiaPlugin from "../../extensions/nvidia/index.js";
|
||||
import ollamaPlugin from "../../extensions/ollama/index.js";
|
||||
import openProsePlugin from "../../extensions/open-prose/index.js";
|
||||
import openaiPlugin from "../../extensions/openai/index.js";
|
||||
import opencodeGoPlugin from "../../extensions/opencode-go/index.js";
|
||||
import opencodePlugin from "../../extensions/opencode/index.js";
|
||||
import openrouterPlugin from "../../extensions/openrouter/index.js";
|
||||
import openshellPlugin from "../../extensions/openshell/index.js";
|
||||
import perplexityPlugin from "../../extensions/perplexity/index.js";
|
||||
import qianfanPlugin from "../../extensions/qianfan/index.js";
|
||||
import sglangPlugin from "../../extensions/sglang/index.js";
|
||||
import signalPlugin from "../../extensions/signal/index.js";
|
||||
import slackPlugin from "../../extensions/slack/index.js";
|
||||
import synologyChatPlugin from "../../extensions/synology-chat/index.js";
|
||||
import syntheticPlugin from "../../extensions/synthetic/index.js";
|
||||
import tavilyPlugin from "../../extensions/tavily/index.js";
|
||||
import telegramPlugin from "../../extensions/telegram/index.js";
|
||||
import tlonPlugin from "../../extensions/tlon/index.js";
|
||||
import togetherPlugin from "../../extensions/together/index.js";
|
||||
import twitchPlugin from "../../extensions/twitch/index.js";
|
||||
import venicePlugin from "../../extensions/venice/index.js";
|
||||
import vercelAiGatewayPlugin from "../../extensions/vercel-ai-gateway/index.js";
|
||||
import vllmPlugin from "../../extensions/vllm/index.js";
|
||||
import voiceCallPlugin from "../../extensions/voice-call/index.js";
|
||||
import volcenginePlugin from "../../extensions/volcengine/index.js";
|
||||
import whatsappPlugin from "../../extensions/whatsapp/index.js";
|
||||
import xaiPlugin from "../../extensions/xai/index.js";
|
||||
import xiaomiPlugin from "../../extensions/xiaomi/index.js";
|
||||
import zaiPlugin from "../../extensions/zai/index.js";
|
||||
import zaloPlugin from "../../extensions/zalo/index.js";
|
||||
import zalouserPlugin from "../../extensions/zalouser/index.js";
|
||||
|
||||
export const GENERATED_BUNDLED_PLUGIN_ENTRIES = [
|
||||
acpxPlugin,
|
||||
amazonBedrockPlugin,
|
||||
anthropicPlugin,
|
||||
bluebubblesPlugin,
|
||||
bravePlugin,
|
||||
byteplusPlugin,
|
||||
chutesPlugin,
|
||||
cloudflareAiGatewayPlugin,
|
||||
copilotProxyPlugin,
|
||||
deepgramPlugin,
|
||||
deepseekPlugin,
|
||||
diagnosticsOtelPlugin,
|
||||
diffsPlugin,
|
||||
discordPlugin,
|
||||
duckduckgoPlugin,
|
||||
elevenlabsPlugin,
|
||||
exaPlugin,
|
||||
falPlugin,
|
||||
feishuPlugin,
|
||||
firecrawlPlugin,
|
||||
githubCopilotPlugin,
|
||||
googlePlugin,
|
||||
googlechatPlugin,
|
||||
groqPlugin,
|
||||
huggingfacePlugin,
|
||||
imessagePlugin,
|
||||
ircPlugin,
|
||||
kilocodePlugin,
|
||||
kimiCodingPlugin,
|
||||
linePlugin,
|
||||
llmTaskPlugin,
|
||||
lobsterPlugin,
|
||||
matrixPlugin,
|
||||
mattermostPlugin,
|
||||
memoryCorePlugin,
|
||||
memoryLancedbPlugin,
|
||||
microsoftPlugin,
|
||||
microsoftFoundryPlugin,
|
||||
minimaxPlugin,
|
||||
mistralPlugin,
|
||||
modelstudioPlugin,
|
||||
moonshotPlugin,
|
||||
msteamsPlugin,
|
||||
nextcloudTalkPlugin,
|
||||
nostrPlugin,
|
||||
nvidiaPlugin,
|
||||
ollamaPlugin,
|
||||
openProsePlugin,
|
||||
openaiPlugin,
|
||||
opencodePlugin,
|
||||
opencodeGoPlugin,
|
||||
openrouterPlugin,
|
||||
openshellPlugin,
|
||||
perplexityPlugin,
|
||||
qianfanPlugin,
|
||||
sglangPlugin,
|
||||
signalPlugin,
|
||||
slackPlugin,
|
||||
synologyChatPlugin,
|
||||
syntheticPlugin,
|
||||
tavilyPlugin,
|
||||
telegramPlugin,
|
||||
tlonPlugin,
|
||||
togetherPlugin,
|
||||
twitchPlugin,
|
||||
venicePlugin,
|
||||
vercelAiGatewayPlugin,
|
||||
vllmPlugin,
|
||||
voiceCallPlugin,
|
||||
volcenginePlugin,
|
||||
whatsappPlugin,
|
||||
xaiPlugin,
|
||||
xiaomiPlugin,
|
||||
zaiPlugin,
|
||||
zaloPlugin,
|
||||
zalouserPlugin,
|
||||
] as const;
|
||||
export async function loadGeneratedBundledPluginEntries() {
|
||||
const [
|
||||
acpxPluginModule,
|
||||
amazonBedrockPluginModule,
|
||||
anthropicPluginModule,
|
||||
bluebubblesPluginModule,
|
||||
bravePluginModule,
|
||||
byteplusPluginModule,
|
||||
chutesPluginModule,
|
||||
cloudflareAiGatewayPluginModule,
|
||||
copilotProxyPluginModule,
|
||||
deepgramPluginModule,
|
||||
deepseekPluginModule,
|
||||
diagnosticsOtelPluginModule,
|
||||
diffsPluginModule,
|
||||
discordPluginModule,
|
||||
duckduckgoPluginModule,
|
||||
elevenlabsPluginModule,
|
||||
exaPluginModule,
|
||||
falPluginModule,
|
||||
feishuPluginModule,
|
||||
firecrawlPluginModule,
|
||||
githubCopilotPluginModule,
|
||||
googlePluginModule,
|
||||
googlechatPluginModule,
|
||||
groqPluginModule,
|
||||
huggingfacePluginModule,
|
||||
imessagePluginModule,
|
||||
ircPluginModule,
|
||||
kilocodePluginModule,
|
||||
kimiCodingPluginModule,
|
||||
linePluginModule,
|
||||
llmTaskPluginModule,
|
||||
lobsterPluginModule,
|
||||
matrixPluginModule,
|
||||
mattermostPluginModule,
|
||||
memoryCorePluginModule,
|
||||
memoryLancedbPluginModule,
|
||||
microsoftPluginModule,
|
||||
microsoftFoundryPluginModule,
|
||||
minimaxPluginModule,
|
||||
mistralPluginModule,
|
||||
modelstudioPluginModule,
|
||||
moonshotPluginModule,
|
||||
msteamsPluginModule,
|
||||
nextcloudTalkPluginModule,
|
||||
nostrPluginModule,
|
||||
nvidiaPluginModule,
|
||||
ollamaPluginModule,
|
||||
openProsePluginModule,
|
||||
openaiPluginModule,
|
||||
opencodePluginModule,
|
||||
opencodeGoPluginModule,
|
||||
openrouterPluginModule,
|
||||
openshellPluginModule,
|
||||
perplexityPluginModule,
|
||||
qianfanPluginModule,
|
||||
sglangPluginModule,
|
||||
signalPluginModule,
|
||||
slackPluginModule,
|
||||
synologyChatPluginModule,
|
||||
syntheticPluginModule,
|
||||
tavilyPluginModule,
|
||||
telegramPluginModule,
|
||||
tlonPluginModule,
|
||||
togetherPluginModule,
|
||||
twitchPluginModule,
|
||||
venicePluginModule,
|
||||
vercelAiGatewayPluginModule,
|
||||
vllmPluginModule,
|
||||
voiceCallPluginModule,
|
||||
volcenginePluginModule,
|
||||
whatsappPluginModule,
|
||||
xaiPluginModule,
|
||||
xiaomiPluginModule,
|
||||
zaiPluginModule,
|
||||
zaloPluginModule,
|
||||
zalouserPluginModule,
|
||||
] = await Promise.all([
|
||||
import("../../extensions/acpx/index.js"),
|
||||
import("../../extensions/amazon-bedrock/index.js"),
|
||||
import("../../extensions/anthropic/index.js"),
|
||||
import("../../extensions/bluebubbles/index.js"),
|
||||
import("../../extensions/brave/index.js"),
|
||||
import("../../extensions/byteplus/index.js"),
|
||||
import("../../extensions/chutes/index.js"),
|
||||
import("../../extensions/cloudflare-ai-gateway/index.js"),
|
||||
import("../../extensions/copilot-proxy/index.js"),
|
||||
import("../../extensions/deepgram/index.js"),
|
||||
import("../../extensions/deepseek/index.js"),
|
||||
import("../../extensions/diagnostics-otel/index.js"),
|
||||
import("../../extensions/diffs/index.js"),
|
||||
import("../../extensions/discord/index.js"),
|
||||
import("../../extensions/duckduckgo/index.js"),
|
||||
import("../../extensions/elevenlabs/index.js"),
|
||||
import("../../extensions/exa/index.js"),
|
||||
import("../../extensions/fal/index.js"),
|
||||
import("../../extensions/feishu/index.js"),
|
||||
import("../../extensions/firecrawl/index.js"),
|
||||
import("../../extensions/github-copilot/index.js"),
|
||||
import("../../extensions/google/index.js"),
|
||||
import("../../extensions/googlechat/index.js"),
|
||||
import("../../extensions/groq/index.js"),
|
||||
import("../../extensions/huggingface/index.js"),
|
||||
import("../../extensions/imessage/index.js"),
|
||||
import("../../extensions/irc/index.js"),
|
||||
import("../../extensions/kilocode/index.js"),
|
||||
import("../../extensions/kimi-coding/index.js"),
|
||||
import("../../extensions/line/index.js"),
|
||||
import("../../extensions/llm-task/index.js"),
|
||||
import("../../extensions/lobster/index.js"),
|
||||
import("../../extensions/matrix/index.js"),
|
||||
import("../../extensions/mattermost/index.js"),
|
||||
import("../../extensions/memory-core/index.js"),
|
||||
import("../../extensions/memory-lancedb/index.js"),
|
||||
import("../../extensions/microsoft/index.js"),
|
||||
import("../../extensions/microsoft-foundry/index.js"),
|
||||
import("../../extensions/minimax/index.js"),
|
||||
import("../../extensions/mistral/index.js"),
|
||||
import("../../extensions/modelstudio/index.js"),
|
||||
import("../../extensions/moonshot/index.js"),
|
||||
import("../../extensions/msteams/index.js"),
|
||||
import("../../extensions/nextcloud-talk/index.js"),
|
||||
import("../../extensions/nostr/index.js"),
|
||||
import("../../extensions/nvidia/index.js"),
|
||||
import("../../extensions/ollama/index.js"),
|
||||
import("../../extensions/open-prose/index.js"),
|
||||
import("../../extensions/openai/index.js"),
|
||||
import("../../extensions/opencode/index.js"),
|
||||
import("../../extensions/opencode-go/index.js"),
|
||||
import("../../extensions/openrouter/index.js"),
|
||||
import("../../extensions/openshell/index.js"),
|
||||
import("../../extensions/perplexity/index.js"),
|
||||
import("../../extensions/qianfan/index.js"),
|
||||
import("../../extensions/sglang/index.js"),
|
||||
import("../../extensions/signal/index.js"),
|
||||
import("../../extensions/slack/index.js"),
|
||||
import("../../extensions/synology-chat/index.js"),
|
||||
import("../../extensions/synthetic/index.js"),
|
||||
import("../../extensions/tavily/index.js"),
|
||||
import("../../extensions/telegram/index.js"),
|
||||
import("../../extensions/tlon/index.js"),
|
||||
import("../../extensions/together/index.js"),
|
||||
import("../../extensions/twitch/index.js"),
|
||||
import("../../extensions/venice/index.js"),
|
||||
import("../../extensions/vercel-ai-gateway/index.js"),
|
||||
import("../../extensions/vllm/index.js"),
|
||||
import("../../extensions/voice-call/index.js"),
|
||||
import("../../extensions/volcengine/index.js"),
|
||||
import("../../extensions/whatsapp/index.js"),
|
||||
import("../../extensions/xai/index.js"),
|
||||
import("../../extensions/xiaomi/index.js"),
|
||||
import("../../extensions/zai/index.js"),
|
||||
import("../../extensions/zalo/index.js"),
|
||||
import("../../extensions/zalouser/index.js"),
|
||||
]);
|
||||
return [
|
||||
acpxPluginModule.default,
|
||||
amazonBedrockPluginModule.default,
|
||||
anthropicPluginModule.default,
|
||||
bluebubblesPluginModule.default,
|
||||
bravePluginModule.default,
|
||||
byteplusPluginModule.default,
|
||||
chutesPluginModule.default,
|
||||
cloudflareAiGatewayPluginModule.default,
|
||||
copilotProxyPluginModule.default,
|
||||
deepgramPluginModule.default,
|
||||
deepseekPluginModule.default,
|
||||
diagnosticsOtelPluginModule.default,
|
||||
diffsPluginModule.default,
|
||||
discordPluginModule.default,
|
||||
duckduckgoPluginModule.default,
|
||||
elevenlabsPluginModule.default,
|
||||
exaPluginModule.default,
|
||||
falPluginModule.default,
|
||||
feishuPluginModule.default,
|
||||
firecrawlPluginModule.default,
|
||||
githubCopilotPluginModule.default,
|
||||
googlePluginModule.default,
|
||||
googlechatPluginModule.default,
|
||||
groqPluginModule.default,
|
||||
huggingfacePluginModule.default,
|
||||
imessagePluginModule.default,
|
||||
ircPluginModule.default,
|
||||
kilocodePluginModule.default,
|
||||
kimiCodingPluginModule.default,
|
||||
linePluginModule.default,
|
||||
llmTaskPluginModule.default,
|
||||
lobsterPluginModule.default,
|
||||
matrixPluginModule.default,
|
||||
mattermostPluginModule.default,
|
||||
memoryCorePluginModule.default,
|
||||
memoryLancedbPluginModule.default,
|
||||
microsoftPluginModule.default,
|
||||
microsoftFoundryPluginModule.default,
|
||||
minimaxPluginModule.default,
|
||||
mistralPluginModule.default,
|
||||
modelstudioPluginModule.default,
|
||||
moonshotPluginModule.default,
|
||||
msteamsPluginModule.default,
|
||||
nextcloudTalkPluginModule.default,
|
||||
nostrPluginModule.default,
|
||||
nvidiaPluginModule.default,
|
||||
ollamaPluginModule.default,
|
||||
openProsePluginModule.default,
|
||||
openaiPluginModule.default,
|
||||
opencodePluginModule.default,
|
||||
opencodeGoPluginModule.default,
|
||||
openrouterPluginModule.default,
|
||||
openshellPluginModule.default,
|
||||
perplexityPluginModule.default,
|
||||
qianfanPluginModule.default,
|
||||
sglangPluginModule.default,
|
||||
signalPluginModule.default,
|
||||
slackPluginModule.default,
|
||||
synologyChatPluginModule.default,
|
||||
syntheticPluginModule.default,
|
||||
tavilyPluginModule.default,
|
||||
telegramPluginModule.default,
|
||||
tlonPluginModule.default,
|
||||
togetherPluginModule.default,
|
||||
twitchPluginModule.default,
|
||||
venicePluginModule.default,
|
||||
vercelAiGatewayPluginModule.default,
|
||||
vllmPluginModule.default,
|
||||
voiceCallPluginModule.default,
|
||||
volcenginePluginModule.default,
|
||||
whatsappPluginModule.default,
|
||||
xaiPluginModule.default,
|
||||
xiaomiPluginModule.default,
|
||||
zaiPluginModule.default,
|
||||
zaloPluginModule.default,
|
||||
zalouserPluginModule.default,
|
||||
] as const;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
// Shared speech-provider implementation helpers for bundled and third-party plugins.
|
||||
|
||||
export type { SpeechProviderPlugin } from "../plugins/types.js";
|
||||
export type { SpeechVoiceOption } from "../tts/provider-types.js";
|
||||
export type {
|
||||
SpeechDirectiveTokenParseContext,
|
||||
SpeechDirectiveTokenParseResult,
|
||||
SpeechListVoicesRequest,
|
||||
SpeechModelOverridePolicy,
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderConfiguredContext,
|
||||
SpeechProviderResolveConfigContext,
|
||||
SpeechProviderResolveTalkConfigContext,
|
||||
SpeechProviderResolveTalkOverridesContext,
|
||||
SpeechProviderOverrides,
|
||||
SpeechSynthesisRequest,
|
||||
SpeechTelephonySynthesisRequest,
|
||||
SpeechVoiceOption,
|
||||
TtsDirectiveOverrides,
|
||||
TtsDirectiveParseResult,
|
||||
} from "../tts/provider-types.js";
|
||||
|
||||
export {
|
||||
normalizeApplyTextNormalization,
|
||||
normalizeLanguageCode,
|
||||
normalizeSeed,
|
||||
parseTtsDirectives,
|
||||
requireInRange,
|
||||
} from "../tts/tts-core.js";
|
||||
export { parseTtsDirectives } from "../tts/directives.js";
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
// Public speech helpers for bundled or third-party plugins.
|
||||
|
||||
export { parseTtsDirectives } from "../tts/tts-core.js";
|
||||
export type { SpeechVoiceOption } from "../tts/provider-types.js";
|
||||
export { parseTtsDirectives } from "../tts/directives.js";
|
||||
export type {
|
||||
SpeechModelOverridePolicy,
|
||||
SpeechVoiceOption,
|
||||
TtsDirectiveOverrides,
|
||||
TtsDirectiveParseResult,
|
||||
} from "../tts/provider-types.js";
|
||||
|
||||
@@ -8,7 +8,6 @@ export {
|
||||
TtsModeSchema,
|
||||
TtsProviderSchema,
|
||||
} from "../config/zod-schema.core.js";
|
||||
export { resolveOpenAITtsInstructions } from "../tts/tts-core.js";
|
||||
export type { GatewayRequestHandlerOptions } from "../gateway/server-methods/types.js";
|
||||
export {
|
||||
isRequestBodyLimitError,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GENERATED_BUNDLED_PLUGIN_ENTRIES } from "../generated/bundled-plugin-entries.generated.js";
|
||||
import { loadGeneratedBundledPluginEntries } from "../generated/bundled-plugin-entries.generated.js";
|
||||
import type { OpenClawPluginDefinition } from "./types.js";
|
||||
|
||||
type BundledRegistrablePlugin = OpenClawPluginDefinition & {
|
||||
@@ -7,4 +7,4 @@ type BundledRegistrablePlugin = OpenClawPluginDefinition & {
|
||||
};
|
||||
|
||||
export const BUNDLED_PLUGIN_ENTRIES =
|
||||
GENERATED_BUNDLED_PLUGIN_ENTRIES as unknown as readonly BundledRegistrablePlugin[];
|
||||
(await loadGeneratedBundledPluginEntries()) as unknown as readonly BundledRegistrablePlugin[];
|
||||
|
||||
@@ -249,7 +249,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "brave",
|
||||
idHint: "brave-plugin",
|
||||
idHint: "brave",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -820,7 +820,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "duckduckgo",
|
||||
idHint: "duckduckgo-plugin",
|
||||
idHint: "duckduckgo",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -889,7 +889,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "exa",
|
||||
idHint: "exa-plugin",
|
||||
idHint: "exa",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -1021,7 +1021,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "firecrawl",
|
||||
idHint: "firecrawl-plugin",
|
||||
idHint: "firecrawl",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -1109,7 +1109,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "google",
|
||||
idHint: "google-plugin",
|
||||
idHint: "google",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -2556,7 +2556,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "openshell",
|
||||
idHint: "openshell-sandbox",
|
||||
idHint: "openshell",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -2670,7 +2670,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "perplexity",
|
||||
idHint: "perplexity-plugin",
|
||||
idHint: "perplexity",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -2966,7 +2966,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "tavily",
|
||||
idHint: "tavily-plugin",
|
||||
idHint: "tavily",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
@@ -4007,7 +4007,7 @@ export const GENERATED_BUNDLED_PLUGIN_METADATA = [
|
||||
},
|
||||
{
|
||||
dirName: "xai",
|
||||
idHint: "xai-plugin",
|
||||
idHint: "xai",
|
||||
source: {
|
||||
source: "./index.ts",
|
||||
built: "index.js",
|
||||
|
||||
@@ -32,7 +32,13 @@ import type { MediaUnderstandingProvider } from "../media-understanding/types.js
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import type { RuntimeWebSearchMetadata } from "../secrets/runtime-web-tools.types.js";
|
||||
import type {
|
||||
SpeechDirectiveTokenParseContext,
|
||||
SpeechDirectiveTokenParseResult,
|
||||
SpeechProviderConfiguredContext,
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderResolveConfigContext,
|
||||
SpeechProviderResolveTalkConfigContext,
|
||||
SpeechProviderResolveTalkOverridesContext,
|
||||
SpeechListVoicesRequest,
|
||||
SpeechProviderId,
|
||||
SpeechSynthesisRequest,
|
||||
@@ -939,8 +945,15 @@ export type SpeechProviderPlugin = {
|
||||
id: SpeechProviderId;
|
||||
label: string;
|
||||
aliases?: string[];
|
||||
autoSelectOrder?: number;
|
||||
models?: readonly string[];
|
||||
voices?: readonly string[];
|
||||
resolveConfig?: (ctx: SpeechProviderResolveConfigContext) => SpeechProviderConfig;
|
||||
parseDirectiveToken?: (ctx: SpeechDirectiveTokenParseContext) => SpeechDirectiveTokenParseResult;
|
||||
resolveTalkConfig?: (ctx: SpeechProviderResolveTalkConfigContext) => SpeechProviderConfig;
|
||||
resolveTalkOverrides?: (
|
||||
ctx: SpeechProviderResolveTalkOverridesContext,
|
||||
) => SpeechProviderConfig | undefined;
|
||||
isConfigured: (ctx: SpeechProviderConfiguredContext) => boolean;
|
||||
synthesize: (req: SpeechSynthesisRequest) => Promise<SpeechSynthesisResult>;
|
||||
synthesizeTelephony?: (
|
||||
|
||||
160
src/tts/directives.ts
Normal file
160
src/tts/directives.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { SpeechProviderPlugin } from "../plugins/types.js";
|
||||
import { listSpeechProviders } from "./provider-registry.js";
|
||||
import type {
|
||||
SpeechModelOverridePolicy,
|
||||
SpeechProviderConfig,
|
||||
SpeechProviderOverrides,
|
||||
TtsDirectiveOverrides,
|
||||
TtsDirectiveParseResult,
|
||||
} from "./provider-types.js";
|
||||
|
||||
type ParseTtsDirectiveOptions = {
|
||||
cfg?: OpenClawConfig;
|
||||
providers?: readonly SpeechProviderPlugin[];
|
||||
providerConfigs?: Record<string, SpeechProviderConfig>;
|
||||
openaiBaseUrl?: string;
|
||||
};
|
||||
|
||||
function buildProviderOrder(left: SpeechProviderPlugin, right: SpeechProviderPlugin): number {
|
||||
const leftOrder = left.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = right.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
return left.id.localeCompare(right.id);
|
||||
}
|
||||
|
||||
function resolveDirectiveProviders(options?: ParseTtsDirectiveOptions): SpeechProviderPlugin[] {
|
||||
if (options?.providers) {
|
||||
return [...options.providers].toSorted(buildProviderOrder);
|
||||
}
|
||||
return listSpeechProviders(options?.cfg).toSorted(buildProviderOrder);
|
||||
}
|
||||
|
||||
function resolveDirectiveProviderConfig(
|
||||
provider: SpeechProviderPlugin,
|
||||
options?: ParseTtsDirectiveOptions,
|
||||
): SpeechProviderConfig | undefined {
|
||||
const explicit = options?.providerConfigs?.[provider.id];
|
||||
if (explicit) {
|
||||
return explicit;
|
||||
}
|
||||
if (provider.id === "openai" && options?.openaiBaseUrl) {
|
||||
return { baseUrl: options.openaiBaseUrl };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function mergeProviderOverrides(
|
||||
target: TtsDirectiveOverrides,
|
||||
providerId: string,
|
||||
next: SpeechProviderOverrides,
|
||||
): void {
|
||||
target.providerOverrides = {
|
||||
...target.providerOverrides,
|
||||
[providerId]: {
|
||||
...target.providerOverrides?.[providerId],
|
||||
...next,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function resolveLegacyOptions(
|
||||
optionsOrOpenaiBaseUrl?: ParseTtsDirectiveOptions | string,
|
||||
): ParseTtsDirectiveOptions | undefined {
|
||||
if (typeof optionsOrOpenaiBaseUrl === "string") {
|
||||
return { openaiBaseUrl: optionsOrOpenaiBaseUrl };
|
||||
}
|
||||
return optionsOrOpenaiBaseUrl;
|
||||
}
|
||||
|
||||
export function parseTtsDirectives(
|
||||
text: string,
|
||||
policy: SpeechModelOverridePolicy,
|
||||
optionsOrOpenaiBaseUrl?: ParseTtsDirectiveOptions | string,
|
||||
): TtsDirectiveParseResult {
|
||||
if (!policy.enabled) {
|
||||
return { cleanedText: text, overrides: {}, warnings: [], hasDirective: false };
|
||||
}
|
||||
|
||||
const options = resolveLegacyOptions(optionsOrOpenaiBaseUrl);
|
||||
const providers = resolveDirectiveProviders(options);
|
||||
const overrides: TtsDirectiveOverrides = {};
|
||||
const warnings: string[] = [];
|
||||
let cleanedText = text;
|
||||
let hasDirective = false;
|
||||
|
||||
const blockRegex = /\[\[tts:text\]\]([\s\S]*?)\[\[\/tts:text\]\]/gi;
|
||||
cleanedText = cleanedText.replace(blockRegex, (_match, inner: string) => {
|
||||
hasDirective = true;
|
||||
if (policy.allowText && overrides.ttsText == null) {
|
||||
overrides.ttsText = inner.trim();
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
const directiveRegex = /\[\[tts:([^\]]+)\]\]/gi;
|
||||
cleanedText = cleanedText.replace(directiveRegex, (_match, body: string) => {
|
||||
hasDirective = true;
|
||||
const tokens = body.split(/\s+/).filter(Boolean);
|
||||
for (const token of tokens) {
|
||||
const eqIndex = token.indexOf("=");
|
||||
if (eqIndex === -1) {
|
||||
continue;
|
||||
}
|
||||
const rawKey = token.slice(0, eqIndex).trim();
|
||||
const rawValue = token.slice(eqIndex + 1).trim();
|
||||
if (!rawKey || !rawValue) {
|
||||
continue;
|
||||
}
|
||||
const key = rawKey.toLowerCase();
|
||||
if (key === "provider") {
|
||||
if (policy.allowProvider) {
|
||||
const providerId = rawValue.trim().toLowerCase();
|
||||
if (providerId) {
|
||||
overrides.provider = providerId;
|
||||
} else {
|
||||
warnings.push("invalid provider id");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
let handled = false;
|
||||
for (const provider of providers) {
|
||||
const parsed = provider.parseDirectiveToken?.({
|
||||
key,
|
||||
value: rawValue,
|
||||
policy,
|
||||
providerConfig: resolveDirectiveProviderConfig(provider, options),
|
||||
currentOverrides: overrides.providerOverrides?.[provider.id],
|
||||
});
|
||||
if (!parsed?.handled) {
|
||||
continue;
|
||||
}
|
||||
handled = true;
|
||||
if (parsed.overrides) {
|
||||
mergeProviderOverrides(overrides, provider.id, parsed.overrides);
|
||||
}
|
||||
if (parsed.warnings?.length) {
|
||||
warnings.push(...parsed.warnings);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
return {
|
||||
cleanedText,
|
||||
ttsText: overrides.ttsText,
|
||||
hasDirective,
|
||||
overrides,
|
||||
warnings,
|
||||
};
|
||||
}
|
||||
@@ -13,6 +13,7 @@ vi.mock("../plugins/loader.js", () => ({
|
||||
|
||||
let getSpeechProvider: typeof import("./provider-registry.js").getSpeechProvider;
|
||||
let listSpeechProviders: typeof import("./provider-registry.js").listSpeechProviders;
|
||||
let canonicalizeSpeechProviderId: typeof import("./provider-registry.js").canonicalizeSpeechProviderId;
|
||||
let normalizeSpeechProviderId: typeof import("./provider-registry.js").normalizeSpeechProviderId;
|
||||
|
||||
function createSpeechProvider(id: string, aliases?: string[]): SpeechProviderPlugin {
|
||||
@@ -36,8 +37,12 @@ describe("speech provider registry", () => {
|
||||
resetPluginRuntimeStateForTest();
|
||||
loadOpenClawPluginsMock.mockReset();
|
||||
loadOpenClawPluginsMock.mockReturnValue(createEmptyPluginRegistry());
|
||||
({ getSpeechProvider, listSpeechProviders, normalizeSpeechProviderId } =
|
||||
await import("./provider-registry.js"));
|
||||
({
|
||||
getSpeechProvider,
|
||||
listSpeechProviders,
|
||||
canonicalizeSpeechProviderId,
|
||||
normalizeSpeechProviderId,
|
||||
} = await import("./provider-registry.js"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -86,7 +91,19 @@ describe("speech provider registry", () => {
|
||||
expect(getSpeechProvider("openai")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("normalizes the legacy edge alias to microsoft", () => {
|
||||
expect(normalizeSpeechProviderId("edge")).toBe("microsoft");
|
||||
it("canonicalizes the legacy edge alias to microsoft", () => {
|
||||
setActivePluginRegistry({
|
||||
...createEmptyPluginRegistry(),
|
||||
speechProviders: [
|
||||
{
|
||||
pluginId: "test-microsoft",
|
||||
source: "test",
|
||||
provider: createSpeechProvider("microsoft", ["edge"]),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(normalizeSpeechProviderId("edge")).toBe("edge");
|
||||
expect(canonicalizeSpeechProviderId("edge")).toBe("microsoft");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,11 +12,7 @@ function trimToUndefined(value: string | undefined): string | undefined {
|
||||
export function normalizeSpeechProviderId(
|
||||
providerId: string | undefined,
|
||||
): SpeechProviderId | undefined {
|
||||
const normalized = trimToUndefined(providerId);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
return normalized === "edge" ? "microsoft" : normalized;
|
||||
return trimToUndefined(providerId);
|
||||
}
|
||||
|
||||
function resolveSpeechProviderPluginEntries(cfg?: OpenClawConfig): SpeechProviderPlugin[] {
|
||||
@@ -70,3 +66,14 @@ export function getSpeechProvider(
|
||||
}
|
||||
return buildProviderMaps(cfg).aliases.get(normalized);
|
||||
}
|
||||
|
||||
export function canonicalizeSpeechProviderId(
|
||||
providerId: string | undefined,
|
||||
cfg?: OpenClawConfig,
|
||||
): SpeechProviderId | undefined {
|
||||
const normalized = normalizeSpeechProviderId(providerId);
|
||||
if (!normalized) {
|
||||
return undefined;
|
||||
}
|
||||
return getSpeechProvider(normalized, cfg)?.id ?? normalized;
|
||||
}
|
||||
|
||||
@@ -1,21 +1,52 @@
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { ResolvedTtsConfig, TtsDirectiveOverrides } from "./tts.js";
|
||||
import type { TalkProviderConfig } from "../config/types.gateway.js";
|
||||
|
||||
export type SpeechProviderId = string;
|
||||
|
||||
export type SpeechSynthesisTarget = "audio-file" | "voice-note";
|
||||
|
||||
export type SpeechProviderConfig = Record<string, unknown>;
|
||||
|
||||
export type SpeechProviderOverrides = Record<string, unknown>;
|
||||
|
||||
export type SpeechModelOverridePolicy = {
|
||||
enabled: boolean;
|
||||
allowText: boolean;
|
||||
allowProvider: boolean;
|
||||
allowVoice: boolean;
|
||||
allowModelId: boolean;
|
||||
allowVoiceSettings: boolean;
|
||||
allowNormalization: boolean;
|
||||
allowSeed: boolean;
|
||||
};
|
||||
|
||||
export type TtsDirectiveOverrides = {
|
||||
ttsText?: string;
|
||||
provider?: SpeechProviderId;
|
||||
providerOverrides?: Record<string, SpeechProviderOverrides>;
|
||||
};
|
||||
|
||||
export type TtsDirectiveParseResult = {
|
||||
cleanedText: string;
|
||||
ttsText?: string;
|
||||
hasDirective: boolean;
|
||||
overrides: TtsDirectiveOverrides;
|
||||
warnings: string[];
|
||||
};
|
||||
|
||||
export type SpeechProviderConfiguredContext = {
|
||||
cfg?: OpenClawConfig;
|
||||
config: ResolvedTtsConfig;
|
||||
providerConfig: SpeechProviderConfig;
|
||||
timeoutMs: number;
|
||||
};
|
||||
|
||||
export type SpeechSynthesisRequest = {
|
||||
text: string;
|
||||
cfg: OpenClawConfig;
|
||||
config: ResolvedTtsConfig;
|
||||
providerConfig: SpeechProviderConfig;
|
||||
target: SpeechSynthesisTarget;
|
||||
overrides?: TtsDirectiveOverrides;
|
||||
providerOverrides?: SpeechProviderOverrides;
|
||||
timeoutMs: number;
|
||||
};
|
||||
|
||||
export type SpeechSynthesisResult = {
|
||||
@@ -28,7 +59,8 @@ export type SpeechSynthesisResult = {
|
||||
export type SpeechTelephonySynthesisRequest = {
|
||||
text: string;
|
||||
cfg: OpenClawConfig;
|
||||
config: ResolvedTtsConfig;
|
||||
providerConfig: SpeechProviderConfig;
|
||||
timeoutMs: number;
|
||||
};
|
||||
|
||||
export type SpeechTelephonySynthesisResult = {
|
||||
@@ -49,7 +81,39 @@ export type SpeechVoiceOption = {
|
||||
|
||||
export type SpeechListVoicesRequest = {
|
||||
cfg?: OpenClawConfig;
|
||||
config?: ResolvedTtsConfig;
|
||||
providerConfig?: SpeechProviderConfig;
|
||||
apiKey?: string;
|
||||
baseUrl?: string;
|
||||
};
|
||||
|
||||
export type SpeechProviderResolveConfigContext = {
|
||||
cfg: OpenClawConfig;
|
||||
rawConfig: Record<string, unknown>;
|
||||
timeoutMs: number;
|
||||
};
|
||||
|
||||
export type SpeechDirectiveTokenParseContext = {
|
||||
key: string;
|
||||
value: string;
|
||||
policy: SpeechModelOverridePolicy;
|
||||
providerConfig?: SpeechProviderConfig;
|
||||
currentOverrides?: SpeechProviderOverrides;
|
||||
};
|
||||
|
||||
export type SpeechDirectiveTokenParseResult = {
|
||||
handled: boolean;
|
||||
overrides?: SpeechProviderOverrides;
|
||||
warnings?: string[];
|
||||
};
|
||||
|
||||
export type SpeechProviderResolveTalkConfigContext = {
|
||||
cfg: OpenClawConfig;
|
||||
baseTtsConfig: Record<string, unknown>;
|
||||
talkProviderConfig: TalkProviderConfig;
|
||||
timeoutMs: number;
|
||||
};
|
||||
|
||||
export type SpeechProviderResolveTalkOverridesContext = {
|
||||
talkProviderConfig: TalkProviderConfig;
|
||||
params: Record<string, unknown>;
|
||||
};
|
||||
|
||||
@@ -10,33 +10,10 @@ import {
|
||||
import { resolveModelAsync } from "../agents/pi-embedded-runner/model.js";
|
||||
import { prepareModelForSimpleCompletion } from "../agents/simple-completion-transport.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type {
|
||||
ResolvedTtsConfig,
|
||||
ResolvedTtsModelOverrides,
|
||||
TtsDirectiveOverrides,
|
||||
TtsDirectiveParseResult,
|
||||
} from "./tts.js";
|
||||
import type { ResolvedTtsConfig } from "./tts.js";
|
||||
|
||||
export const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
||||
const TEMP_FILE_CLEANUP_DELAY_MS = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
export function isValidVoiceId(voiceId: string): boolean {
|
||||
return /^[a-zA-Z0-9]{10,40}$/.test(voiceId);
|
||||
}
|
||||
|
||||
function normalizeOpenAITtsBaseUrl(baseUrl?: string): string {
|
||||
const trimmed = baseUrl?.trim();
|
||||
if (!trimmed) {
|
||||
return DEFAULT_OPENAI_BASE_URL;
|
||||
}
|
||||
return trimmed.replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
function trimToUndefined(value?: string): string | undefined {
|
||||
const trimmed = value?.trim();
|
||||
return trimmed ? trimmed : undefined;
|
||||
}
|
||||
|
||||
export function requireInRange(value: number, min: number, max: number, label: string): void {
|
||||
if (!Number.isFinite(value) || value < min || value > max) {
|
||||
throw new Error(`${label} must be between ${min} and ${max}`);
|
||||
@@ -78,317 +55,6 @@ export function normalizeSeed(seed?: number): number | undefined {
|
||||
return next;
|
||||
}
|
||||
|
||||
function parseBooleanValue(value: string): boolean | undefined {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (["true", "1", "yes", "on"].includes(normalized)) {
|
||||
return true;
|
||||
}
|
||||
if (["false", "0", "no", "off"].includes(normalized)) {
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseNumberValue(value: string): number | undefined {
|
||||
const parsed = Number.parseFloat(value);
|
||||
return Number.isFinite(parsed) ? parsed : undefined;
|
||||
}
|
||||
|
||||
export function parseTtsDirectives(
|
||||
text: string,
|
||||
policy: ResolvedTtsModelOverrides,
|
||||
openaiBaseUrl?: string,
|
||||
): TtsDirectiveParseResult {
|
||||
if (!policy.enabled) {
|
||||
return { cleanedText: text, overrides: {}, warnings: [], hasDirective: false };
|
||||
}
|
||||
|
||||
const overrides: TtsDirectiveOverrides = {};
|
||||
const warnings: string[] = [];
|
||||
let cleanedText = text;
|
||||
let hasDirective = false;
|
||||
|
||||
const blockRegex = /\[\[tts:text\]\]([\s\S]*?)\[\[\/tts:text\]\]/gi;
|
||||
cleanedText = cleanedText.replace(blockRegex, (_match, inner: string) => {
|
||||
hasDirective = true;
|
||||
if (policy.allowText && overrides.ttsText == null) {
|
||||
overrides.ttsText = inner.trim();
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
const directiveRegex = /\[\[tts:([^\]]+)\]\]/gi;
|
||||
cleanedText = cleanedText.replace(directiveRegex, (_match, body: string) => {
|
||||
hasDirective = true;
|
||||
const tokens = body.split(/\s+/).filter(Boolean);
|
||||
for (const token of tokens) {
|
||||
const eqIndex = token.indexOf("=");
|
||||
if (eqIndex === -1) {
|
||||
continue;
|
||||
}
|
||||
const rawKey = token.slice(0, eqIndex).trim();
|
||||
const rawValue = token.slice(eqIndex + 1).trim();
|
||||
if (!rawKey || !rawValue) {
|
||||
continue;
|
||||
}
|
||||
const key = rawKey.toLowerCase();
|
||||
try {
|
||||
switch (key) {
|
||||
case "provider":
|
||||
if (!policy.allowProvider) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
const providerId = rawValue.trim().toLowerCase();
|
||||
if (providerId) {
|
||||
overrides.provider = providerId;
|
||||
} else {
|
||||
warnings.push("invalid provider id");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "voice":
|
||||
case "openai_voice":
|
||||
case "openaivoice":
|
||||
if (!policy.allowVoice) {
|
||||
break;
|
||||
}
|
||||
if (isValidOpenAIVoice(rawValue, openaiBaseUrl)) {
|
||||
overrides.openai = { ...overrides.openai, voice: rawValue };
|
||||
} else {
|
||||
warnings.push(`invalid OpenAI voice "${rawValue}"`);
|
||||
}
|
||||
break;
|
||||
case "voiceid":
|
||||
case "voice_id":
|
||||
case "elevenlabs_voice":
|
||||
case "elevenlabsvoice":
|
||||
if (!policy.allowVoice) {
|
||||
break;
|
||||
}
|
||||
if (isValidVoiceId(rawValue)) {
|
||||
overrides.elevenlabs = { ...overrides.elevenlabs, voiceId: rawValue };
|
||||
} else {
|
||||
warnings.push(`invalid ElevenLabs voiceId "${rawValue}"`);
|
||||
}
|
||||
break;
|
||||
case "model":
|
||||
case "modelid":
|
||||
case "model_id":
|
||||
case "elevenlabs_model":
|
||||
case "elevenlabsmodel":
|
||||
case "openai_model":
|
||||
case "openaimodel":
|
||||
if (!policy.allowModelId) {
|
||||
break;
|
||||
}
|
||||
if (isValidOpenAIModel(rawValue, openaiBaseUrl)) {
|
||||
overrides.openai = { ...overrides.openai, model: rawValue };
|
||||
} else {
|
||||
overrides.elevenlabs = { ...overrides.elevenlabs, modelId: rawValue };
|
||||
}
|
||||
break;
|
||||
case "stability":
|
||||
if (!policy.allowVoiceSettings) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
const value = parseNumberValue(rawValue);
|
||||
if (value == null) {
|
||||
warnings.push("invalid stability value");
|
||||
break;
|
||||
}
|
||||
requireInRange(value, 0, 1, "stability");
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
voiceSettings: { ...overrides.elevenlabs?.voiceSettings, stability: value },
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "similarity":
|
||||
case "similarityboost":
|
||||
case "similarity_boost":
|
||||
if (!policy.allowVoiceSettings) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
const value = parseNumberValue(rawValue);
|
||||
if (value == null) {
|
||||
warnings.push("invalid similarityBoost value");
|
||||
break;
|
||||
}
|
||||
requireInRange(value, 0, 1, "similarityBoost");
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
voiceSettings: { ...overrides.elevenlabs?.voiceSettings, similarityBoost: value },
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "style":
|
||||
if (!policy.allowVoiceSettings) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
const value = parseNumberValue(rawValue);
|
||||
if (value == null) {
|
||||
warnings.push("invalid style value");
|
||||
break;
|
||||
}
|
||||
requireInRange(value, 0, 1, "style");
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
voiceSettings: { ...overrides.elevenlabs?.voiceSettings, style: value },
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "speed":
|
||||
if (!policy.allowVoiceSettings) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
const value = parseNumberValue(rawValue);
|
||||
if (value == null) {
|
||||
warnings.push("invalid speed value");
|
||||
break;
|
||||
}
|
||||
requireInRange(value, 0.5, 2, "speed");
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
voiceSettings: { ...overrides.elevenlabs?.voiceSettings, speed: value },
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "speakerboost":
|
||||
case "speaker_boost":
|
||||
case "usespeakerboost":
|
||||
case "use_speaker_boost":
|
||||
if (!policy.allowVoiceSettings) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
const value = parseBooleanValue(rawValue);
|
||||
if (value == null) {
|
||||
warnings.push("invalid useSpeakerBoost value");
|
||||
break;
|
||||
}
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
voiceSettings: { ...overrides.elevenlabs?.voiceSettings, useSpeakerBoost: value },
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "normalize":
|
||||
case "applytextnormalization":
|
||||
case "apply_text_normalization":
|
||||
if (!policy.allowNormalization) {
|
||||
break;
|
||||
}
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
applyTextNormalization: normalizeApplyTextNormalization(rawValue),
|
||||
};
|
||||
break;
|
||||
case "language":
|
||||
case "languagecode":
|
||||
case "language_code":
|
||||
if (!policy.allowNormalization) {
|
||||
break;
|
||||
}
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
languageCode: normalizeLanguageCode(rawValue),
|
||||
};
|
||||
break;
|
||||
case "seed":
|
||||
if (!policy.allowSeed) {
|
||||
break;
|
||||
}
|
||||
overrides.elevenlabs = {
|
||||
...overrides.elevenlabs,
|
||||
seed: normalizeSeed(Number.parseInt(rawValue, 10)),
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
warnings.push((err as Error).message);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
return {
|
||||
cleanedText,
|
||||
ttsText: overrides.ttsText,
|
||||
hasDirective,
|
||||
overrides,
|
||||
warnings,
|
||||
};
|
||||
}
|
||||
|
||||
export const OPENAI_TTS_MODELS = ["gpt-4o-mini-tts", "tts-1", "tts-1-hd"] as const;
|
||||
|
||||
/**
|
||||
* Custom OpenAI-compatible TTS endpoint.
|
||||
* When set, model/voice validation is relaxed to allow non-OpenAI models.
|
||||
* Example: OPENAI_TTS_BASE_URL=http://localhost:8880/v1
|
||||
*
|
||||
* Note: Read at runtime (not module load) to support config.env loading.
|
||||
*/
|
||||
function getOpenAITtsBaseUrl(): string {
|
||||
return normalizeOpenAITtsBaseUrl(process.env.OPENAI_TTS_BASE_URL);
|
||||
}
|
||||
|
||||
function isCustomOpenAIEndpoint(baseUrl?: string): boolean {
|
||||
if (baseUrl != null) {
|
||||
return normalizeOpenAITtsBaseUrl(baseUrl) !== DEFAULT_OPENAI_BASE_URL;
|
||||
}
|
||||
return getOpenAITtsBaseUrl() !== DEFAULT_OPENAI_BASE_URL;
|
||||
}
|
||||
export const OPENAI_TTS_VOICES = [
|
||||
"alloy",
|
||||
"ash",
|
||||
"ballad",
|
||||
"cedar",
|
||||
"coral",
|
||||
"echo",
|
||||
"fable",
|
||||
"juniper",
|
||||
"marin",
|
||||
"onyx",
|
||||
"nova",
|
||||
"sage",
|
||||
"shimmer",
|
||||
"verse",
|
||||
] as const;
|
||||
|
||||
type OpenAiTtsVoice = (typeof OPENAI_TTS_VOICES)[number];
|
||||
|
||||
export function isValidOpenAIModel(model: string, baseUrl?: string): boolean {
|
||||
// Allow any model when using custom endpoint (e.g., Kokoro, LocalAI)
|
||||
if (isCustomOpenAIEndpoint(baseUrl)) {
|
||||
return true;
|
||||
}
|
||||
return OPENAI_TTS_MODELS.includes(model as (typeof OPENAI_TTS_MODELS)[number]);
|
||||
}
|
||||
|
||||
export function resolveOpenAITtsInstructions(
|
||||
model: string,
|
||||
instructions?: string,
|
||||
): string | undefined {
|
||||
const next = trimToUndefined(instructions);
|
||||
return next && model.includes("gpt-4o-mini-tts") ? next : undefined;
|
||||
}
|
||||
|
||||
export function isValidOpenAIVoice(voice: string, baseUrl?: string): voice is OpenAiTtsVoice {
|
||||
// Allow any voice when using custom endpoint (e.g., Kokoro Chinese voices)
|
||||
if (isCustomOpenAIEndpoint(baseUrl)) {
|
||||
return true;
|
||||
}
|
||||
return OPENAI_TTS_VOICES.includes(voice as OpenAiTtsVoice);
|
||||
}
|
||||
|
||||
type SummarizeResult = {
|
||||
summary: string;
|
||||
latencyMs: number;
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { buildElevenLabsSpeechProvider } from "../../extensions/elevenlabs/speech-provider.ts";
|
||||
import {
|
||||
buildElevenLabsSpeechProvider,
|
||||
isValidVoiceId,
|
||||
} from "../../extensions/elevenlabs/speech-provider.ts";
|
||||
import { buildMicrosoftSpeechProvider } from "../../extensions/microsoft/speech-provider.ts";
|
||||
import { buildOpenAISpeechProvider } from "../../extensions/openai/speech-provider.ts";
|
||||
import {
|
||||
isValidOpenAIModel,
|
||||
isValidOpenAIVoice,
|
||||
OPENAI_TTS_MODELS,
|
||||
OPENAI_TTS_VOICES,
|
||||
resolveOpenAITtsInstructions,
|
||||
} from "../../extensions/openai/tts.ts";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry-empty.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
@@ -73,17 +83,11 @@ vi.mock("../agents/custom-api-registry.js", () => ({
|
||||
const { _test, resolveTtsConfig, maybeApplyTtsToPayload, getTtsProvider } = tts;
|
||||
|
||||
const {
|
||||
isValidVoiceId,
|
||||
isValidOpenAIVoice,
|
||||
isValidOpenAIModel,
|
||||
OPENAI_TTS_MODELS,
|
||||
OPENAI_TTS_VOICES,
|
||||
parseTtsDirectives,
|
||||
resolveOpenAITtsInstructions,
|
||||
resolveModelOverridePolicy,
|
||||
summarizeText,
|
||||
resolveOutputFormat,
|
||||
resolveEdgeOutputFormat,
|
||||
getResolvedSpeechProviderConfig,
|
||||
} = _test;
|
||||
|
||||
const mockAssistantMessage = (content: AssistantMessage["content"]): AssistantMessage => ({
|
||||
@@ -317,7 +321,10 @@ describe("tts", () => {
|
||||
] as const;
|
||||
for (const testCase of cases) {
|
||||
const config = resolveTtsConfig(testCase.cfg);
|
||||
expect(resolveEdgeOutputFormat(config), testCase.name).toBe(testCase.expected);
|
||||
const providerConfig = getResolvedSpeechProviderConfig(config, "microsoft") as {
|
||||
outputFormat?: string;
|
||||
};
|
||||
expect(providerConfig.outputFormat, testCase.name).toBe(testCase.expected);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -329,13 +336,19 @@ describe("tts", () => {
|
||||
"Hello [[tts:provider=elevenlabs voiceId=pMsXgVXv3BLzUgSXRplE stability=0.4 speed=1.1]] world\n\n" +
|
||||
"[[tts:text]](laughs) Read the song once more.[[/tts:text]]";
|
||||
const result = parseTtsDirectives(input, policy);
|
||||
const elevenlabsOverrides = result.overrides.providerOverrides?.elevenlabs as
|
||||
| {
|
||||
voiceId?: string;
|
||||
voiceSettings?: { stability?: number; speed?: number };
|
||||
}
|
||||
| undefined;
|
||||
|
||||
expect(result.cleanedText).not.toContain("[[tts:");
|
||||
expect(result.ttsText).toBe("(laughs) Read the song once more.");
|
||||
expect(result.overrides.provider).toBe("elevenlabs");
|
||||
expect(result.overrides.elevenlabs?.voiceId).toBe("pMsXgVXv3BLzUgSXRplE");
|
||||
expect(result.overrides.elevenlabs?.voiceSettings?.stability).toBe(0.4);
|
||||
expect(result.overrides.elevenlabs?.voiceSettings?.speed).toBe(1.1);
|
||||
expect(elevenlabsOverrides?.voiceId).toBe("pMsXgVXv3BLzUgSXRplE");
|
||||
expect(elevenlabsOverrides?.voiceSettings?.stability).toBe(0.4);
|
||||
expect(elevenlabsOverrides?.voiceSettings?.speed).toBe(1.1);
|
||||
});
|
||||
|
||||
it("accepts edge as a legacy microsoft provider override", () => {
|
||||
@@ -350,9 +363,12 @@ describe("tts", () => {
|
||||
const policy = resolveModelOverridePolicy({ enabled: true });
|
||||
const input = "Hello [[tts:provider=edge voice=alloy]] world";
|
||||
const result = parseTtsDirectives(input, policy);
|
||||
const openaiOverrides = result.overrides.providerOverrides?.openai as
|
||||
| { voice?: string }
|
||||
| undefined;
|
||||
|
||||
expect(result.overrides.provider).toBeUndefined();
|
||||
expect(result.overrides.openai?.voice).toBe("alloy");
|
||||
expect(openaiOverrides?.voice).toBe("alloy");
|
||||
});
|
||||
|
||||
it("keeps text intact when overrides are disabled", () => {
|
||||
@@ -370,9 +386,12 @@ describe("tts", () => {
|
||||
const customBaseUrl = "http://localhost:8880/v1";
|
||||
|
||||
const result = parseTtsDirectives(input, policy, customBaseUrl);
|
||||
const openaiOverrides = result.overrides.providerOverrides?.openai as
|
||||
| { voice?: string; model?: string }
|
||||
| undefined;
|
||||
|
||||
expect(result.overrides.openai?.voice).toBe("kokoro-chinese");
|
||||
expect(result.overrides.openai?.model).toBe("kokoro-v1");
|
||||
expect(openaiOverrides?.voice).toBe("kokoro-chinese");
|
||||
expect(openaiOverrides?.model).toBe("kokoro-v1");
|
||||
expect(result.warnings).toHaveLength(0);
|
||||
});
|
||||
|
||||
@@ -382,8 +401,11 @@ describe("tts", () => {
|
||||
const defaultBaseUrl = "https://api.openai.com/v1";
|
||||
|
||||
const result = parseTtsDirectives(input, policy, defaultBaseUrl);
|
||||
const openaiOverrides = result.overrides.providerOverrides?.openai as
|
||||
| { voice?: string }
|
||||
| undefined;
|
||||
|
||||
expect(result.overrides.openai?.voice).toBeUndefined();
|
||||
expect(openaiOverrides?.voice).toBeUndefined();
|
||||
expect(result.warnings).toContain('invalid OpenAI voice "kokoro-chinese"');
|
||||
});
|
||||
});
|
||||
@@ -704,7 +726,10 @@ describe("tts", () => {
|
||||
] as const) {
|
||||
withEnv(testCase.env, () => {
|
||||
const config = resolveTtsConfig(testCase.cfg);
|
||||
expect(config.openai.baseUrl, testCase.name).toBe(testCase.expected);
|
||||
const openaiConfig = getResolvedSpeechProviderConfig(config, "openai") as {
|
||||
baseUrl?: string;
|
||||
};
|
||||
expect(openaiConfig.baseUrl, testCase.name).toBe(testCase.expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
335
src/tts/tts.ts
335
src/tts/tts.ts
@@ -14,7 +14,6 @@ import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import { normalizeChannelId } from "../channels/plugins/index.js";
|
||||
import type { ChannelId } from "../channels/plugins/types.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { normalizeResolvedSecretInputString } from "../config/types.secrets.js";
|
||||
import type {
|
||||
TtsConfig,
|
||||
TtsAutoMode,
|
||||
@@ -24,52 +23,30 @@ import type {
|
||||
} from "../config/types.tts.js";
|
||||
import { logVerbose } from "../globals.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../infra/tmp-openclaw-dir.js";
|
||||
import {
|
||||
OPENAI_DEFAULT_TTS_MODEL as DEFAULT_OPENAI_MODEL,
|
||||
OPENAI_DEFAULT_TTS_VOICE as DEFAULT_OPENAI_VOICE,
|
||||
} from "../plugins/provider-model-defaults.js";
|
||||
import { stripMarkdown } from "../shared/text/strip-markdown.js";
|
||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||
import { parseTtsDirectives } from "./directives.js";
|
||||
import {
|
||||
canonicalizeSpeechProviderId,
|
||||
getSpeechProvider,
|
||||
listSpeechProviders,
|
||||
normalizeSpeechProviderId,
|
||||
} from "./provider-registry.js";
|
||||
import type { SpeechVoiceOption } from "./provider-types.js";
|
||||
import {
|
||||
DEFAULT_OPENAI_BASE_URL,
|
||||
isValidOpenAIModel,
|
||||
isValidOpenAIVoice,
|
||||
isValidVoiceId,
|
||||
OPENAI_TTS_MODELS,
|
||||
OPENAI_TTS_VOICES,
|
||||
resolveOpenAITtsInstructions,
|
||||
parseTtsDirectives,
|
||||
scheduleCleanup,
|
||||
summarizeText,
|
||||
} from "./tts-core.js";
|
||||
export { OPENAI_TTS_MODELS, OPENAI_TTS_VOICES } from "./tts-core.js";
|
||||
import type {
|
||||
SpeechModelOverridePolicy,
|
||||
SpeechProviderConfig,
|
||||
SpeechVoiceOption,
|
||||
TtsDirectiveOverrides,
|
||||
TtsDirectiveParseResult,
|
||||
} from "./provider-types.js";
|
||||
import { scheduleCleanup, summarizeText } from "./tts-core.js";
|
||||
|
||||
export type { TtsDirectiveOverrides, TtsDirectiveParseResult } from "./provider-types.js";
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 30_000;
|
||||
const DEFAULT_TTS_MAX_LENGTH = 1500;
|
||||
const DEFAULT_TTS_SUMMARIZE = true;
|
||||
const DEFAULT_MAX_TEXT_LENGTH = 4096;
|
||||
|
||||
const DEFAULT_ELEVENLABS_BASE_URL = "https://api.elevenlabs.io";
|
||||
const DEFAULT_ELEVENLABS_VOICE_ID = "pMsXgVXv3BLzUgSXRplE";
|
||||
const DEFAULT_ELEVENLABS_MODEL_ID = "eleven_multilingual_v2";
|
||||
const DEFAULT_EDGE_VOICE = "en-US-MichelleNeural";
|
||||
const DEFAULT_EDGE_LANG = "en-US";
|
||||
const DEFAULT_EDGE_OUTPUT_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
|
||||
|
||||
const DEFAULT_ELEVENLABS_VOICE_SETTINGS = {
|
||||
stability: 0.5,
|
||||
similarityBoost: 0.75,
|
||||
style: 0.0,
|
||||
useSpeakerBoost: true,
|
||||
speed: 1.0,
|
||||
};
|
||||
|
||||
const OPUS_OUTPUT = {
|
||||
openai: "opus" as const,
|
||||
// ElevenLabs output formats use codec_sample_rate_bitrate naming.
|
||||
@@ -95,43 +72,7 @@ export type ResolvedTtsConfig = {
|
||||
providerSource: "config" | "default";
|
||||
summaryModel?: string;
|
||||
modelOverrides: ResolvedTtsModelOverrides;
|
||||
elevenlabs: {
|
||||
apiKey?: string;
|
||||
baseUrl: string;
|
||||
voiceId: string;
|
||||
modelId: string;
|
||||
seed?: number;
|
||||
applyTextNormalization?: "auto" | "on" | "off";
|
||||
languageCode?: string;
|
||||
voiceSettings: {
|
||||
stability: number;
|
||||
similarityBoost: number;
|
||||
style: number;
|
||||
useSpeakerBoost: boolean;
|
||||
speed: number;
|
||||
};
|
||||
};
|
||||
openai: {
|
||||
apiKey?: string;
|
||||
baseUrl: string;
|
||||
model: string;
|
||||
voice: string;
|
||||
speed?: number;
|
||||
instructions?: string;
|
||||
};
|
||||
edge: {
|
||||
enabled: boolean;
|
||||
voice: string;
|
||||
lang: string;
|
||||
outputFormat: string;
|
||||
outputFormatConfigured: boolean;
|
||||
pitch?: string;
|
||||
rate?: string;
|
||||
volume?: string;
|
||||
saveSubtitles: boolean;
|
||||
proxy?: string;
|
||||
timeoutMs?: number;
|
||||
};
|
||||
providerConfigs: Record<string, SpeechProviderConfig>;
|
||||
prefsPath?: string;
|
||||
maxTextLength: number;
|
||||
timeoutMs: number;
|
||||
@@ -147,47 +88,7 @@ type TtsUserPrefs = {
|
||||
};
|
||||
};
|
||||
|
||||
export type ResolvedTtsModelOverrides = {
|
||||
enabled: boolean;
|
||||
allowText: boolean;
|
||||
allowProvider: boolean;
|
||||
allowVoice: boolean;
|
||||
allowModelId: boolean;
|
||||
allowVoiceSettings: boolean;
|
||||
allowNormalization: boolean;
|
||||
allowSeed: boolean;
|
||||
};
|
||||
|
||||
export type TtsDirectiveOverrides = {
|
||||
ttsText?: string;
|
||||
provider?: TtsProvider;
|
||||
openai?: {
|
||||
voice?: string;
|
||||
model?: string;
|
||||
speed?: number;
|
||||
};
|
||||
elevenlabs?: {
|
||||
voiceId?: string;
|
||||
modelId?: string;
|
||||
outputFormat?: string;
|
||||
seed?: number;
|
||||
applyTextNormalization?: "auto" | "on" | "off";
|
||||
languageCode?: string;
|
||||
voiceSettings?: Partial<ResolvedTtsConfig["elevenlabs"]["voiceSettings"]>;
|
||||
};
|
||||
microsoft?: {
|
||||
voice?: string;
|
||||
outputFormat?: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type TtsDirectiveParseResult = {
|
||||
cleanedText: string;
|
||||
ttsText?: string;
|
||||
hasDirective: boolean;
|
||||
overrides: TtsDirectiveOverrides;
|
||||
warnings: string[];
|
||||
};
|
||||
export type ResolvedTtsModelOverrides = SpeechModelOverridePolicy;
|
||||
|
||||
export type TtsResult = {
|
||||
success: boolean;
|
||||
@@ -273,75 +174,66 @@ function resolveModelOverridePolicy(
|
||||
};
|
||||
}
|
||||
|
||||
function sortSpeechProvidersForAutoSelection(cfg?: OpenClawConfig) {
|
||||
return listSpeechProviders(cfg).toSorted((left, right) => {
|
||||
const leftOrder = left.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = right.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
return left.id.localeCompare(right.id);
|
||||
});
|
||||
}
|
||||
|
||||
function asProviderConfig(value: unknown): SpeechProviderConfig {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value)
|
||||
? (value as SpeechProviderConfig)
|
||||
: {};
|
||||
}
|
||||
|
||||
function resolveSpeechProviderConfigs(
|
||||
raw: TtsConfig,
|
||||
cfg: OpenClawConfig,
|
||||
timeoutMs: number,
|
||||
): Record<string, SpeechProviderConfig> {
|
||||
const providerConfigs: Record<string, SpeechProviderConfig> = {};
|
||||
for (const provider of listSpeechProviders(cfg)) {
|
||||
providerConfigs[provider.id] =
|
||||
provider.resolveConfig?.({
|
||||
cfg,
|
||||
rawConfig: raw as Record<string, unknown>,
|
||||
timeoutMs,
|
||||
}) ?? asProviderConfig((raw as Record<string, unknown>)[provider.id]);
|
||||
}
|
||||
return providerConfigs;
|
||||
}
|
||||
|
||||
export function getResolvedSpeechProviderConfig(
|
||||
config: ResolvedTtsConfig,
|
||||
providerId: string,
|
||||
cfg?: OpenClawConfig,
|
||||
): SpeechProviderConfig {
|
||||
const canonical =
|
||||
canonicalizeSpeechProviderId(providerId, cfg) ?? providerId.trim().toLowerCase();
|
||||
return config.providerConfigs[canonical] ?? {};
|
||||
}
|
||||
|
||||
export function resolveTtsConfig(cfg: OpenClawConfig): ResolvedTtsConfig {
|
||||
const raw: TtsConfig = cfg.messages?.tts ?? {};
|
||||
const providerSource = raw.provider ? "config" : "default";
|
||||
const rawMicrosoft = { ...raw.edge, ...raw.microsoft };
|
||||
const edgeOutputFormat = rawMicrosoft.outputFormat?.trim();
|
||||
const timeoutMs = raw.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
||||
const auto = normalizeTtsAutoMode(raw.auto) ?? (raw.enabled ? "always" : "off");
|
||||
return {
|
||||
auto,
|
||||
mode: raw.mode ?? "final",
|
||||
provider: normalizeSpeechProviderId(raw.provider) ?? "microsoft",
|
||||
provider: canonicalizeSpeechProviderId(raw.provider, cfg) ?? "microsoft",
|
||||
providerSource,
|
||||
summaryModel: raw.summaryModel?.trim() || undefined,
|
||||
modelOverrides: resolveModelOverridePolicy(raw.modelOverrides),
|
||||
elevenlabs: {
|
||||
apiKey: normalizeResolvedSecretInputString({
|
||||
value: raw.elevenlabs?.apiKey,
|
||||
path: "messages.tts.elevenlabs.apiKey",
|
||||
}),
|
||||
baseUrl: raw.elevenlabs?.baseUrl?.trim() || DEFAULT_ELEVENLABS_BASE_URL,
|
||||
voiceId: raw.elevenlabs?.voiceId ?? DEFAULT_ELEVENLABS_VOICE_ID,
|
||||
modelId: raw.elevenlabs?.modelId ?? DEFAULT_ELEVENLABS_MODEL_ID,
|
||||
seed: raw.elevenlabs?.seed,
|
||||
applyTextNormalization: raw.elevenlabs?.applyTextNormalization,
|
||||
languageCode: raw.elevenlabs?.languageCode,
|
||||
voiceSettings: {
|
||||
stability:
|
||||
raw.elevenlabs?.voiceSettings?.stability ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.stability,
|
||||
similarityBoost:
|
||||
raw.elevenlabs?.voiceSettings?.similarityBoost ??
|
||||
DEFAULT_ELEVENLABS_VOICE_SETTINGS.similarityBoost,
|
||||
style: raw.elevenlabs?.voiceSettings?.style ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.style,
|
||||
useSpeakerBoost:
|
||||
raw.elevenlabs?.voiceSettings?.useSpeakerBoost ??
|
||||
DEFAULT_ELEVENLABS_VOICE_SETTINGS.useSpeakerBoost,
|
||||
speed: raw.elevenlabs?.voiceSettings?.speed ?? DEFAULT_ELEVENLABS_VOICE_SETTINGS.speed,
|
||||
},
|
||||
},
|
||||
openai: {
|
||||
apiKey: normalizeResolvedSecretInputString({
|
||||
value: raw.openai?.apiKey,
|
||||
path: "messages.tts.openai.apiKey",
|
||||
}),
|
||||
// Config > env var > default; strip trailing slashes for consistency.
|
||||
baseUrl: (
|
||||
raw.openai?.baseUrl?.trim() ||
|
||||
process.env.OPENAI_TTS_BASE_URL?.trim() ||
|
||||
DEFAULT_OPENAI_BASE_URL
|
||||
).replace(/\/+$/, ""),
|
||||
model: raw.openai?.model ?? DEFAULT_OPENAI_MODEL,
|
||||
voice: raw.openai?.voice ?? DEFAULT_OPENAI_VOICE,
|
||||
speed: raw.openai?.speed,
|
||||
instructions: raw.openai?.instructions?.trim() || undefined,
|
||||
},
|
||||
edge: {
|
||||
enabled: rawMicrosoft.enabled ?? true,
|
||||
voice: rawMicrosoft.voice?.trim() || DEFAULT_EDGE_VOICE,
|
||||
lang: rawMicrosoft.lang?.trim() || DEFAULT_EDGE_LANG,
|
||||
outputFormat: edgeOutputFormat || DEFAULT_EDGE_OUTPUT_FORMAT,
|
||||
outputFormatConfigured: Boolean(edgeOutputFormat),
|
||||
pitch: rawMicrosoft.pitch?.trim() || undefined,
|
||||
rate: rawMicrosoft.rate?.trim() || undefined,
|
||||
volume: rawMicrosoft.volume?.trim() || undefined,
|
||||
saveSubtitles: rawMicrosoft.saveSubtitles ?? false,
|
||||
proxy: rawMicrosoft.proxy?.trim() || undefined,
|
||||
timeoutMs: rawMicrosoft.timeoutMs,
|
||||
},
|
||||
providerConfigs: resolveSpeechProviderConfigs(raw, cfg, timeoutMs),
|
||||
prefsPath: raw.prefsPath,
|
||||
maxTextLength: raw.maxTextLength ?? DEFAULT_MAX_TEXT_LENGTH,
|
||||
timeoutMs: raw.timeoutMs ?? DEFAULT_TIMEOUT_MS,
|
||||
timeoutMs,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -464,26 +356,30 @@ export function setTtsEnabled(prefsPath: string, enabled: boolean): void {
|
||||
|
||||
export function getTtsProvider(config: ResolvedTtsConfig, prefsPath: string): TtsProvider {
|
||||
const prefs = readPrefs(prefsPath);
|
||||
const prefsProvider = normalizeSpeechProviderId(prefs.tts?.provider);
|
||||
const prefsProvider = canonicalizeSpeechProviderId(prefs.tts?.provider);
|
||||
if (prefsProvider) {
|
||||
return prefsProvider;
|
||||
}
|
||||
if (config.providerSource === "config") {
|
||||
return normalizeSpeechProviderId(config.provider) ?? config.provider;
|
||||
return canonicalizeSpeechProviderId(config.provider) ?? config.provider;
|
||||
}
|
||||
|
||||
if (resolveTtsApiKey(config, "openai")) {
|
||||
return "openai";
|
||||
}
|
||||
if (resolveTtsApiKey(config, "elevenlabs")) {
|
||||
return "elevenlabs";
|
||||
for (const provider of sortSpeechProvidersForAutoSelection()) {
|
||||
if (
|
||||
provider.isConfigured({
|
||||
providerConfig: config.providerConfigs[provider.id] ?? {},
|
||||
timeoutMs: config.timeoutMs,
|
||||
})
|
||||
) {
|
||||
return provider.id;
|
||||
}
|
||||
}
|
||||
return "microsoft";
|
||||
}
|
||||
|
||||
export function setTtsProvider(prefsPath: string, provider: TtsProvider): void {
|
||||
updatePrefs(prefsPath, (prefs) => {
|
||||
prefs.tts = { ...prefs.tts, provider: normalizeSpeechProviderId(provider) ?? provider };
|
||||
prefs.tts = { ...prefs.tts, provider: canonicalizeSpeechProviderId(provider) ?? provider };
|
||||
});
|
||||
}
|
||||
|
||||
@@ -531,36 +427,11 @@ function resolveChannelId(channel: string | undefined): ChannelId | null {
|
||||
return channel ? normalizeChannelId(channel) : null;
|
||||
}
|
||||
|
||||
function resolveEdgeOutputFormat(config: ResolvedTtsConfig): string {
|
||||
return config.edge.outputFormat;
|
||||
}
|
||||
|
||||
export function resolveTtsApiKey(
|
||||
config: ResolvedTtsConfig,
|
||||
provider: TtsProvider,
|
||||
): string | undefined {
|
||||
const normalizedProvider = normalizeSpeechProviderId(provider);
|
||||
if (normalizedProvider === "elevenlabs") {
|
||||
return config.elevenlabs.apiKey || process.env.ELEVENLABS_API_KEY || process.env.XI_API_KEY;
|
||||
}
|
||||
if (normalizedProvider === "openai") {
|
||||
return config.openai.apiKey || process.env.OPENAI_API_KEY;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export const TTS_PROVIDERS = ["openai", "elevenlabs", "microsoft"] as const;
|
||||
|
||||
export function resolveTtsProviderOrder(primary: TtsProvider, cfg?: OpenClawConfig): TtsProvider[] {
|
||||
const normalizedPrimary = normalizeSpeechProviderId(primary) ?? primary;
|
||||
const normalizedPrimary = canonicalizeSpeechProviderId(primary, cfg) ?? primary;
|
||||
const ordered = new Set<TtsProvider>([normalizedPrimary]);
|
||||
for (const provider of TTS_PROVIDERS) {
|
||||
if (provider !== normalizedPrimary) {
|
||||
ordered.add(provider);
|
||||
}
|
||||
}
|
||||
for (const provider of listSpeechProviders(cfg)) {
|
||||
const normalized = normalizeSpeechProviderId(provider.id) ?? provider.id;
|
||||
for (const provider of sortSpeechProvidersForAutoSelection(cfg)) {
|
||||
const normalized = provider.id;
|
||||
if (normalized !== normalizedPrimary) {
|
||||
ordered.add(normalized);
|
||||
}
|
||||
@@ -574,7 +445,16 @@ export function isTtsProviderConfigured(
|
||||
cfg?: OpenClawConfig,
|
||||
): boolean {
|
||||
const resolvedProvider = getSpeechProvider(provider, cfg);
|
||||
return resolvedProvider?.isConfigured({ cfg, config }) ?? false;
|
||||
if (!resolvedProvider) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
resolvedProvider.isConfigured({
|
||||
cfg,
|
||||
providerConfig: getResolvedSpeechProviderConfig(config, resolvedProvider.id, cfg),
|
||||
timeoutMs: config.timeoutMs,
|
||||
}) ?? false
|
||||
);
|
||||
}
|
||||
|
||||
function formatTtsProviderError(provider: TtsProvider, err: unknown): string {
|
||||
@@ -604,7 +484,18 @@ function resolveReadySpeechProvider(params: {
|
||||
params.errors.push(`${params.provider}: no provider registered`);
|
||||
return null;
|
||||
}
|
||||
if (!resolvedProvider.isConfigured({ cfg: params.cfg, config: params.config })) {
|
||||
const providerConfig = getResolvedSpeechProviderConfig(
|
||||
params.config,
|
||||
resolvedProvider.id,
|
||||
params.cfg,
|
||||
);
|
||||
if (
|
||||
!resolvedProvider.isConfigured({
|
||||
cfg: params.cfg,
|
||||
providerConfig,
|
||||
timeoutMs: params.config.timeoutMs,
|
||||
})
|
||||
) {
|
||||
params.errors.push(`${params.provider}: not configured`);
|
||||
return null;
|
||||
}
|
||||
@@ -638,7 +529,8 @@ function resolveTtsRequestSetup(params: {
|
||||
}
|
||||
|
||||
const userProvider = getTtsProvider(config, prefsPath);
|
||||
const provider = normalizeSpeechProviderId(params.providerOverride) ?? userProvider;
|
||||
const provider =
|
||||
canonicalizeSpeechProviderId(params.providerOverride, params.cfg) ?? userProvider;
|
||||
return {
|
||||
config,
|
||||
providers: params.disableFallback ? [provider] : resolveTtsProviderOrder(provider, params.cfg),
|
||||
@@ -715,9 +607,10 @@ export async function synthesizeSpeech(params: {
|
||||
const synthesis = await resolvedProvider.synthesize({
|
||||
text: params.text,
|
||||
cfg: params.cfg,
|
||||
config,
|
||||
providerConfig: getResolvedSpeechProviderConfig(config, resolvedProvider.id, params.cfg),
|
||||
target,
|
||||
overrides: params.overrides,
|
||||
providerOverrides: params.overrides?.providerOverrides?.[resolvedProvider.id],
|
||||
timeoutMs: config.timeoutMs,
|
||||
});
|
||||
return {
|
||||
success: true,
|
||||
@@ -770,7 +663,8 @@ export async function textToSpeechTelephony(params: {
|
||||
const synthesis = await resolvedProvider.synthesizeTelephony({
|
||||
text: params.text,
|
||||
cfg: params.cfg,
|
||||
config,
|
||||
providerConfig: getResolvedSpeechProviderConfig(config, resolvedProvider.id, params.cfg),
|
||||
timeoutMs: config.timeoutMs,
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -796,7 +690,7 @@ export async function listSpeechVoices(params: {
|
||||
apiKey?: string;
|
||||
baseUrl?: string;
|
||||
}): Promise<SpeechVoiceOption[]> {
|
||||
const provider = normalizeSpeechProviderId(params.provider);
|
||||
const provider = canonicalizeSpeechProviderId(params.provider, params.cfg);
|
||||
if (!provider) {
|
||||
throw new Error("speech provider id is required");
|
||||
}
|
||||
@@ -813,7 +707,7 @@ export async function listSpeechVoices(params: {
|
||||
}
|
||||
return await resolvedProvider.listVoices({
|
||||
cfg: params.cfg,
|
||||
config,
|
||||
providerConfig: getResolvedSpeechProviderConfig(config, resolvedProvider.id, params.cfg),
|
||||
apiKey: params.apiKey,
|
||||
baseUrl: params.baseUrl,
|
||||
});
|
||||
@@ -844,7 +738,10 @@ export async function maybeApplyTtsToPayload(params: {
|
||||
|
||||
const reply = resolveSendableOutboundReplyParts(params.payload);
|
||||
const text = reply.text;
|
||||
const directives = parseTtsDirectives(text, config.modelOverrides, config.openai.baseUrl);
|
||||
const directives = parseTtsDirectives(text, config.modelOverrides, {
|
||||
cfg: params.cfg,
|
||||
providerConfigs: config.providerConfigs,
|
||||
});
|
||||
if (directives.warnings.length > 0) {
|
||||
logVerbose(`TTS: ignored directive overrides (${directives.warnings.join("; ")})`);
|
||||
}
|
||||
@@ -971,15 +868,9 @@ export async function maybeApplyTtsToPayload(params: {
|
||||
}
|
||||
|
||||
export const _test = {
|
||||
isValidVoiceId,
|
||||
isValidOpenAIVoice,
|
||||
isValidOpenAIModel,
|
||||
OPENAI_TTS_MODELS,
|
||||
OPENAI_TTS_VOICES,
|
||||
resolveOpenAITtsInstructions,
|
||||
parseTtsDirectives,
|
||||
resolveModelOverridePolicy,
|
||||
summarizeText,
|
||||
resolveOutputFormat,
|
||||
resolveEdgeOutputFormat,
|
||||
getResolvedSpeechProviderConfig,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user