@soederpop/luca 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +71 -0
- package/README.md +78 -0
- package/bun.lock +2928 -0
- package/bunfig.toml +3 -0
- package/commands/audit-docs.ts +740 -0
- package/commands/build-scaffolds.ts +154 -0
- package/commands/generate-api-docs.ts +114 -0
- package/commands/update-introspection.ts +67 -0
- package/docs/CLI.md +335 -0
- package/docs/README.md +88 -0
- package/docs/TABLE-OF-CONTENTS.md +157 -0
- package/docs/apis/clients/elevenlabs.md +84 -0
- package/docs/apis/clients/graph.md +56 -0
- package/docs/apis/clients/openai.md +69 -0
- package/docs/apis/clients/rest.md +41 -0
- package/docs/apis/clients/websocket.md +107 -0
- package/docs/apis/features/agi/assistant.md +471 -0
- package/docs/apis/features/agi/assistants-manager.md +154 -0
- package/docs/apis/features/agi/claude-code.md +602 -0
- package/docs/apis/features/agi/conversation-history.md +352 -0
- package/docs/apis/features/agi/conversation.md +333 -0
- package/docs/apis/features/agi/docs-reader.md +121 -0
- package/docs/apis/features/agi/openai-codex.md +318 -0
- package/docs/apis/features/agi/openapi.md +138 -0
- package/docs/apis/features/agi/semantic-search.md +387 -0
- package/docs/apis/features/agi/skills-library.md +216 -0
- package/docs/apis/features/node/container-link.md +133 -0
- package/docs/apis/features/node/content-db.md +313 -0
- package/docs/apis/features/node/disk-cache.md +379 -0
- package/docs/apis/features/node/dns.md +651 -0
- package/docs/apis/features/node/docker.md +705 -0
- package/docs/apis/features/node/downloader.md +81 -0
- package/docs/apis/features/node/esbuild.md +59 -0
- package/docs/apis/features/node/file-manager.md +182 -0
- package/docs/apis/features/node/fs.md +581 -0
- package/docs/apis/features/node/git.md +330 -0
- package/docs/apis/features/node/google-auth.md +174 -0
- package/docs/apis/features/node/google-calendar.md +187 -0
- package/docs/apis/features/node/google-docs.md +151 -0
- package/docs/apis/features/node/google-drive.md +225 -0
- package/docs/apis/features/node/google-sheets.md +179 -0
- package/docs/apis/features/node/grep.md +290 -0
- package/docs/apis/features/node/helpers.md +135 -0
- package/docs/apis/features/node/ink.md +334 -0
- package/docs/apis/features/node/ipc-socket.md +260 -0
- package/docs/apis/features/node/json-tree.md +86 -0
- package/docs/apis/features/node/launcher-app-command-listener.md +145 -0
- package/docs/apis/features/node/networking.md +281 -0
- package/docs/apis/features/node/nlp.md +133 -0
- package/docs/apis/features/node/opener.md +97 -0
- package/docs/apis/features/node/os.md +118 -0
- package/docs/apis/features/node/package-finder.md +402 -0
- package/docs/apis/features/node/postgres.md +212 -0
- package/docs/apis/features/node/proc.md +430 -0
- package/docs/apis/features/node/process-manager.md +210 -0
- package/docs/apis/features/node/python.md +278 -0
- package/docs/apis/features/node/repl.md +88 -0
- package/docs/apis/features/node/runpod.md +673 -0
- package/docs/apis/features/node/secure-shell.md +169 -0
- package/docs/apis/features/node/semantic-search.md +401 -0
- package/docs/apis/features/node/sqlite.md +211 -0
- package/docs/apis/features/node/telegram.md +254 -0
- package/docs/apis/features/node/tts.md +118 -0
- package/docs/apis/features/node/ui.md +703 -0
- package/docs/apis/features/node/vault.md +64 -0
- package/docs/apis/features/node/vm.md +84 -0
- package/docs/apis/features/node/window-manager.md +337 -0
- package/docs/apis/features/node/yaml-tree.md +85 -0
- package/docs/apis/features/node/yaml.md +176 -0
- package/docs/apis/features/web/asset-loader.md +47 -0
- package/docs/apis/features/web/container-link.md +133 -0
- package/docs/apis/features/web/esbuild.md +59 -0
- package/docs/apis/features/web/helpers.md +135 -0
- package/docs/apis/features/web/network.md +30 -0
- package/docs/apis/features/web/speech.md +55 -0
- package/docs/apis/features/web/vault.md +64 -0
- package/docs/apis/features/web/vm.md +84 -0
- package/docs/apis/features/web/voice.md +67 -0
- package/docs/apis/servers/express.md +127 -0
- package/docs/apis/servers/mcp.md +213 -0
- package/docs/apis/servers/websocket.md +99 -0
- package/docs/documentation-audit.md +134 -0
- package/docs/examples/content-db.md +77 -0
- package/docs/examples/disk-cache.md +83 -0
- package/docs/examples/docker.md +101 -0
- package/docs/examples/downloader.md +70 -0
- package/docs/examples/esbuild.md +80 -0
- package/docs/examples/file-manager.md +82 -0
- package/docs/examples/fs.md +83 -0
- package/docs/examples/git.md +85 -0
- package/docs/examples/google-auth.md +88 -0
- package/docs/examples/google-calendar.md +94 -0
- package/docs/examples/google-docs.md +82 -0
- package/docs/examples/google-drive.md +96 -0
- package/docs/examples/google-sheets.md +95 -0
- package/docs/examples/grep.md +85 -0
- package/docs/examples/ink-blocks.md +75 -0
- package/docs/examples/ink-renderer.md +41 -0
- package/docs/examples/ink.md +103 -0
- package/docs/examples/ipc-socket.md +103 -0
- package/docs/examples/json-tree.md +91 -0
- package/docs/examples/launcher-app-command-listener.md +120 -0
- package/docs/examples/networking.md +58 -0
- package/docs/examples/nlp.md +91 -0
- package/docs/examples/opener.md +78 -0
- package/docs/examples/os.md +72 -0
- package/docs/examples/package-finder.md +89 -0
- package/docs/examples/port-exposer.md +89 -0
- package/docs/examples/postgres.md +91 -0
- package/docs/examples/proc.md +81 -0
- package/docs/examples/process-manager.md +79 -0
- package/docs/examples/python.md +91 -0
- package/docs/examples/repl.md +93 -0
- package/docs/examples/runpod.md +119 -0
- package/docs/examples/secure-shell.md +92 -0
- package/docs/examples/sqlite.md +86 -0
- package/docs/examples/telegram.md +77 -0
- package/docs/examples/tts.md +86 -0
- package/docs/examples/ui.md +80 -0
- package/docs/examples/vault.md +70 -0
- package/docs/examples/vm.md +86 -0
- package/docs/examples/window-manager.md +125 -0
- package/docs/examples/yaml-tree.md +93 -0
- package/docs/examples/yaml.md +104 -0
- package/docs/ideas/class-registration-refactor-possibilities.md +197 -0
- package/docs/ideas/container-use-api.md +9 -0
- package/docs/ideas/easy-auth-for-express-servers-and-luca-serve.md +0 -0
- package/docs/ideas/feature-stacks.md +22 -0
- package/docs/ideas/luca-cli-self-sufficiency-demo.md +23 -0
- package/docs/ideas/mcp-design.md +9 -0
- package/docs/ideas/web-container-debugging-feature.md +13 -0
- package/docs/introspection-audit.md +49 -0
- package/docs/introspection.md +154 -0
- package/docs/mcp/readme.md +162 -0
- package/docs/models.ts +38 -0
- package/docs/philosophy.md +85 -0
- package/docs/principles.md +7 -0
- package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
- package/docs/prompts/mcp-test-easy-command.md +27 -0
- package/docs/reports/assistant-bugs.md +38 -0
- package/docs/reports/attach-pattern-usage.md +18 -0
- package/docs/reports/code-audit-results.md +391 -0
- package/docs/reports/introspection-audit-tasks.md +378 -0
- package/docs/reports/luca-mcp-improvements.md +128 -0
- package/docs/scaffolds/client.md +140 -0
- package/docs/scaffolds/command.md +106 -0
- package/docs/scaffolds/endpoint.md +176 -0
- package/docs/scaffolds/feature.md +148 -0
- package/docs/scaffolds/server.md +187 -0
- package/docs/tasks/web-container-helper-discovery.md +71 -0
- package/docs/todos.md +1 -0
- package/docs/tutorials/01-getting-started.md +106 -0
- package/docs/tutorials/02-container.md +210 -0
- package/docs/tutorials/03-scripts.md +194 -0
- package/docs/tutorials/04-features-overview.md +196 -0
- package/docs/tutorials/05-state-and-events.md +171 -0
- package/docs/tutorials/06-servers.md +157 -0
- package/docs/tutorials/07-endpoints.md +198 -0
- package/docs/tutorials/08-commands.md +171 -0
- package/docs/tutorials/09-clients.md +162 -0
- package/docs/tutorials/10-creating-features.md +198 -0
- package/docs/tutorials/11-contentbase.md +191 -0
- package/docs/tutorials/12-assistants.md +215 -0
- package/docs/tutorials/13-introspection.md +147 -0
- package/docs/tutorials/14-type-system.md +174 -0
- package/docs/tutorials/15-project-patterns.md +222 -0
- package/docs/tutorials/16-google-features.md +534 -0
- package/docs/tutorials/17-tui-blocks.md +530 -0
- package/docs/tutorials/18-semantic-search.md +334 -0
- package/index.ts +1 -0
- package/luca.console.ts +9 -0
- package/main.py +6 -0
- package/package.json +154 -0
- package/pyproject.toml +7 -0
- package/scripts/animations/chrome-glitch.ts +55 -0
- package/scripts/animations/index.ts +16 -0
- package/scripts/animations/neon-pulse.ts +64 -0
- package/scripts/animations/types.ts +6 -0
- package/scripts/build-web.ts +28 -0
- package/scripts/examples/ask-luca-expert.ts +42 -0
- package/scripts/examples/assistant-questions.ts +12 -0
- package/scripts/examples/excalidraw-expert.ts +75 -0
- package/scripts/examples/expert-chat.ts +0 -0
- package/scripts/examples/file-manager.ts +14 -0
- package/scripts/examples/ideas.ts +12 -0
- package/scripts/examples/interactive-chat.ts +20 -0
- package/scripts/examples/openai-tool-calls.ts +113 -0
- package/scripts/examples/opening-a-web-browser.ts +5 -0
- package/scripts/examples/telegram-bot.ts +79 -0
- package/scripts/examples/telegram-ink-ui.ts +302 -0
- package/scripts/examples/using-assistant-with-mcp.ts +560 -0
- package/scripts/examples/using-claude-code.ts +10 -0
- package/scripts/examples/using-contentdb.ts +35 -0
- package/scripts/examples/using-conversations.ts +35 -0
- package/scripts/examples/using-disk-cache.ts +10 -0
- package/scripts/examples/using-docker-shell.ts +75 -0
- package/scripts/examples/using-elevenlabs.ts +25 -0
- package/scripts/examples/using-google-calendar.ts +57 -0
- package/scripts/examples/using-google-docs.ts +74 -0
- package/scripts/examples/using-google-drive.ts +74 -0
- package/scripts/examples/using-google-sheets.ts +89 -0
- package/scripts/examples/using-nlp.ts +55 -0
- package/scripts/examples/using-ollama.ts +10 -0
- package/scripts/examples/using-openai-codex.ts +23 -0
- package/scripts/examples/using-postgres.ts +55 -0
- package/scripts/examples/using-runpod.ts +32 -0
- package/scripts/examples/using-tts.ts +40 -0
- package/scripts/examples/vm-loading-esm-modules.ts +16 -0
- package/scripts/scaffold.ts +391 -0
- package/scripts/scratch.ts +15 -0
- package/scripts/test-command-listener.ts +123 -0
- package/scripts/test-window-manager-lifecycle.ts +86 -0
- package/scripts/test-window-manager.ts +43 -0
- package/scripts/update-introspection-data.ts +58 -0
- package/src/agi/README.md +14 -0
- package/src/agi/container.server.ts +114 -0
- package/src/agi/endpoints/ask.ts +60 -0
- package/src/agi/endpoints/conversations/[id].ts +45 -0
- package/src/agi/endpoints/conversations.ts +31 -0
- package/src/agi/endpoints/experts.ts +37 -0
- package/src/agi/features/assistant.ts +767 -0
- package/src/agi/features/assistants-manager.ts +260 -0
- package/src/agi/features/claude-code.ts +1111 -0
- package/src/agi/features/conversation-history.ts +497 -0
- package/src/agi/features/conversation.ts +799 -0
- package/src/agi/features/openai-codex.ts +631 -0
- package/src/agi/features/openapi.ts +438 -0
- package/src/agi/features/skills-library.ts +425 -0
- package/src/agi/index.ts +6 -0
- package/src/agi/lib/token-counter.ts +122 -0
- package/src/browser.ts +25 -0
- package/src/bus.ts +100 -0
- package/src/cli/cli.ts +70 -0
- package/src/client.ts +461 -0
- package/src/clients/civitai/index.ts +541 -0
- package/src/clients/client-template.ts +41 -0
- package/src/clients/comfyui/index.ts +597 -0
- package/src/clients/elevenlabs/index.ts +291 -0
- package/src/clients/openai/index.ts +451 -0
- package/src/clients/supabase/index.ts +366 -0
- package/src/command.ts +164 -0
- package/src/commands/chat.ts +182 -0
- package/src/commands/console.ts +192 -0
- package/src/commands/describe.ts +433 -0
- package/src/commands/eval.ts +116 -0
- package/src/commands/help.ts +214 -0
- package/src/commands/index.ts +14 -0
- package/src/commands/mcp.ts +64 -0
- package/src/commands/prompt.ts +807 -0
- package/src/commands/run.ts +257 -0
- package/src/commands/sandbox-mcp.ts +439 -0
- package/src/commands/scaffold.ts +79 -0
- package/src/commands/serve.ts +172 -0
- package/src/container.ts +781 -0
- package/src/endpoint.ts +340 -0
- package/src/feature.ts +75 -0
- package/src/hash-object.ts +97 -0
- package/src/helper.ts +543 -0
- package/src/introspection/generated.agi.ts +23388 -0
- package/src/introspection/generated.node.ts +18899 -0
- package/src/introspection/generated.web.ts +2021 -0
- package/src/introspection/index.ts +256 -0
- package/src/introspection/scan.ts +912 -0
- package/src/node/container.ts +354 -0
- package/src/node/feature.ts +13 -0
- package/src/node/features/container-link.ts +558 -0
- package/src/node/features/content-db.ts +475 -0
- package/src/node/features/disk-cache.ts +382 -0
- package/src/node/features/dns.ts +655 -0
- package/src/node/features/docker.ts +912 -0
- package/src/node/features/downloader.ts +92 -0
- package/src/node/features/esbuild.ts +68 -0
- package/src/node/features/file-manager.ts +357 -0
- package/src/node/features/fs.ts +534 -0
- package/src/node/features/git.ts +492 -0
- package/src/node/features/google-auth.ts +502 -0
- package/src/node/features/google-calendar.ts +300 -0
- package/src/node/features/google-docs.ts +404 -0
- package/src/node/features/google-drive.ts +339 -0
- package/src/node/features/google-sheets.ts +279 -0
- package/src/node/features/grep.ts +406 -0
- package/src/node/features/helpers.ts +374 -0
- package/src/node/features/ink.ts +490 -0
- package/src/node/features/ipc-socket.ts +459 -0
- package/src/node/features/json-tree.ts +188 -0
- package/src/node/features/launcher-app-command-listener.ts +388 -0
- package/src/node/features/networking.ts +925 -0
- package/src/node/features/nlp.ts +211 -0
- package/src/node/features/opener.ts +166 -0
- package/src/node/features/os.ts +157 -0
- package/src/node/features/package-finder.ts +539 -0
- package/src/node/features/port-exposer.ts +342 -0
- package/src/node/features/postgres.ts +273 -0
- package/src/node/features/proc.ts +502 -0
- package/src/node/features/process-manager.ts +542 -0
- package/src/node/features/python.ts +444 -0
- package/src/node/features/repl.ts +194 -0
- package/src/node/features/runpod.ts +802 -0
- package/src/node/features/secure-shell.ts +248 -0
- package/src/node/features/semantic-search.ts +924 -0
- package/src/node/features/sqlite.ts +289 -0
- package/src/node/features/telegram.ts +342 -0
- package/src/node/features/tts.ts +184 -0
- package/src/node/features/ui.ts +857 -0
- package/src/node/features/vault.ts +164 -0
- package/src/node/features/vm.ts +312 -0
- package/src/node/features/window-manager.ts +804 -0
- package/src/node/features/yaml-tree.ts +149 -0
- package/src/node/features/yaml.ts +132 -0
- package/src/node.ts +70 -0
- package/src/react/index.ts +175 -0
- package/src/registry.ts +199 -0
- package/src/scaffolds/generated.ts +1613 -0
- package/src/scaffolds/template.ts +37 -0
- package/src/schemas/base.ts +255 -0
- package/src/server.ts +135 -0
- package/src/servers/express.ts +209 -0
- package/src/servers/mcp.ts +805 -0
- package/src/servers/socket.ts +120 -0
- package/src/state.ts +101 -0
- package/src/web/clients/socket.ts +82 -0
- package/src/web/container.ts +74 -0
- package/src/web/extension.ts +30 -0
- package/src/web/feature.ts +12 -0
- package/src/web/features/asset-loader.ts +64 -0
- package/src/web/features/container-link.ts +385 -0
- package/src/web/features/esbuild.ts +79 -0
- package/src/web/features/helpers.ts +267 -0
- package/src/web/features/network.ts +61 -0
- package/src/web/features/speech.ts +87 -0
- package/src/web/features/vault.ts +189 -0
- package/src/web/features/vm.ts +78 -0
- package/src/web/features/voice-recognition.ts +129 -0
- package/src/web/shims/isomorphic-vm.ts +149 -0
- package/test/bus.test.ts +134 -0
- package/test/clients-servers.test.ts +216 -0
- package/test/container-link.test.ts +274 -0
- package/test/features.test.ts +160 -0
- package/test/integration.test.ts +787 -0
- package/test/node-container.test.ts +121 -0
- package/test/rate-limit.test.ts +272 -0
- package/test/semantic-search.test.ts +550 -0
- package/test/state.test.ts +121 -0
- package/test-integration/assistant.test.ts +138 -0
- package/test-integration/assistants-manager.test.ts +123 -0
- package/test-integration/claude-code.test.ts +98 -0
- package/test-integration/conversation-history.test.ts +205 -0
- package/test-integration/conversation.test.ts +137 -0
- package/test-integration/elevenlabs.test.ts +55 -0
- package/test-integration/google-services.test.ts +80 -0
- package/test-integration/helpers.ts +89 -0
- package/test-integration/openai-codex.test.ts +93 -0
- package/test-integration/runpod.test.ts +58 -0
- package/test-integration/server-endpoints.test.ts +97 -0
- package/test-integration/skills-library.test.ts +157 -0
- package/test-integration/telegram.test.ts +46 -0
- package/tsconfig.json +58 -0
- package/uv.lock +8 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema, FeatureOptionsSchema, FeatureEventsSchema } from '../../schemas/base.js'
|
|
3
|
+
import { Feature, features } from '../feature.js'
|
|
4
|
+
import { createHash } from 'crypto'
|
|
5
|
+
|
|
6
|
+
const CHATTERBOX_ENDPOINT = 'https://api.runpod.ai/v2/chatterbox-turbo/runsync'
|
|
7
|
+
|
|
8
|
+
const PRESET_VOICES = [
|
|
9
|
+
'aaron', 'abigail', 'anaya', 'andy', 'archer',
|
|
10
|
+
'brian', 'chloe', 'dylan', 'emmanuel', 'ethan',
|
|
11
|
+
'evelyn', 'gavin', 'gordon', 'ivan', 'laura',
|
|
12
|
+
'lucy', 'madison', 'marisol', 'meera', 'walter',
|
|
13
|
+
] as const
|
|
14
|
+
|
|
15
|
+
type PresetVoice = typeof PRESET_VOICES[number]
|
|
16
|
+
|
|
17
|
+
export const TTSOptionsSchema = FeatureOptionsSchema.extend({
|
|
18
|
+
apiKey: z.string().optional().describe('RunPod API key (falls back to RUNPOD_API_KEY env var)'),
|
|
19
|
+
voice: z.string().optional().describe('Default preset voice name'),
|
|
20
|
+
outputDir: z.string().optional().describe('Directory to save generated audio files'),
|
|
21
|
+
format: z.enum(['wav', 'flac', 'ogg']).default('wav').describe('Audio output format'),
|
|
22
|
+
})
|
|
23
|
+
export type TTSOptions = z.infer<typeof TTSOptionsSchema>
|
|
24
|
+
|
|
25
|
+
export const TTSStateSchema = FeatureStateSchema.extend({
|
|
26
|
+
lastFile: z.string().optional().describe('Path to the last generated audio file'),
|
|
27
|
+
lastText: z.string().optional().describe('Text of the last synthesis request'),
|
|
28
|
+
generating: z.boolean().default(false).describe('Whether audio is currently being generated'),
|
|
29
|
+
})
|
|
30
|
+
export type TTSState = z.infer<typeof TTSStateSchema>
|
|
31
|
+
|
|
32
|
+
export const TTSEventsSchema = FeatureEventsSchema.extend({
|
|
33
|
+
synthesized: z.tuple([
|
|
34
|
+
z.string().describe('The text that was synthesized'),
|
|
35
|
+
z.string().describe('Path to the generated audio file'),
|
|
36
|
+
z.string().describe('Voice used'),
|
|
37
|
+
z.number().describe('Duration of the API call in milliseconds'),
|
|
38
|
+
]).describe('Emitted when audio synthesis completes'),
|
|
39
|
+
error: z.tuple([
|
|
40
|
+
z.any().describe('The error'),
|
|
41
|
+
]).describe('Emitted when synthesis fails'),
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* TTS feature — synthesizes text to audio files via RunPod's Chatterbox Turbo endpoint.
|
|
46
|
+
*
|
|
47
|
+
* Generates high-quality speech audio by calling the Chatterbox Turbo public endpoint
|
|
48
|
+
* on RunPod, downloads the resulting audio, and saves it locally. Supports 20 preset
|
|
49
|
+
* voices and voice cloning via a reference audio URL.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const tts = container.feature('tts', { enable: true })
|
|
54
|
+
* const path = await tts.synthesize('Hello, how are you?', { voice: 'lucy' })
|
|
55
|
+
* console.log(`Audio saved to: ${path}`)
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export class TTS extends Feature<TTSState, TTSOptions> {
|
|
59
|
+
static override shortcut = 'features.tts' as const
|
|
60
|
+
static override envVars = ['RUNPOD_API_KEY']
|
|
61
|
+
static override stateSchema = TTSStateSchema
|
|
62
|
+
static override optionsSchema = TTSOptionsSchema
|
|
63
|
+
static override eventsSchema = TTSEventsSchema
|
|
64
|
+
|
|
65
|
+
/** RunPod API key from options or environment. */
|
|
66
|
+
get apiKey(): string {
|
|
67
|
+
return this.options.apiKey || process.env.RUNPOD_API_KEY || ''
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Directory where generated audio files are saved. */
|
|
71
|
+
get outputDir(): string {
|
|
72
|
+
return this.options.outputDir || this.container.paths.join(this.container.feature('os').homedir, '.luca', 'tts-cache')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The 20 preset voice names available in Chatterbox Turbo. */
|
|
76
|
+
get voices(): readonly string[] {
|
|
77
|
+
return PRESET_VOICES
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Synthesize text to an audio file using Chatterbox Turbo.
|
|
82
|
+
*
|
|
83
|
+
* Calls the RunPod public endpoint, downloads the generated audio,
|
|
84
|
+
* and saves it to the output directory.
|
|
85
|
+
*
|
|
86
|
+
* @param text - The text to synthesize into speech
|
|
87
|
+
* @param options - Override voice, format, or provide a voiceUrl for cloning
|
|
88
|
+
* @returns Absolute path to the generated audio file
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* // Use a preset voice
|
|
93
|
+
* const path = await tts.synthesize('Good morning!', { voice: 'ethan' })
|
|
94
|
+
*
|
|
95
|
+
* // Clone a voice from a reference audio URL
|
|
96
|
+
* const path = await tts.synthesize('Hello world', {
|
|
97
|
+
* voiceUrl: 'https://example.com/reference.wav'
|
|
98
|
+
* })
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
async synthesize(text: string, options?: {
|
|
102
|
+
voice?: string
|
|
103
|
+
format?: 'wav' | 'flac' | 'ogg'
|
|
104
|
+
voiceUrl?: string
|
|
105
|
+
}): Promise<string> {
|
|
106
|
+
if (!this.apiKey) {
|
|
107
|
+
throw new Error('TTS requires a RunPod API key. Set RUNPOD_API_KEY or pass apiKey in options.')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const voice = options?.voice || this.options.voice || 'lucy'
|
|
111
|
+
const format = options?.format || this.options.format || 'wav'
|
|
112
|
+
|
|
113
|
+
this.setState({ generating: true, lastText: text })
|
|
114
|
+
|
|
115
|
+
const startTime = Date.now()
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const input: Record<string, any> = {
|
|
119
|
+
prompt: text,
|
|
120
|
+
format,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (options?.voiceUrl) {
|
|
124
|
+
input.voice_url = options.voiceUrl
|
|
125
|
+
} else {
|
|
126
|
+
input.voice = voice
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const response = await fetch(CHATTERBOX_ENDPOINT, {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
headers: {
|
|
132
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
},
|
|
135
|
+
body: JSON.stringify({ input }),
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
const body = await response.text()
|
|
140
|
+
throw new Error(`Chatterbox API error ${response.status}: ${body}`)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const data = await response.json() as { output?: { audio_url?: string }, error?: string }
|
|
144
|
+
|
|
145
|
+
if (data.error) {
|
|
146
|
+
throw new Error(`Chatterbox API error: ${data.error}`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const audioUrl = data.output?.audio_url
|
|
150
|
+
if (!audioUrl) {
|
|
151
|
+
throw new Error('No audio_url in Chatterbox response')
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Download the audio file
|
|
155
|
+
const audioResponse = await fetch(audioUrl)
|
|
156
|
+
if (!audioResponse.ok) {
|
|
157
|
+
throw new Error(`Failed to download audio: ${audioResponse.status}`)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const audioBuffer = Buffer.from(await audioResponse.arrayBuffer())
|
|
161
|
+
|
|
162
|
+
// Save to output dir with hash-based name
|
|
163
|
+
this.container.fs.ensureFolder(this.outputDir)
|
|
164
|
+
const hash = createHash('md5').update(text).digest('hex').slice(0, 8)
|
|
165
|
+
const filename = `${hash}-${Date.now()}.${format}`
|
|
166
|
+
const filePath = this.container.paths.join(this.outputDir, filename)
|
|
167
|
+
|
|
168
|
+
await this.container.fs.writeFileAsync(filePath, audioBuffer)
|
|
169
|
+
|
|
170
|
+
const durationMs = Date.now() - startTime
|
|
171
|
+
|
|
172
|
+
this.setState({ generating: false, lastFile: filePath })
|
|
173
|
+
this.emit('synthesized', text, filePath, voice, durationMs)
|
|
174
|
+
|
|
175
|
+
return filePath
|
|
176
|
+
} catch (error: any) {
|
|
177
|
+
this.setState({ generating: false })
|
|
178
|
+
this.emit('error', error)
|
|
179
|
+
throw error
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export default features.register('tts', TTS)
|