chore: import upstream snapshot with attribution
Publish CLI Package / publish-npm (push) Waiting to run
Publish Python SDK / publish-pypi (push) Waiting to run
Publish TypeScript SDK / publish-npm (push) Waiting to run
CI / Migrate Dev DB (push) Has been skipped
CI / Detect Version (push) Has been cancelled
CI / Migrate DB (push) Has been cancelled
CI / Build Dev ECR (./docker/app.Dockerfile, ECR_APP) (push) Has been cancelled
CI / Build Dev ECR (./docker/db.Dockerfile, ECR_MIGRATIONS) (push) Has been cancelled
CI / Build Dev ECR (./docker/pii.Dockerfile, ECR_PII) (push) Has been cancelled
CI / Build Dev ECR (./docker/realtime.Dockerfile, ECR_REALTIME) (push) Has been cancelled
CI / Deploy Trigger.dev (Dev) (push) Has been cancelled
CI / Build AMD64 (./docker/app.Dockerfile, ECR_APP, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build AMD64 (./docker/db.Dockerfile, ECR_MIGRATIONS, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build AMD64 (./docker/pii.Dockerfile, ECR_PII, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build AMD64 (./docker/realtime.Dockerfile, ECR_REALTIME, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/app.Dockerfile, ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/db.Dockerfile, ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/pii.Dockerfile, ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Build ARM64 (GHCR Only) (./docker/realtime.Dockerfile, ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/migrations) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/pii) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/realtime) (push) Has been cancelled
CI / Create GHCR Manifests (ghcr.io/simstudioai/simstudio) (push) Has been cancelled
CI / Check Docs Changes (push) Has been cancelled
CI / Process Docs (push) Has been cancelled
CI / Create GitHub Release (push) Has been cancelled
CI / Test and Build (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:20:55 +08:00
commit d25d482dc2
13754 changed files with 4996608 additions and 0 deletions
@@ -0,0 +1,73 @@
import type {
ElevenLabsAudioIsolationParams,
ElevenLabsAudioResponse,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsAudioIsolationTool: ToolConfig<
ElevenLabsAudioIsolationParams,
ElevenLabsAudioResponse
> = {
id: 'elevenlabs_audio_isolation',
name: 'ElevenLabs Audio Isolation',
description: 'Remove background noise from an audio file, isolating the speech using ElevenLabs',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
audioFile: {
type: 'file',
required: true,
visibility: 'user-only',
description: 'The audio file to isolate speech from (e.g., MP3, WAV, M4A)',
},
},
request: {
url: '/api/tools/elevenlabs/audio',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (
params: ElevenLabsAudioIsolationParams & {
_context?: { workspaceId?: string; workflowId?: string; executionId?: string }
}
) => ({
operation: 'audio_isolation',
apiKey: params.apiKey,
audioFile: params.audioFile,
workspaceId: params._context?.workspaceId,
workflowId: params._context?.workflowId,
executionId: params._context?.executionId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok || data.error) {
return {
success: false,
error: data.error || 'Audio isolation failed',
output: { audioUrl: '' },
}
}
return {
success: true,
output: {
audioUrl: data.audioUrl,
audioFile: data.audioFile,
},
}
},
outputs: {
audioUrl: { type: 'string', description: 'URL of the isolated audio' },
audioFile: { type: 'file', description: 'The isolated audio file' },
},
}
@@ -0,0 +1,92 @@
import type {
ElevenLabsEditVoiceSettingsParams,
ElevenLabsEditVoiceSettingsResponse,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsEditVoiceSettingsTool: ToolConfig<
ElevenLabsEditVoiceSettingsParams,
ElevenLabsEditVoiceSettingsResponse
> = {
id: 'elevenlabs_edit_voice_settings',
name: 'ElevenLabs Edit Voice Settings',
description: 'Update the settings for a specific ElevenLabs voice',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
voiceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the voice to update',
},
stability: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Voice stability from 0.0 to 1.0 (default 0.5)',
},
similarityBoost: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Similarity boost from 0.0 to 1.0 (default 0.75)',
},
style: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Style exaggeration from 0.0 to 1.0 (default 0)',
},
useSpeakerBoost: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to enhance similarity to the original speaker (default true)',
},
speed: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Speech speed where 1.0 is normal (default 1.0)',
},
},
request: {
url: (params) => `https://api.elevenlabs.io/v1/voices/${params.voiceId.trim()}/settings/edit`,
method: 'POST',
headers: (params) => ({
'xi-api-key': params.apiKey,
'Content-Type': 'application/json',
}),
body: (params) => {
const body: Record<string, unknown> = {}
if (params.stability !== undefined) body.stability = params.stability
if (params.similarityBoost !== undefined) body.similarity_boost = params.similarityBoost
if (params.style !== undefined) body.style = params.style
if (params.useSpeakerBoost !== undefined) body.use_speaker_boost = params.useSpeakerBoost
if (params.speed !== undefined) body.speed = params.speed
return body
},
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
status: data.status ?? 'ok',
},
}
},
outputs: {
status: { type: 'string', description: 'Request outcome ("ok" on success)' },
},
}
+72
View File
@@ -0,0 +1,72 @@
import type { ElevenLabsGetUserParams, ElevenLabsGetUserResponse } from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsGetUserTool: ToolConfig<ElevenLabsGetUserParams, ElevenLabsGetUserResponse> =
{
id: 'elevenlabs_get_user',
name: 'ElevenLabs Get User',
description: 'Get account and subscription information for the ElevenLabs user',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
},
request: {
url: 'https://api.elevenlabs.io/v1/user',
method: 'GET',
headers: (params) => ({
'xi-api-key': params.apiKey,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const subscription = data.subscription
return {
success: true,
output: {
userId: data.user_id ?? null,
isNewUser: data.is_new_user ?? null,
subscription: subscription
? {
tier: subscription.tier ?? null,
characterCount: subscription.character_count ?? null,
characterLimit: subscription.character_limit ?? null,
canExtendCharacterLimit: subscription.can_extend_character_limit ?? null,
status: subscription.status ?? null,
nextCharacterCountResetUnix: subscription.next_character_count_reset_unix ?? null,
}
: null,
},
}
},
outputs: {
userId: { type: 'string', description: 'Unique user identifier' },
isNewUser: { type: 'boolean', description: 'Whether the user is new' },
subscription: {
type: 'object',
description: 'Subscription and usage details',
properties: {
tier: { type: 'string', description: 'Subscription tier' },
characterCount: { type: 'number', description: 'Characters used this period' },
characterLimit: { type: 'number', description: 'Character quota for this period' },
canExtendCharacterLimit: {
type: 'boolean',
description: 'Whether the character limit can be extended',
},
status: { type: 'string', description: 'Subscription status' },
nextCharacterCountResetUnix: {
type: 'number',
description: 'Unix timestamp when the character count resets',
},
},
},
},
}
@@ -0,0 +1,60 @@
import type {
ElevenLabsGetVoiceSettingsParams,
ElevenLabsGetVoiceSettingsResponse,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsGetVoiceSettingsTool: ToolConfig<
ElevenLabsGetVoiceSettingsParams,
ElevenLabsGetVoiceSettingsResponse
> = {
id: 'elevenlabs_get_voice_settings',
name: 'ElevenLabs Get Voice Settings',
description: 'Get the configured settings for a specific ElevenLabs voice',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
voiceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the voice whose settings to retrieve',
},
},
request: {
url: (params) => `https://api.elevenlabs.io/v1/voices/${params.voiceId.trim()}/settings`,
method: 'GET',
headers: (params) => ({
'xi-api-key': params.apiKey,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
stability: data.stability ?? null,
similarityBoost: data.similarity_boost ?? null,
style: data.style ?? null,
useSpeakerBoost: data.use_speaker_boost ?? null,
speed: data.speed ?? null,
},
}
},
outputs: {
stability: { type: 'number', description: 'Voice stability (0.0-1.0)' },
similarityBoost: { type: 'number', description: 'Similarity boost (0.0-1.0)' },
style: { type: 'number', description: 'Style exaggeration (0.0-1.0)' },
useSpeakerBoost: { type: 'boolean', description: 'Whether speaker boost is enabled' },
speed: { type: 'number', description: 'Speech speed (1.0 = normal)' },
},
}
+73
View File
@@ -0,0 +1,73 @@
import type { ElevenLabsGetVoiceParams, ElevenLabsGetVoiceResponse } from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsGetVoiceTool: ToolConfig<
ElevenLabsGetVoiceParams,
ElevenLabsGetVoiceResponse
> = {
id: 'elevenlabs_get_voice',
name: 'ElevenLabs Get Voice',
description: 'Get metadata and settings for a specific ElevenLabs voice',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
voiceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the voice to retrieve (e.g., "21m00Tcm4TlvDq8ikWAM")',
},
},
request: {
url: (params) => `https://api.elevenlabs.io/v1/voices/${params.voiceId.trim()}`,
method: 'GET',
headers: (params) => ({
'xi-api-key': params.apiKey,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
return {
success: true,
output: {
voiceId: data.voice_id,
name: data.name ?? null,
category: data.category ?? null,
description: data.description ?? null,
labels: data.labels ?? null,
previewUrl: data.preview_url ?? null,
settings: data.settings ?? null,
availableForTiers: data.available_for_tiers ?? [],
highQualityBaseModelIds: data.high_quality_base_model_ids ?? [],
isOwner: data.is_owner ?? null,
},
}
},
outputs: {
voiceId: { type: 'string', description: 'Unique voice identifier' },
name: { type: 'string', description: 'Voice name' },
category: { type: 'string', description: 'Voice category' },
description: { type: 'string', description: 'Voice description' },
labels: { type: 'json', description: 'Voice labels (accent, gender, age, use case)' },
previewUrl: { type: 'string', description: 'URL to a preview audio sample' },
settings: { type: 'json', description: 'Default voice settings' },
availableForTiers: {
type: 'array',
description: 'Subscription tiers the voice is available on',
},
highQualityBaseModelIds: {
type: 'array',
description: 'Model IDs that support high-quality output for this voice',
},
isOwner: { type: 'boolean', description: 'Whether the current user owns this voice' },
},
}
+11
View File
@@ -0,0 +1,11 @@
export { elevenLabsAudioIsolationTool } from '@/tools/elevenlabs/audio-isolation'
export { elevenLabsEditVoiceSettingsTool } from '@/tools/elevenlabs/edit-voice-settings'
export { elevenLabsGetUserTool } from '@/tools/elevenlabs/get-user'
export { elevenLabsGetVoiceTool } from '@/tools/elevenlabs/get-voice'
export { elevenLabsGetVoiceSettingsTool } from '@/tools/elevenlabs/get-voice-settings'
export { elevenLabsListModelsTool } from '@/tools/elevenlabs/list-models'
export { elevenLabsListVoicesTool } from '@/tools/elevenlabs/list-voices'
export { elevenLabsSoundEffectsTool } from '@/tools/elevenlabs/sound-effects'
export { elevenLabsSpeechToSpeechTool } from '@/tools/elevenlabs/speech-to-speech'
export { elevenLabsTtsTool } from '@/tools/elevenlabs/tts'
export * from '@/tools/elevenlabs/types'
+87
View File
@@ -0,0 +1,87 @@
import type {
ElevenLabsListModelsParams,
ElevenLabsListModelsResponse,
ElevenLabsModelSummary,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsListModelsTool: ToolConfig<
ElevenLabsListModelsParams,
ElevenLabsListModelsResponse
> = {
id: 'elevenlabs_list_models',
name: 'ElevenLabs List Models',
description: 'List the models available in ElevenLabs',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
},
request: {
url: 'https://api.elevenlabs.io/v1/models',
method: 'GET',
headers: (params) => ({
'xi-api-key': params.apiKey,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const models: ElevenLabsModelSummary[] = (Array.isArray(data) ? data : []).map(
(model: any) => ({
modelId: model.model_id,
name: model.name ?? null,
description: model.description ?? null,
canDoTextToSpeech: model.can_do_text_to_speech ?? null,
canDoVoiceConversion: model.can_do_voice_conversion ?? null,
canUseStyle: model.can_use_style ?? null,
canUseSpeakerBoost: model.can_use_speaker_boost ?? null,
languages: (model.languages ?? []).map((language: any) => ({
languageId: language.language_id ?? null,
name: language.name ?? null,
})),
})
)
return {
success: true,
output: { models },
}
},
outputs: {
models: {
type: 'array',
description: 'List of available models',
items: {
type: 'object',
properties: {
modelId: { type: 'string', description: 'Unique model identifier' },
name: { type: 'string', description: 'Model name' },
description: { type: 'string', description: 'Model description' },
canDoTextToSpeech: { type: 'boolean', description: 'Supports text-to-speech' },
canDoVoiceConversion: { type: 'boolean', description: 'Supports voice conversion' },
canUseStyle: { type: 'boolean', description: 'Supports the style parameter' },
canUseSpeakerBoost: { type: 'boolean', description: 'Supports speaker boost' },
languages: {
type: 'array',
description: 'Languages supported by the model',
items: {
type: 'object',
properties: {
languageId: { type: 'string', description: 'Language code' },
name: { type: 'string', description: 'Language name' },
},
},
},
},
},
},
},
}
+110
View File
@@ -0,0 +1,110 @@
import type {
ElevenLabsListVoicesParams,
ElevenLabsListVoicesResponse,
ElevenLabsVoiceSummary,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsListVoicesTool: ToolConfig<
ElevenLabsListVoicesParams,
ElevenLabsListVoicesResponse
> = {
id: 'elevenlabs_list_voices',
name: 'ElevenLabs List Voices',
description: 'List the voices available in your ElevenLabs account',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
search: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Search term to filter voices by name, description, labels, or category',
},
category: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Filter by category: premade, cloned, generated, or professional',
},
pageSize: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Number of voices to return (1-100, default 10)',
},
nextPageToken: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'Page token from a previous response to fetch the next page of voices',
},
},
request: {
url: (params) => {
const query = new URLSearchParams()
if (params.search) query.set('search', params.search)
if (params.category) query.set('category', params.category)
if (params.pageSize !== undefined) query.set('page_size', String(params.pageSize))
if (params.nextPageToken) query.set('next_page_token', params.nextPageToken)
const qs = query.toString()
return `https://api.elevenlabs.io/v2/voices${qs ? `?${qs}` : ''}`
},
method: 'GET',
headers: (params) => ({
'xi-api-key': params.apiKey,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
const voices: ElevenLabsVoiceSummary[] = (data.voices ?? []).map((voice: any) => ({
voiceId: voice.voice_id,
name: voice.name ?? null,
category: voice.category ?? null,
description: voice.description ?? null,
labels: voice.labels ?? null,
previewUrl: voice.preview_url ?? null,
settings: voice.settings ?? null,
}))
return {
success: true,
output: {
voices,
totalCount: data.total_count ?? null,
hasMore: data.has_more ?? false,
nextPageToken: data.next_page_token ?? null,
},
}
},
outputs: {
voices: {
type: 'array',
description: 'List of voices',
items: {
type: 'object',
properties: {
voiceId: { type: 'string', description: 'Unique voice identifier' },
name: { type: 'string', description: 'Voice name' },
category: { type: 'string', description: 'Voice category' },
description: { type: 'string', description: 'Voice description' },
labels: { type: 'json', description: 'Voice labels (accent, gender, age, use case)' },
previewUrl: { type: 'string', description: 'URL to a preview audio sample' },
settings: { type: 'json', description: 'Default voice settings' },
},
},
},
totalCount: { type: 'number', description: 'Total number of matching voices', optional: true },
hasMore: { type: 'boolean', description: 'Whether more voices are available' },
nextPageToken: { type: 'string', description: 'Token to fetch the next page', optional: true },
},
}
+102
View File
@@ -0,0 +1,102 @@
import type {
ElevenLabsAudioResponse,
ElevenLabsSoundEffectsParams,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsSoundEffectsTool: ToolConfig<
ElevenLabsSoundEffectsParams,
ElevenLabsAudioResponse
> = {
id: 'elevenlabs_sound_effects',
name: 'ElevenLabs Sound Effects',
description: 'Generate a sound effect from a text prompt using ElevenLabs',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
text: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'The prompt describing the sound effect (e.g., "thunder rumbling in the distance")',
},
modelId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The model to use (defaults to eleven_text_to_sound_v2)',
},
durationSeconds: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'Length of the sound in seconds (0.5-30). Omit to auto-determine',
},
promptInfluence: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description: 'How closely to follow the prompt from 0.0 to 1.0 (default 0.3)',
},
loop: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to generate a seamlessly looping sound effect (default false)',
},
},
request: {
url: '/api/tools/elevenlabs/audio',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (
params: ElevenLabsSoundEffectsParams & {
_context?: { workspaceId?: string; workflowId?: string; executionId?: string }
}
) => ({
operation: 'sound_effects',
apiKey: params.apiKey,
text: params.text,
modelId: params.modelId,
durationSeconds: params.durationSeconds,
promptInfluence: params.promptInfluence,
loop: params.loop,
workspaceId: params._context?.workspaceId,
workflowId: params._context?.workflowId,
executionId: params._context?.executionId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok || data.error) {
return {
success: false,
error: data.error || 'Sound effect generation failed',
output: { audioUrl: '' },
}
}
return {
success: true,
output: {
audioUrl: data.audioUrl,
audioFile: data.audioFile,
},
}
},
outputs: {
audioUrl: { type: 'string', description: 'URL of the generated sound effect' },
audioFile: { type: 'file', description: 'The generated sound effect file' },
},
}
@@ -0,0 +1,94 @@
import type {
ElevenLabsAudioResponse,
ElevenLabsSpeechToSpeechParams,
} from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsSpeechToSpeechTool: ToolConfig<
ElevenLabsSpeechToSpeechParams,
ElevenLabsAudioResponse
> = {
id: 'elevenlabs_speech_to_speech',
name: 'ElevenLabs Speech to Speech',
description: 'Convert audio into a chosen ElevenLabs voice while preserving content and emotion',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
voiceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the target voice to convert the audio into',
},
audioFile: {
type: 'file',
required: true,
visibility: 'user-only',
description: 'The source audio file to convert (e.g., MP3, WAV, M4A)',
},
modelId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The model to use (defaults to eleven_english_sts_v2)',
},
removeBackgroundNoise: {
type: 'boolean',
required: false,
visibility: 'user-or-llm',
description: 'Whether to isolate the voice and remove background noise (default false)',
},
},
request: {
url: '/api/tools/elevenlabs/audio',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (
params: ElevenLabsSpeechToSpeechParams & {
_context?: { workspaceId?: string; workflowId?: string; executionId?: string }
}
) => ({
operation: 'speech_to_speech',
apiKey: params.apiKey,
voiceId: params.voiceId,
audioFile: params.audioFile,
modelId: params.modelId,
removeBackgroundNoise: params.removeBackgroundNoise,
workspaceId: params._context?.workspaceId,
workflowId: params._context?.workflowId,
executionId: params._context?.executionId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok || data.error) {
return {
success: false,
error: data.error || 'Speech-to-speech conversion failed',
output: { audioUrl: '' },
}
}
return {
success: true,
output: {
audioUrl: data.audioUrl,
audioFile: data.audioFile,
},
}
},
outputs: {
audioUrl: { type: 'string', description: 'URL of the converted audio' },
audioFile: { type: 'file', description: 'The converted audio file' },
},
}
+101
View File
@@ -0,0 +1,101 @@
import type { ElevenLabsTtsParams, ElevenLabsTtsResponse } from '@/tools/elevenlabs/types'
import type { ToolConfig } from '@/tools/types'
export const elevenLabsTtsTool: ToolConfig<ElevenLabsTtsParams, ElevenLabsTtsResponse> = {
id: 'elevenlabs_tts',
name: 'ElevenLabs TTS',
description: 'Convert text to speech using ElevenLabs voices',
version: '1.0.0',
params: {
text: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The text to convert to speech (e.g., "Hello, welcome to our service!")',
},
voiceId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the voice to use (e.g., "21m00Tcm4TlvDq8ikWAM" for Rachel)',
},
modelId: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description:
'The ID of the model to use (e.g., "eleven_multilingual_v2", "eleven_turbo_v2"). Defaults to eleven_monolingual_v1',
},
stability: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'Voice stability setting from 0.0 to 1.0 (e.g., 0.5 for balanced, 0.75 for more stable). Higher values produce more consistent output',
},
similarityBoost: {
type: 'number',
required: false,
visibility: 'user-or-llm',
description:
'Similarity boost setting from 0.0 to 1.0 (e.g., 0.75 for natural, 1.0 for maximum similarity). Higher values make the voice more similar to the original',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'Your ElevenLabs API key',
},
},
request: {
url: '/api/tools/tts',
method: 'POST',
headers: () => ({
'Content-Type': 'application/json',
}),
body: (
params: ElevenLabsTtsParams & {
_context?: { workspaceId?: string; workflowId?: string; executionId?: string }
}
) => ({
apiKey: params.apiKey,
text: params.text,
voiceId: params.voiceId,
modelId: params.modelId || 'eleven_monolingual_v1',
stability: params.stability,
similarityBoost: params.similarityBoost,
workspaceId: params._context?.workspaceId,
workflowId: params._context?.workflowId,
executionId: params._context?.executionId,
}),
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!response.ok || data.error) {
return {
success: false,
error: data.error || 'Unknown error occurred',
output: {
audioUrl: '',
},
}
}
return {
success: true,
output: {
audioUrl: data.audioUrl,
audioFile: data.audioFile,
},
}
},
outputs: {
audioUrl: { type: 'string', description: 'The URL of the generated audio' },
audioFile: { type: 'file', description: 'The generated audio file' },
},
}
+182
View File
@@ -0,0 +1,182 @@
import type { UserFile } from '@/executor/types'
import type { ToolResponse } from '@/tools/types'
export interface ElevenLabsTtsParams {
apiKey: string
text: string
voiceId: string
modelId?: string
stability?: number
similarityBoost?: number
}
export interface ElevenLabsTtsResponse extends ToolResponse {
output: {
audioUrl: string
audioFile?: UserFile
}
}
/** Voice settings shared by get/edit settings and embedded voice objects. */
export interface ElevenLabsVoiceSettings {
stability?: number | null
similarity_boost?: number | null
style?: number | null
use_speaker_boost?: boolean | null
speed?: number | null
}
export interface ElevenLabsVoiceSummary {
voiceId: string
name: string | null
category: string | null
description: string | null
labels: Record<string, string> | null
previewUrl: string | null
settings: ElevenLabsVoiceSettings | null
}
export interface ElevenLabsListVoicesParams {
apiKey: string
search?: string
category?: string
pageSize?: number
nextPageToken?: string
}
export interface ElevenLabsListVoicesResponse extends ToolResponse {
output: {
voices: ElevenLabsVoiceSummary[]
totalCount: number | null
hasMore: boolean
nextPageToken: string | null
}
}
export interface ElevenLabsGetVoiceParams {
apiKey: string
voiceId: string
}
export interface ElevenLabsGetVoiceResponse extends ToolResponse {
output: ElevenLabsVoiceSummary & {
availableForTiers: string[]
highQualityBaseModelIds: string[]
isOwner: boolean | null
}
}
export interface ElevenLabsGetVoiceSettingsParams {
apiKey: string
voiceId: string
}
export interface ElevenLabsGetVoiceSettingsResponse extends ToolResponse {
output: {
stability: number | null
similarityBoost: number | null
style: number | null
useSpeakerBoost: boolean | null
speed: number | null
}
}
export interface ElevenLabsEditVoiceSettingsParams {
apiKey: string
voiceId: string
stability?: number
similarityBoost?: number
style?: number
useSpeakerBoost?: boolean
speed?: number
}
export interface ElevenLabsEditVoiceSettingsResponse extends ToolResponse {
output: {
status: string
}
}
export interface ElevenLabsModelLanguage {
languageId: string | null
name: string | null
}
export interface ElevenLabsModelSummary {
modelId: string
name: string | null
description: string | null
canDoTextToSpeech: boolean | null
canDoVoiceConversion: boolean | null
canUseStyle: boolean | null
canUseSpeakerBoost: boolean | null
languages: ElevenLabsModelLanguage[]
}
export interface ElevenLabsListModelsParams {
apiKey: string
}
export interface ElevenLabsListModelsResponse extends ToolResponse {
output: {
models: ElevenLabsModelSummary[]
}
}
export interface ElevenLabsGetUserParams {
apiKey: string
}
export interface ElevenLabsGetUserResponse extends ToolResponse {
output: {
userId: string | null
isNewUser: boolean | null
subscription: {
tier: string | null
characterCount: number | null
characterLimit: number | null
canExtendCharacterLimit: boolean | null
status: string | null
nextCharacterCountResetUnix: number | null
} | null
}
}
export interface ElevenLabsSoundEffectsParams {
apiKey: string
text: string
modelId?: string
durationSeconds?: number
promptInfluence?: number
loop?: boolean
}
export interface ElevenLabsSpeechToSpeechParams {
apiKey: string
voiceId: string
audioFile?: UserFile
modelId?: string
removeBackgroundNoise?: boolean
}
export interface ElevenLabsAudioIsolationParams {
apiKey: string
audioFile?: UserFile
}
export interface ElevenLabsAudioResponse extends ToolResponse {
output: {
audioUrl: string
audioFile?: UserFile
}
}
export type ElevenLabsBlockResponse =
| ElevenLabsTtsResponse
| ElevenLabsListVoicesResponse
| ElevenLabsGetVoiceResponse
| ElevenLabsGetVoiceSettingsResponse
| ElevenLabsEditVoiceSettingsResponse
| ElevenLabsListModelsResponse
| ElevenLabsGetUserResponse
| ElevenLabsAudioResponse