@hasna/skills 0.1.27 → 0.1.29
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/LICENSE +1 -10
- package/README.md +141 -39
- package/bin/index.js +30121 -27576
- package/bin/mcp.js +22073 -18556
- package/dist/cli/cli.test-utils.d.ts +15 -0
- package/dist/cli/commands/auth.d.ts +2 -0
- package/dist/cli/commands/install.d.ts +1 -1
- package/dist/cli/commands/runtime-mcp.d.ts +4 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +11606 -598
- package/dist/lib/auth-store.d.ts +13 -0
- package/dist/lib/installer.d.ts +58 -55
- package/dist/lib/mcp-contracts.d.ts +86 -0
- package/dist/lib/project-state.d.ts +43 -0
- package/dist/lib/registry-data/business-marketing.d.ts +2 -0
- package/dist/lib/registry-data/communication.d.ts +2 -0
- package/dist/lib/registry-data/content-generation.d.ts +2 -0
- package/dist/lib/registry-data/data-analysis.d.ts +2 -0
- package/dist/lib/registry-data/design-branding.d.ts +2 -0
- package/dist/lib/registry-data/development-tools.d.ts +2 -0
- package/dist/lib/registry-data/education-learning.d.ts +2 -0
- package/dist/lib/registry-data/event-management.d.ts +2 -0
- package/dist/lib/registry-data/finance-compliance.d.ts +2 -0
- package/dist/lib/registry-data/health-wellness.d.ts +2 -0
- package/dist/lib/registry-data/index.d.ts +2 -0
- package/dist/lib/registry-data/media-processing.d.ts +2 -0
- package/dist/lib/registry-data/productivity-organization.d.ts +2 -0
- package/dist/lib/registry-data/project-management.d.ts +2 -0
- package/dist/lib/registry-data/research-writing.d.ts +2 -0
- package/dist/lib/registry-data/science-academic.d.ts +2 -0
- package/dist/lib/registry-data/travel-lifestyle.d.ts +2 -0
- package/dist/lib/registry-data/web-browser.d.ts +2 -0
- package/dist/lib/registry-types.d.ts +27 -0
- package/dist/lib/registry.d.ts +6 -18
- package/dist/lib/remote-registry.d.ts +3 -0
- package/dist/lib/run-state.d.ts +60 -0
- package/dist/lib/skill-aliases.d.ts +17 -0
- package/dist/lib/skillinfo.d.ts +5 -1
- package/dist/mcp/discovery-tools.d.ts +2 -0
- package/dist/mcp/helpers.d.ts +26 -0
- package/dist/mcp/http.d.ts +10 -0
- package/dist/mcp/index.d.ts +3 -2
- package/dist/mcp/operation-tools.d.ts +2 -0
- package/dist/mcp/resource-meta-tools.d.ts +2 -0
- package/dist/mcp/schedule-tools.d.ts +2 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/types/api.d.ts +7 -4
- package/package.json +22 -11
- package/skills/_common/http-client.ts +1 -1
- package/skills/_common/index.ts +2 -3
- package/skills/_common/install.sh +5 -110
- package/skills/_common/installer.ts +31 -282
- package/skills/_common/skill-install.ts +14 -181
- package/skills/ad-creative-pack/SKILL.md +45 -0
- package/skills/ad-creative-pack/package.json +14 -0
- package/skills/advanced-math/package.json +3 -1
- package/skills/advanced-math/src/calculators.ts +118 -0
- package/skills/advanced-math/src/cli.ts +130 -0
- package/skills/advanced-math/src/conversion.ts +90 -0
- package/skills/advanced-math/src/finance.ts +75 -0
- package/skills/advanced-math/src/formatting.ts +95 -0
- package/skills/advanced-math/src/index.ts +24 -702
- package/skills/advanced-math/src/runtime.ts +49 -0
- package/skills/advanced-math/src/symbolic.ts +110 -0
- package/skills/advanced-math/src/types.ts +36 -0
- package/skills/analyze-data/SKILL.md +2 -2
- package/skills/analyze-data/src/analysis.ts +401 -0
- package/skills/analyze-data/src/cli.ts +66 -0
- package/skills/analyze-data/src/formatters.ts +235 -0
- package/skills/analyze-data/src/index.ts +6 -1027
- package/skills/analyze-data/src/logger.ts +36 -0
- package/skills/analyze-data/src/parsers.ts +57 -0
- package/skills/analyze-data/src/stats.ts +151 -0
- package/skills/analyze-data/src/types.ts +85 -0
- package/skills/api-docs-portal/SKILL.md +46 -0
- package/skills/api-docs-portal/package.json +9 -0
- package/skills/api-test-suite/src/index.ts +13 -0
- package/skills/apidocs/package.json +1 -1
- package/skills/apidocs/src/index.ts +3 -0
- package/skills/audio/package.json +2 -3
- package/skills/audio-cleanup-lab/SKILL.md +2 -2
- package/skills/audio-extract/CLAUDE.md +1 -1
- package/skills/audio-transcript-pack/SKILL.md +43 -0
- package/skills/audio-transcript-pack/package.json +10 -0
- package/skills/blog-article/CLAUDE.md +12 -0
- package/skills/blog-article/SKILL.md +45 -0
- package/skills/{create-blog-article → blog-article}/package.json +3 -3
- package/skills/brand-kit/SKILL.md +45 -0
- package/skills/brand-kit/package.json +14 -0
- package/skills/brand-photo-shoot/SKILL.md +28 -0
- package/skills/brand-photo-shoot/package.json +10 -0
- package/skills/brand-style-guide/SKILL.md +2 -2
- package/skills/brand-style-guide/src/index.ts +0 -0
- package/skills/budget-variance-analyzer/SKILL.md +2 -2
- package/skills/businessactivity/package.json +1 -1
- package/skills/businessactivity/src/index.ts +3 -0
- package/skills/calendar-events/src/ai-parser.ts +103 -0
- package/skills/calendar-events/src/api.ts +157 -0
- package/skills/calendar-events/src/auth.ts +22 -0
- package/skills/calendar-events/src/config.ts +6 -0
- package/skills/calendar-events/src/format.ts +96 -0
- package/skills/calendar-events/src/help.ts +54 -0
- package/skills/calendar-events/src/index.ts +21 -524
- package/skills/calendar-events/src/logger.ts +34 -0
- package/skills/calendar-events/src/types.ts +67 -0
- package/skills/compress-video/SKILL.md +2 -2
- package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.csv +16 -0
- package/skills/consolelog/exports/products-2025-12-14T13-50-53-041Z.json +227 -0
- package/skills/consolelog/package.json +1 -1
- package/skills/consolelog/src/index.ts +3 -0
- package/skills/contract-review-report/SKILL.md +43 -0
- package/skills/contract-review-report/package.json +10 -0
- package/skills/convert/SKILL.md +2 -3
- package/skills/customer-feedback-report/SKILL.md +44 -0
- package/skills/customer-feedback-report/package.json +10 -0
- package/skills/dashboard-builder/package.json +3 -1
- package/skills/database-explorer/package.json +3 -1
- package/skills/deepresearch/README.md +4 -13
- package/skills/deploy/src/http-client.ts +1 -1
- package/skills/diff-viewer/package.json +4 -1
- package/skills/doc-generate/package.json +0 -1
- package/skills/doc-generate/src/ai.ts +50 -0
- package/skills/doc-generate/src/cli.ts +203 -0
- package/skills/doc-generate/src/dependencies.ts +44 -0
- package/skills/doc-generate/src/document-builder.ts +299 -0
- package/skills/doc-generate/src/index.ts +40 -764
- package/skills/doc-generate/src/markdown-parser.ts +125 -0
- package/skills/doc-generate/src/types.ts +68 -0
- package/skills/domainpurchase/SKILL.md +1 -1
- package/skills/domainpurchase/package.json +1 -1
- package/skills/domainpurchase/src/index.ts +3 -0
- package/skills/domainsearch/SKILL.md +1 -1
- package/skills/domainsearch/package.json +1 -1
- package/skills/domainsearch/src/index.ts +3 -0
- package/skills/email-sequence/SKILL.md +44 -0
- package/skills/email-sequence/package.json +14 -0
- package/skills/excel/CLAUDE.md +2 -2
- package/skills/experiment-power-calculator/package.json +3 -1
- package/skills/extract-invoice/src/cli.ts +97 -0
- package/skills/extract-invoice/src/extractor.ts +170 -0
- package/skills/extract-invoice/src/file-utils.ts +46 -0
- package/skills/extract-invoice/src/formatters.ts +144 -0
- package/skills/extract-invoice/src/index.ts +44 -629
- package/skills/extract-invoice/src/runtime.ts +46 -0
- package/skills/extract-invoice/src/types.ts +88 -0
- package/skills/folder-tree/package.json +3 -1
- package/skills/form-filler/package.json +3 -1
- package/skills/generate-api-client/package.json +3 -1
- package/skills/generate-api-client/src/generator.ts +47 -0
- package/skills/generate-api-client/src/index.ts +3 -777
- package/skills/generate-api-client/src/logger.ts +34 -0
- package/skills/generate-api-client/src/python-generator.ts +245 -0
- package/skills/generate-api-client/src/spec-loader.ts +48 -0
- package/skills/generate-api-client/src/type-mappers.ts +79 -0
- package/skills/generate-api-client/src/types.ts +76 -0
- package/skills/generate-api-client/src/typescript-generator.ts +247 -0
- package/skills/generate-book-cover/package.json +3 -1
- package/skills/generate-dockerfile/src/cli.ts +78 -0
- package/skills/generate-dockerfile/src/dockerfile-templates.ts +392 -0
- package/skills/generate-dockerfile/src/index.ts +12 -790
- package/skills/generate-dockerfile/src/logger.ts +30 -0
- package/skills/generate-dockerfile/src/project-detection.ts +68 -0
- package/skills/generate-dockerfile/src/support-files.ts +171 -0
- package/skills/generate-dockerfile/src/types.ts +29 -0
- package/skills/generate-documentation/src/ai.ts +131 -0
- package/skills/generate-documentation/src/cli.ts +71 -0
- package/skills/generate-documentation/src/code-parser.ts +300 -0
- package/skills/generate-documentation/src/file-processing.ts +182 -0
- package/skills/generate-documentation/src/index.ts +13 -753
- package/skills/generate-documentation/src/runtime.ts +35 -0
- package/skills/generate-documentation/src/types.ts +30 -0
- package/skills/generate-env/package.json +3 -1
- package/skills/generate-env/src/cli.ts +85 -0
- package/skills/generate-env/src/detection.ts +161 -0
- package/skills/generate-env/src/env-data.ts +66 -0
- package/skills/generate-env/src/generators.ts +240 -0
- package/skills/generate-env/src/index.ts +76 -676
- package/skills/generate-env/src/runtime.ts +30 -0
- package/skills/generate-env/src/types.ts +32 -0
- package/skills/generate-favicon/package.json +3 -1
- package/skills/generate-mock-data/package.json +3 -1
- package/skills/generate-mock-data/src/ai.ts +102 -0
- package/skills/generate-mock-data/src/formatters.ts +84 -0
- package/skills/generate-mock-data/src/generator.ts +377 -0
- package/skills/generate-mock-data/src/index.ts +15 -716
- package/skills/generate-mock-data/src/logger.ts +37 -0
- package/skills/generate-mock-data/src/presets.ts +110 -0
- package/skills/generate-mock-data/src/types.ts +21 -0
- package/skills/generate-pr-description/src/ai.ts +144 -0
- package/skills/generate-pr-description/src/cli.ts +80 -0
- package/skills/generate-pr-description/src/clipboard.ts +30 -0
- package/skills/generate-pr-description/src/formatters.ts +231 -0
- package/skills/generate-pr-description/src/git.ts +153 -0
- package/skills/generate-pr-description/src/index.ts +21 -714
- package/skills/generate-pr-description/src/types.ts +49 -0
- package/skills/generate-presentation/src/ai-clients.ts +61 -0
- package/skills/generate-presentation/src/cli.ts +126 -0
- package/skills/generate-presentation/src/index.ts +3 -751
- package/skills/generate-presentation/src/logger.ts +67 -0
- package/skills/generate-presentation/src/presentation-generator.ts +425 -0
- package/skills/generate-presentation/src/runtime.ts +6 -0
- package/skills/generate-presentation/src/security.ts +12 -0
- package/skills/generate-presentation/src/types.ts +28 -0
- package/skills/generate-qrcode/package.json +4 -1
- package/skills/generate-regex/package.json +3 -1
- package/skills/generate-resume/src/cli.ts +157 -0
- package/skills/generate-resume/src/index.ts +13 -917
- package/skills/generate-resume/src/parsers.ts +95 -0
- package/skills/generate-resume/src/renderers.ts +538 -0
- package/skills/generate-resume/src/security.ts +39 -0
- package/skills/generate-resume/src/types.ts +86 -0
- package/skills/generate-social-posts/src/ai.ts +88 -0
- package/skills/generate-social-posts/src/cli.ts +118 -0
- package/skills/generate-social-posts/src/exporters.ts +126 -0
- package/skills/generate-social-posts/src/generator.ts +130 -0
- package/skills/generate-social-posts/src/index.ts +19 -709
- package/skills/generate-social-posts/src/platforms.ts +39 -0
- package/skills/generate-social-posts/src/runtime.ts +34 -0
- package/skills/generate-social-posts/src/source.ts +116 -0
- package/skills/generate-social-posts/src/types.ts +58 -0
- package/skills/gif-maker/package.json +4 -1
- package/skills/github-manager/package.json +3 -1
- package/skills/gmail/CLAUDE.md +1 -1
- package/skills/highlight-reel-generator/src/index.ts +19 -0
- package/skills/hook/src/commands/create.ts +20 -845
- package/skills/hook/src/templates/root.ts +196 -0
- package/skills/hook/src/templates/source.ts +647 -0
- package/skills/http-server/package.json +3 -1
- package/skills/icon-pack/README.md +28 -0
- package/skills/icon-pack/SKILL.md +23 -0
- package/skills/icon-pack/package.json +29 -0
- package/skills/{audio → icon-pack}/tsconfig.json +10 -12
- package/skills/image/package.json +1 -2
- package/skills/implementation-agent/package.json +3 -1
- package/skills/implementation-agent/src/ai-generation.ts +225 -0
- package/skills/implementation-agent/src/index.ts +3 -960
- package/skills/implementation-agent/src/minimist.d.ts +15 -0
- package/skills/implementation-agent/src/templates.ts +686 -0
- package/skills/implementation-agent/src/types.ts +53 -0
- package/skills/implementation-plan/package.json +3 -1
- package/skills/implementation-todo/package.json +3 -1
- package/skills/invoice/package.json +1 -1
- package/skills/invoice/src/index.ts +3 -0
- package/skills/invoice-reconciliation/SKILL.md +42 -0
- package/skills/invoice-reconciliation/package.json +10 -0
- package/skills/landing-page-pack/SKILL.md +47 -0
- package/skills/landing-page-pack/package.json +14 -0
- package/skills/latex-table-generator/package.json +3 -1
- package/skills/logo-design/SKILL.md +25 -44
- package/skills/logo-design/package.json +3 -15
- package/skills/lorem-generator/package.json +3 -1
- package/skills/lorem-generator/src/index.ts +13 -0
- package/skills/managehook/package.json +1 -1
- package/skills/managehook/src/index.ts +3 -0
- package/skills/managemcp/package.json +1 -1
- package/skills/managemcp/src/index.ts +3 -0
- package/skills/manageskill/package.json +1 -1
- package/skills/manageskill/src/index.ts +3 -0
- package/skills/markdown-validator/package.json +3 -1
- package/skills/markdown-validator/src/index.ts +1 -4
- package/skills/market-research-report/SKILL.md +41 -0
- package/skills/market-research-report/package.json +10 -0
- package/skills/mcp-builder/package.json +4 -1
- package/skills/mcp-builder/src/ai-descriptions.ts +37 -0
- package/skills/mcp-builder/src/generators.ts +513 -0
- package/skills/mcp-builder/src/index.ts +7 -908
- package/skills/mcp-builder/src/minimist.d.ts +15 -0
- package/skills/mcp-builder/src/naming.ts +12 -0
- package/skills/mcp-builder/src/options.ts +170 -0
- package/skills/mcp-builder/src/templates.ts +149 -0
- package/skills/mcp-builder/src/types.ts +42 -0
- package/skills/meeting-pack/SKILL.md +43 -0
- package/skills/meeting-pack/package.json +10 -0
- package/skills/merge-pdfs/package.json +5 -1
- package/skills/migration-plan-pack/SKILL.md +45 -0
- package/skills/migration-plan-pack/package.json +10 -0
- package/skills/music/package.json +2 -3
- package/skills/music-album/SKILL.md +37 -0
- package/skills/music-album/package.json +10 -0
- package/skills/notion-manager/package.json +3 -1
- package/skills/npmpublish/CLAUDE.md +5 -8
- package/skills/npmpublish/README.md +5 -26
- package/skills/npmpublish/src/index.ts +9 -147
- package/skills/one-page-website/SKILL.md +46 -0
- package/skills/one-page-website/package.json +10 -0
- package/skills/one-page-website/tsconfig.json +8 -0
- package/skills/pdf-generate/src/cli.ts +162 -0
- package/skills/pdf-generate/src/html.ts +84 -0
- package/skills/pdf-generate/src/index.ts +11 -800
- package/skills/pdf-generate/src/markdown.ts +27 -0
- package/skills/pdf-generate/src/pdf-writer.ts +78 -0
- package/skills/pdf-generate/src/runtime.ts +34 -0
- package/skills/pdf-generate/src/security.ts +37 -0
- package/skills/pdf-generate/src/templates.ts +311 -0
- package/skills/pdf-generate/src/types.ts +28 -0
- package/skills/pdf-read/SKILL.md +10 -10
- package/skills/pdf-to-dataset/SKILL.md +45 -0
- package/skills/pdf-to-dataset/package.json +10 -0
- package/skills/pdf-to-markdown/SKILL.md +49 -0
- package/skills/pdf-to-markdown/package.json +10 -0
- package/skills/pdf-to-markdown/tsconfig.json +10 -0
- package/skills/performance-audit-report/SKILL.md +42 -0
- package/skills/performance-audit-report/package.json +10 -0
- package/skills/persona-based-adwriter/src/index.ts +19 -0
- package/skills/photo-album/SKILL.md +29 -0
- package/skills/photo-album/package.json +9 -0
- package/skills/photo-album/tsconfig.json +4 -0
- package/skills/pitch-deck/SKILL.md +43 -0
- package/skills/pitch-deck/package.json +9 -0
- package/skills/playlist-maker/SKILL.md +33 -0
- package/skills/playlist-maker/package.json +9 -0
- package/skills/playlist-maker/tsconfig.json +4 -0
- package/skills/product-mockup/SKILL.md +45 -0
- package/skills/product-mockup/package.json +3 -20
- package/skills/product-mockup/tsconfig.json +3 -5
- package/skills/project-retro-companion/src/index.ts +19 -0
- package/skills/proposal-pack/SKILL.md +45 -0
- package/skills/proposal-pack/package.json +10 -0
- package/skills/read-pdf/SKILL.md +5 -4
- package/skills/repo-onboarding-report/SKILL.md +42 -0
- package/skills/repo-onboarding-report/package.json +10 -0
- package/skills/sales-call-recapper/src/index.ts +20 -0
- package/skills/salescopy/package.json +1 -1
- package/skills/salescopy/src/index.ts +3 -0
- package/skills/scaffold-project/src/ai-detect.ts +136 -0
- package/skills/scaffold-project/src/file-generators.ts +292 -0
- package/skills/scaffold-project/src/index.ts +8 -991
- package/skills/scaffold-project/src/project-config.ts +338 -0
- package/skills/scaffold-project/src/templates.ts +173 -0
- package/skills/scaffold-project/src/types.ts +58 -0
- package/skills/scientific-figure-check/package.json +3 -1
- package/skills/sdk-generator/SKILL.md +45 -0
- package/skills/sdk-generator/package.json +10 -0
- package/skills/sdk-generator/tsconfig.json +8 -0
- package/skills/security-audit/src/index.ts +25 -6
- package/skills/security-audit-report/SKILL.md +40 -0
- package/skills/security-audit-report/package.json +10 -0
- package/skills/seo-content-pack/SKILL.md +44 -0
- package/skills/seo-content-pack/package.json +9 -0
- package/skills/short-video-pack/SKILL.md +30 -0
- package/skills/short-video-pack/package.json +10 -0
- package/skills/slack-assistant/package.json +3 -1
- package/skills/slide-deck-generator/SKILL.md +44 -0
- package/skills/slide-deck-generator/package.json +10 -0
- package/skills/sms/package.json +1 -1
- package/skills/sms/src/index.ts +15 -0
- package/skills/social-content-calendar/SKILL.md +45 -0
- package/skills/social-content-calendar/package.json +14 -0
- package/skills/split-pdf/package.json +4 -1
- package/skills/subtitle/package.json +2 -1
- package/skills/subtitle/src/index.ts +3 -0
- package/skills/terraform-generator/package.json +3 -1
- package/skills/test-suite-generator/SKILL.md +41 -0
- package/skills/test-suite-generator/package.json +10 -0
- package/skills/timesheet/package.json +1 -1
- package/skills/timesheet/src/index.ts +3 -0
- package/skills/transcript/SKILL.md +1 -8
- package/skills/validate-config/package.json +3 -1
- package/skills/video/package.json +6 -4
- package/skills/video-downloader/package.json +3 -1
- package/skills/video-highlight-pack/SKILL.md +44 -0
- package/skills/video-highlight-pack/package.json +10 -0
- package/skills/voiceover-jingle-pack/SKILL.md +28 -0
- package/skills/voiceover-jingle-pack/package.json +10 -0
- package/skills/watermark/package.json +6 -1
- package/skills/webcrawling/package.json +2 -1
- package/skills/write/SKILL.md +6 -6
- package/dist/server/serve.d.ts +0 -11
- package/skills/apidocs/.claude/settings.json +0 -5
- package/skills/audio/.env.example +0 -14
- package/skills/audio/QUICKSTART.md +0 -158
- package/skills/audio/README.md +0 -256
- package/skills/audio/src/index-local.ts +0 -206
- package/skills/audio/src/index.ts +0 -95
- package/skills/audio/src/providers/elevenlabs.ts +0 -115
- package/skills/audio/src/providers/google.ts +0 -116
- package/skills/audio/src/providers/minimax.ts +0 -83
- package/skills/audio/src/providers/openai.ts +0 -115
- package/skills/audio/src/types.ts +0 -79
- package/skills/audiobook-chapter-proofer/CLAUDE.md +0 -19
- package/skills/audiobook-chapter-proofer/package.json +0 -27
- package/skills/audiobook-chapter-proofer/src/index.ts +0 -285
- package/skills/browse/src/client.ts +0 -373
- package/skills/browse/src/index-local.ts +0 -430
- package/skills/browse/src/index.ts +0 -110
- package/skills/browse/src/sse-server.ts +0 -919
- package/skills/browse/src/types.ts +0 -104
- package/skills/consolelog/src/server/index.ts +0 -508
- package/skills/create-blog-article/CLAUDE.md +0 -19
- package/skills/create-blog-article/src/index.ts +0 -745
- package/skills/create-blog-article/tsconfig.json +0 -10
- package/skills/deepresearch/src/agents/query-generator.ts +0 -91
- package/skills/deepresearch/src/agents/synthesizer.ts +0 -111
- package/skills/deepresearch/src/index.ts +0 -224
- package/skills/deepresearch/src/research.ts +0 -166
- package/skills/deepresearch/src/services/anthropic.ts +0 -69
- package/skills/deepresearch/src/services/exa.ts +0 -108
- package/skills/deepresearch/src/services/firecrawl.ts +0 -88
- package/skills/deepresearch/src/services/openai.ts +0 -81
- package/skills/deepresearch/src/types.ts +0 -76
- package/skills/deepresearch/src/utils/file.ts +0 -111
- package/skills/deepresearch/src/utils/logger.ts +0 -84
- package/skills/domainpurchase/src/server/index.ts +0 -332
- package/skills/domainsearch/src/server/index.ts +0 -229
- package/skills/e2bswarm/README.md +0 -135
- package/skills/e2bswarm/SKILL.md +0 -118
- package/skills/e2bswarm/examples/tasks-example.json +0 -38
- package/skills/e2bswarm/package.json +0 -59
- package/skills/e2bswarm/src/commands/collect.ts +0 -135
- package/skills/e2bswarm/src/commands/install.ts +0 -164
- package/skills/e2bswarm/src/commands/kill.ts +0 -62
- package/skills/e2bswarm/src/commands/spawn.ts +0 -134
- package/skills/e2bswarm/src/commands/status.ts +0 -90
- package/skills/e2bswarm/src/commands/sync.ts +0 -208
- package/skills/e2bswarm/src/index.ts +0 -121
- package/skills/e2bswarm/src/lib/config.ts +0 -75
- package/skills/e2bswarm/src/lib/e2b.ts +0 -490
- package/skills/e2bswarm/src/lib/github.ts +0 -253
- package/skills/e2bswarm/src/lib/logger.ts +0 -41
- package/skills/e2bswarm/src/lib/paths.ts +0 -75
- package/skills/e2bswarm/src/lib/tasks.ts +0 -320
- package/skills/e2bswarm/src/types/index.ts +0 -107
- package/skills/e2bswarm/templates/codebox/e2b.Dockerfile +0 -38
- package/skills/e2bswarm/templates/codebox/e2b.toml +0 -3
- package/skills/e2bswarm/templates/setup.sh +0 -21
- package/skills/e2bswarm/tsconfig.json +0 -19
- package/skills/generate-book-cover/src/index.ts +0 -694
- package/skills/image/src/index-local.ts +0 -206
- package/skills/image/src/index.ts +0 -96
- package/skills/image/src/providers/google.ts +0 -79
- package/skills/image/src/providers/minimax.ts +0 -94
- package/skills/image/src/providers/openai.ts +0 -80
- package/skills/image/src/providers/xai.ts +0 -73
- package/skills/image/src/types.ts +0 -37
- package/skills/logo-design/CLAUDE.md +0 -30
- package/skills/logo-design/src/index.ts +0 -322
- package/skills/managehook/src/server/index.ts +0 -108
- package/skills/managemcp/src/server/index.ts +0 -108
- package/skills/manageskill/src/server/index.ts +0 -108
- package/skills/music/CLAUDE.md +0 -9
- package/skills/music/src/index.ts +0 -94
- package/skills/music/tsconfig.json +0 -10
- package/skills/pdf-read/src/index.ts +0 -320
- package/skills/product-mockup/CLAUDE.md +0 -19
- package/skills/product-mockup/src/index.ts +0 -290
- package/skills/read-pdf/src/index.ts +0 -388
- package/skills/remove-background/src/index.ts +0 -405
- package/skills/sound-effects/SKILL.md +0 -34
- package/skills/sound-effects/package.json +0 -21
- package/skills/sound-effects/src/index.ts +0 -172
- package/skills/sound-effects/tsconfig.json +0 -8
- package/skills/transcript/src/chunker.ts +0 -215
- package/skills/transcript/src/formatter.ts +0 -134
- package/skills/transcript/src/index-local.ts +0 -226
- package/skills/transcript/src/index.ts +0 -110
- package/skills/transcript/src/providers/elevenlabs.ts +0 -133
- package/skills/transcript/src/providers/gemini.ts +0 -192
- package/skills/transcript/src/providers/index.ts +0 -54
- package/skills/transcript/src/providers/openai.ts +0 -203
- package/skills/transcript/src/types.ts +0 -106
- package/skills/video/.env.example +0 -14
- package/skills/video/EXAMPLES.md +0 -266
- package/skills/video/LICENSE +0 -192
- package/skills/video/README.md +0 -174
- package/skills/video/src/cli.ts +0 -155
- package/skills/video/src/index-local.ts +0 -148
- package/skills/video/src/index.ts +0 -96
- package/skills/video/src/providers/google-veo.ts +0 -126
- package/skills/video/src/providers/index.ts +0 -22
- package/skills/video/src/providers/minimax.ts +0 -100
- package/skills/video/src/providers/openai-sora.ts +0 -164
- package/skills/video/src/providers/runway.ts +0 -159
- package/skills/video/src/types.ts +0 -35
- package/skills/video/tsconfig.json +0 -22
- package/skills/voiceover-casting-assistant/CLAUDE.md +0 -19
- package/skills/voiceover-casting-assistant/package.json +0 -27
- package/skills/voiceover-casting-assistant/src/index.ts +0 -255
- package/skills/voiceover-casting-assistant/tsconfig.json +0 -10
- package/skills/webcrawling/src/commands/config.ts +0 -34
- package/skills/webcrawling/src/commands/crawl.ts +0 -33
- package/skills/webcrawling/src/commands/scrape.ts +0 -32
- package/skills/webcrawling/src/commands/sessions.ts +0 -42
- package/skills/webcrawling/src/lib/crawler.ts +0 -174
- package/skills/webcrawling/src/lib/storage.ts +0 -130
- package/skills/webcrawling/src/types/index.ts +0 -45
- package/skills/webcrawling/src/utils/logger.ts +0 -30
- package/skills/webcrawling/src/utils/paths.ts +0 -28
- /package/skills/{audiobook-chapter-proofer → blog-article}/tsconfig.json +0 -0
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ElevenLabs Scribe Provider
|
|
3
|
-
* High-accuracy speech-to-text with speaker diarization
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
TranscriptionProvider,
|
|
8
|
-
TranscriptionOptions,
|
|
9
|
-
TranscriptionResult,
|
|
10
|
-
TranscriptionSegment,
|
|
11
|
-
ElevenLabsResponse
|
|
12
|
-
} from '../types';
|
|
13
|
-
|
|
14
|
-
// ElevenLabs supports up to 3GB files
|
|
15
|
-
const MAX_FILE_SIZE = 3 * 1024 * 1024 * 1024; // 3GB
|
|
16
|
-
|
|
17
|
-
export class ElevenLabsProvider implements TranscriptionProvider {
|
|
18
|
-
name = 'ElevenLabs Scribe';
|
|
19
|
-
maxFileSize = MAX_FILE_SIZE;
|
|
20
|
-
supportedFormats = ['mp3', 'mp4', 'wav', 'webm', 'm4a', 'ogg', 'flac'];
|
|
21
|
-
|
|
22
|
-
private apiKey: string;
|
|
23
|
-
private baseUrl = 'https://api.elevenlabs.io/v1';
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
const apiKey = process.env.ELEVENLABS_API_KEY;
|
|
27
|
-
if (!apiKey) {
|
|
28
|
-
throw new Error('ELEVENLABS_API_KEY environment variable is required');
|
|
29
|
-
}
|
|
30
|
-
this.apiKey = apiKey;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async transcribe(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
34
|
-
const {
|
|
35
|
-
input,
|
|
36
|
-
language,
|
|
37
|
-
model = 'scribe_v1',
|
|
38
|
-
diarize = true,
|
|
39
|
-
timestamps = true
|
|
40
|
-
} = options;
|
|
41
|
-
|
|
42
|
-
console.log(`[ElevenLabs] Transcribing: ${input}`);
|
|
43
|
-
console.log(`[ElevenLabs] Model: ${model}`);
|
|
44
|
-
console.log(`[ElevenLabs] Diarization: ${diarize}`);
|
|
45
|
-
|
|
46
|
-
// Read the file
|
|
47
|
-
const file = Bun.file(input);
|
|
48
|
-
const fileBuffer = await file.arrayBuffer();
|
|
49
|
-
|
|
50
|
-
// Create form data
|
|
51
|
-
const formData = new FormData();
|
|
52
|
-
formData.append('audio', new Blob([fileBuffer]), input.split('/').pop());
|
|
53
|
-
formData.append('model_id', model);
|
|
54
|
-
|
|
55
|
-
if (language) {
|
|
56
|
-
formData.append('language_code', language);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (diarize) {
|
|
60
|
-
formData.append('diarize', 'true');
|
|
61
|
-
formData.append('num_speakers', '32'); // Max supported speakers
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (timestamps) {
|
|
65
|
-
formData.append('timestamps_granularity', 'word');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const response = await fetch(`${this.baseUrl}/speech-to-text`, {
|
|
69
|
-
method: 'POST',
|
|
70
|
-
headers: {
|
|
71
|
-
'xi-api-key': this.apiKey
|
|
72
|
-
},
|
|
73
|
-
body: formData
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
if (!response.ok) {
|
|
77
|
-
const error = await response.text();
|
|
78
|
-
throw new Error(`ElevenLabs transcription failed: ${error}`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const data = await response.json() as ElevenLabsResponse;
|
|
82
|
-
console.log(`[ElevenLabs] Transcription complete`);
|
|
83
|
-
|
|
84
|
-
return this.formatResult(data, model);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private formatResult(data: ElevenLabsResponse, model: string): TranscriptionResult {
|
|
88
|
-
const segments: TranscriptionSegment[] = [];
|
|
89
|
-
|
|
90
|
-
if (data.words) {
|
|
91
|
-
let currentSegment: TranscriptionSegment | null = null;
|
|
92
|
-
let segmentId = 0;
|
|
93
|
-
|
|
94
|
-
for (const word of data.words) {
|
|
95
|
-
if (!currentSegment || word.speaker !== currentSegment.speaker) {
|
|
96
|
-
if (currentSegment) {
|
|
97
|
-
segments.push(currentSegment);
|
|
98
|
-
}
|
|
99
|
-
currentSegment = {
|
|
100
|
-
id: segmentId++,
|
|
101
|
-
start: word.start,
|
|
102
|
-
end: word.end,
|
|
103
|
-
text: word.word,
|
|
104
|
-
speaker: word.speaker
|
|
105
|
-
};
|
|
106
|
-
} else {
|
|
107
|
-
currentSegment.end = word.end;
|
|
108
|
-
currentSegment.text += ' ' + word.word;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (currentSegment) {
|
|
113
|
-
segments.push(currentSegment);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const speakers = data.speakers?.map(s => ({
|
|
118
|
-
id: s.speaker_id,
|
|
119
|
-
name: s.name,
|
|
120
|
-
segments: segments
|
|
121
|
-
.filter(seg => seg.speaker === s.speaker_id)
|
|
122
|
-
.map(seg => seg.id)
|
|
123
|
-
}));
|
|
124
|
-
|
|
125
|
-
return {
|
|
126
|
-
text: data.text,
|
|
127
|
-
segments: segments.length > 0 ? segments : undefined,
|
|
128
|
-
speakers,
|
|
129
|
-
model,
|
|
130
|
-
provider: 'elevenlabs'
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
}
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Google Gemini Provider
|
|
3
|
-
* Multimodal transcription with analysis capabilities
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { readFile } from 'fs/promises';
|
|
7
|
-
import type {
|
|
8
|
-
TranscriptionProvider,
|
|
9
|
-
TranscriptionOptions,
|
|
10
|
-
TranscriptionResult,
|
|
11
|
-
GeminiResponse
|
|
12
|
-
} from '../types';
|
|
13
|
-
import { getFileSize, needsChunking, splitAudioFile, mergeTranscriptions, cleanupChunks } from '../chunker';
|
|
14
|
-
import { dirname, join } from 'path';
|
|
15
|
-
|
|
16
|
-
// Gemini supports up to 2GB files
|
|
17
|
-
const MAX_FILE_SIZE = 2 * 1024 * 1024 * 1024; // 2GB
|
|
18
|
-
|
|
19
|
-
const MIME_TYPES: Record<string, string> = {
|
|
20
|
-
'mp3': 'audio/mpeg',
|
|
21
|
-
'wav': 'audio/wav',
|
|
22
|
-
'ogg': 'audio/ogg',
|
|
23
|
-
'flac': 'audio/flac',
|
|
24
|
-
'm4a': 'audio/mp4',
|
|
25
|
-
'aac': 'audio/aac',
|
|
26
|
-
'mp4': 'video/mp4',
|
|
27
|
-
'webm': 'video/webm'
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export class GeminiProvider implements TranscriptionProvider {
|
|
31
|
-
name = 'Google Gemini';
|
|
32
|
-
maxFileSize = MAX_FILE_SIZE;
|
|
33
|
-
supportedFormats = ['mp3', 'wav', 'ogg', 'flac', 'm4a', 'aac', 'mp4', 'webm'];
|
|
34
|
-
|
|
35
|
-
private apiKey: string;
|
|
36
|
-
private baseUrl = 'https://generativelanguage.googleapis.com/v1beta';
|
|
37
|
-
|
|
38
|
-
constructor() {
|
|
39
|
-
const apiKey = process.env.GOOGLE_API_KEY;
|
|
40
|
-
if (!apiKey) {
|
|
41
|
-
throw new Error('GOOGLE_API_KEY environment variable is required');
|
|
42
|
-
}
|
|
43
|
-
this.apiKey = apiKey;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async transcribe(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
47
|
-
const {
|
|
48
|
-
input,
|
|
49
|
-
language,
|
|
50
|
-
model = 'gemini-2.0-flash',
|
|
51
|
-
diarize = false,
|
|
52
|
-
timestamps = false
|
|
53
|
-
} = options;
|
|
54
|
-
|
|
55
|
-
console.log(`[Gemini] Transcribing: ${input}`);
|
|
56
|
-
console.log(`[Gemini] Model: ${model}`);
|
|
57
|
-
|
|
58
|
-
// Check file size
|
|
59
|
-
const fileSize = await getFileSize(input);
|
|
60
|
-
console.log(`[Gemini] File size: ${(fileSize / 1024 / 1024).toFixed(2)}MB`);
|
|
61
|
-
|
|
62
|
-
// For very large files, use chunking
|
|
63
|
-
if (fileSize > 100 * 1024 * 1024) { // > 100MB use chunking for efficiency
|
|
64
|
-
console.log(`[Gemini] Large file detected, using chunking for efficiency`);
|
|
65
|
-
return this.transcribeWithChunking(options);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return this.transcribeSingle(options);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
private async transcribeSingle(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
72
|
-
const {
|
|
73
|
-
input,
|
|
74
|
-
language,
|
|
75
|
-
model = 'gemini-2.0-flash',
|
|
76
|
-
diarize = false,
|
|
77
|
-
timestamps = false
|
|
78
|
-
} = options;
|
|
79
|
-
|
|
80
|
-
// Read and encode file
|
|
81
|
-
const fileBuffer = await readFile(input);
|
|
82
|
-
const base64Audio = fileBuffer.toString('base64');
|
|
83
|
-
|
|
84
|
-
// Determine MIME type
|
|
85
|
-
const ext = input.split('.').pop()?.toLowerCase() || 'mp3';
|
|
86
|
-
const mimeType = MIME_TYPES[ext] || 'audio/mpeg';
|
|
87
|
-
|
|
88
|
-
// Build prompt based on options
|
|
89
|
-
let prompt = 'Transcribe this audio accurately. ';
|
|
90
|
-
|
|
91
|
-
if (language) {
|
|
92
|
-
prompt += `The audio is in ${language}. `;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (diarize) {
|
|
96
|
-
prompt += 'Identify and label different speakers (Speaker A, Speaker B, etc.). ';
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (timestamps) {
|
|
100
|
-
prompt += 'Include timestamps for each segment in [HH:MM:SS] format. ';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
prompt += 'Provide only the transcription without any additional commentary.';
|
|
104
|
-
|
|
105
|
-
const response = await fetch(
|
|
106
|
-
`${this.baseUrl}/models/${model}:generateContent?key=${this.apiKey}`,
|
|
107
|
-
{
|
|
108
|
-
method: 'POST',
|
|
109
|
-
headers: {
|
|
110
|
-
'Content-Type': 'application/json'
|
|
111
|
-
},
|
|
112
|
-
body: JSON.stringify({
|
|
113
|
-
contents: [
|
|
114
|
-
{
|
|
115
|
-
parts: [
|
|
116
|
-
{
|
|
117
|
-
inline_data: {
|
|
118
|
-
mime_type: mimeType,
|
|
119
|
-
data: base64Audio
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
text: prompt
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
],
|
|
128
|
-
generationConfig: {
|
|
129
|
-
temperature: 0,
|
|
130
|
-
maxOutputTokens: 8192
|
|
131
|
-
}
|
|
132
|
-
})
|
|
133
|
-
}
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
if (!response.ok) {
|
|
137
|
-
const error = await response.text();
|
|
138
|
-
throw new Error(`Gemini transcription failed: ${error}`);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const data = await response.json() as GeminiResponse;
|
|
142
|
-
const text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
|
143
|
-
|
|
144
|
-
console.log(`[Gemini] Transcription complete`);
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
text: text.trim(),
|
|
148
|
-
model,
|
|
149
|
-
provider: 'gemini'
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
private async transcribeWithChunking(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
154
|
-
const { input, model = 'gemini-2.0-flash' } = options;
|
|
155
|
-
const outputDir = dirname(input);
|
|
156
|
-
|
|
157
|
-
// Split into chunks
|
|
158
|
-
const chunks = await splitAudioFile(input, outputDir);
|
|
159
|
-
const transcriptions: string[] = [];
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
// Process chunks in parallel (Gemini can handle concurrent requests)
|
|
163
|
-
const promises = chunks.map(async (chunk) => {
|
|
164
|
-
console.log(`[Gemini] Processing chunk ${chunk.index + 1}/${chunks.length}`);
|
|
165
|
-
const result = await this.transcribeSingle({
|
|
166
|
-
...options,
|
|
167
|
-
input: chunk.path
|
|
168
|
-
});
|
|
169
|
-
return { index: chunk.index, text: result.text };
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
const results = await Promise.all(promises);
|
|
173
|
-
|
|
174
|
-
// Sort by index and extract texts
|
|
175
|
-
results.sort((a, b) => a.index - b.index);
|
|
176
|
-
transcriptions.push(...results.map(r => r.text));
|
|
177
|
-
|
|
178
|
-
// Merge transcriptions
|
|
179
|
-
const mergedText = mergeTranscriptions(transcriptions);
|
|
180
|
-
|
|
181
|
-
return {
|
|
182
|
-
text: mergedText,
|
|
183
|
-
model,
|
|
184
|
-
provider: 'gemini'
|
|
185
|
-
};
|
|
186
|
-
} finally {
|
|
187
|
-
// Cleanup chunks
|
|
188
|
-
const chunkDir = join(outputDir, '.chunks');
|
|
189
|
-
await cleanupChunks(chunkDir);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Provider Factory
|
|
3
|
-
* Returns the appropriate transcription provider
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ElevenLabsProvider } from './elevenlabs';
|
|
7
|
-
import { OpenAIProvider } from './openai';
|
|
8
|
-
import { GeminiProvider } from './gemini';
|
|
9
|
-
import type { TranscriptionProvider, Provider } from '../types';
|
|
10
|
-
|
|
11
|
-
export function getProvider(providerName: Provider): TranscriptionProvider {
|
|
12
|
-
switch (providerName) {
|
|
13
|
-
case 'elevenlabs':
|
|
14
|
-
return new ElevenLabsProvider();
|
|
15
|
-
case 'openai':
|
|
16
|
-
return new OpenAIProvider();
|
|
17
|
-
case 'gemini':
|
|
18
|
-
return new GeminiProvider();
|
|
19
|
-
default:
|
|
20
|
-
throw new Error(
|
|
21
|
-
`Unknown provider: ${providerName}. Available: elevenlabs, openai, gemini`
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function getProviderInfo(): void {
|
|
27
|
-
console.log(`
|
|
28
|
-
Available Transcription Providers:
|
|
29
|
-
|
|
30
|
-
ELEVENLABS (Scribe)
|
|
31
|
-
- Accuracy: 96.7% for English
|
|
32
|
-
- Max file size: 3GB / 10 hours
|
|
33
|
-
- Features: Speaker diarization (up to 32 speakers), word timestamps
|
|
34
|
-
- Cost: $0.40/hour
|
|
35
|
-
- Best for: Multi-speaker recordings, highest accuracy needs
|
|
36
|
-
|
|
37
|
-
OPENAI (Whisper)
|
|
38
|
-
- Accuracy: Excellent
|
|
39
|
-
- Max file size: 25MB (auto-chunking for larger files)
|
|
40
|
-
- Features: Segment timestamps, language detection
|
|
41
|
-
- Cost: $0.006/min (GPT-4o Mini: $0.003/min)
|
|
42
|
-
- Best for: Standard transcription, good balance of cost/quality
|
|
43
|
-
|
|
44
|
-
GEMINI (Flash)
|
|
45
|
-
- Accuracy: Very good
|
|
46
|
-
- Max file size: 2GB
|
|
47
|
-
- Features: Multimodal analysis, summarization
|
|
48
|
-
- Cost: ~$0.09-0.23/hour (generous free tier)
|
|
49
|
-
- Best for: Cost-sensitive, multimodal needs, free tier usage
|
|
50
|
-
|
|
51
|
-
USAGE:
|
|
52
|
-
transcript transcribe --provider <name> --input <file> [options]
|
|
53
|
-
`);
|
|
54
|
-
}
|
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenAI Whisper Provider
|
|
3
|
-
* Industry-standard speech-to-text with automatic chunking for large files
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
TranscriptionProvider,
|
|
8
|
-
TranscriptionOptions,
|
|
9
|
-
TranscriptionResult,
|
|
10
|
-
TranscriptionSegment,
|
|
11
|
-
OpenAITranscriptionResponse
|
|
12
|
-
} from '../types';
|
|
13
|
-
import {
|
|
14
|
-
needsChunking,
|
|
15
|
-
splitAudioFile,
|
|
16
|
-
mergeTranscriptions,
|
|
17
|
-
cleanupChunks,
|
|
18
|
-
compressAudio,
|
|
19
|
-
getFileSize
|
|
20
|
-
} from '../chunker';
|
|
21
|
-
import { dirname, join, basename, extname } from 'path';
|
|
22
|
-
|
|
23
|
-
// OpenAI Whisper has a 25MB limit
|
|
24
|
-
const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25MB
|
|
25
|
-
|
|
26
|
-
export class OpenAIProvider implements TranscriptionProvider {
|
|
27
|
-
name = 'OpenAI Whisper';
|
|
28
|
-
maxFileSize = MAX_FILE_SIZE;
|
|
29
|
-
supportedFormats = ['mp3', 'mp4', 'mpeg', 'mpga', 'm4a', 'wav', 'webm'];
|
|
30
|
-
|
|
31
|
-
private apiKey: string;
|
|
32
|
-
private baseUrl = 'https://api.openai.com/v1';
|
|
33
|
-
|
|
34
|
-
constructor() {
|
|
35
|
-
const apiKey = process.env.OPENAI_API_KEY;
|
|
36
|
-
if (!apiKey) {
|
|
37
|
-
throw new Error('OPENAI_API_KEY environment variable is required');
|
|
38
|
-
}
|
|
39
|
-
this.apiKey = apiKey;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async transcribe(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
43
|
-
const {
|
|
44
|
-
input,
|
|
45
|
-
language,
|
|
46
|
-
model = 'whisper-1',
|
|
47
|
-
timestamps = true
|
|
48
|
-
} = options;
|
|
49
|
-
|
|
50
|
-
console.log(`[OpenAI] Transcribing: ${input}`);
|
|
51
|
-
console.log(`[OpenAI] Model: ${model}`);
|
|
52
|
-
|
|
53
|
-
// Check if file needs chunking
|
|
54
|
-
const fileSize = await getFileSize(input);
|
|
55
|
-
console.log(`[OpenAI] File size: ${(fileSize / 1024 / 1024).toFixed(2)}MB`);
|
|
56
|
-
|
|
57
|
-
if (fileSize > this.maxFileSize) {
|
|
58
|
-
console.log(`[OpenAI] File exceeds 25MB limit, chunking required`);
|
|
59
|
-
return this.transcribeWithChunking(options);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return this.transcribeSingle(options);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private async transcribeSingle(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
66
|
-
const {
|
|
67
|
-
input,
|
|
68
|
-
language,
|
|
69
|
-
model = 'whisper-1',
|
|
70
|
-
timestamps = true
|
|
71
|
-
} = options;
|
|
72
|
-
|
|
73
|
-
// Read the file
|
|
74
|
-
const file = Bun.file(input);
|
|
75
|
-
const fileBuffer = await file.arrayBuffer();
|
|
76
|
-
|
|
77
|
-
// Create form data
|
|
78
|
-
const formData = new FormData();
|
|
79
|
-
formData.append('file', new Blob([fileBuffer]), input.split('/').pop());
|
|
80
|
-
formData.append('model', model);
|
|
81
|
-
formData.append('response_format', timestamps ? 'verbose_json' : 'json');
|
|
82
|
-
|
|
83
|
-
if (language) {
|
|
84
|
-
formData.append('language', language);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (timestamps) {
|
|
88
|
-
formData.append('timestamp_granularities[]', 'segment');
|
|
89
|
-
formData.append('timestamp_granularities[]', 'word');
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const response = await fetch(`${this.baseUrl}/audio/transcriptions`, {
|
|
93
|
-
method: 'POST',
|
|
94
|
-
headers: {
|
|
95
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
96
|
-
},
|
|
97
|
-
body: formData
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
if (!response.ok) {
|
|
101
|
-
const error = await response.text();
|
|
102
|
-
throw new Error(`OpenAI transcription failed: ${error}`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const data = await response.json() as OpenAITranscriptionResponse;
|
|
106
|
-
console.log(`[OpenAI] Transcription complete`);
|
|
107
|
-
|
|
108
|
-
return this.formatResult(data, model);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private async transcribeWithChunking(options: TranscriptionOptions): Promise<TranscriptionResult> {
|
|
112
|
-
const { input, model = 'whisper-1' } = options;
|
|
113
|
-
const outputDir = dirname(input);
|
|
114
|
-
|
|
115
|
-
// First try compression
|
|
116
|
-
const compressedPath = join(outputDir, `.compressed_${basename(input, extname(input))}.ogg`);
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
console.log('[OpenAI] Attempting compression first...');
|
|
120
|
-
await compressAudio(input, compressedPath, '32k');
|
|
121
|
-
const compressedSize = await getFileSize(compressedPath);
|
|
122
|
-
|
|
123
|
-
if (compressedSize <= this.maxFileSize) {
|
|
124
|
-
console.log('[OpenAI] Compressed file is under 25MB, transcribing directly');
|
|
125
|
-
const result = await this.transcribeSingle({
|
|
126
|
-
...options,
|
|
127
|
-
input: compressedPath
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// Cleanup compressed file
|
|
131
|
-
await Bun.write(compressedPath, '').catch(() => {});
|
|
132
|
-
|
|
133
|
-
return result;
|
|
134
|
-
}
|
|
135
|
-
} catch {
|
|
136
|
-
console.log('[OpenAI] Compression failed or still too large, falling back to chunking');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Split into chunks
|
|
140
|
-
const chunks = await splitAudioFile(input, outputDir);
|
|
141
|
-
const transcriptions: string[] = [];
|
|
142
|
-
const allSegments: TranscriptionSegment[] = [];
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
// Process chunks sequentially to maintain order
|
|
146
|
-
for (const chunk of chunks) {
|
|
147
|
-
console.log(`[OpenAI] Processing chunk ${chunk.index + 1}/${chunks.length}`);
|
|
148
|
-
|
|
149
|
-
const result = await this.transcribeSingle({
|
|
150
|
-
...options,
|
|
151
|
-
input: chunk.path
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
transcriptions.push(result.text);
|
|
155
|
-
|
|
156
|
-
// Adjust segment timestamps based on chunk start time
|
|
157
|
-
if (result.segments) {
|
|
158
|
-
for (const segment of result.segments) {
|
|
159
|
-
allSegments.push({
|
|
160
|
-
...segment,
|
|
161
|
-
id: allSegments.length,
|
|
162
|
-
start: segment.start + chunk.startTime,
|
|
163
|
-
end: segment.end + chunk.startTime
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Merge transcriptions
|
|
170
|
-
const mergedText = mergeTranscriptions(transcriptions);
|
|
171
|
-
|
|
172
|
-
return {
|
|
173
|
-
text: mergedText,
|
|
174
|
-
segments: allSegments.length > 0 ? allSegments : undefined,
|
|
175
|
-
model,
|
|
176
|
-
provider: 'openai'
|
|
177
|
-
};
|
|
178
|
-
} finally {
|
|
179
|
-
// Cleanup chunks
|
|
180
|
-
const chunkDir = join(outputDir, '.chunks');
|
|
181
|
-
await cleanupChunks(chunkDir);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private formatResult(data: OpenAITranscriptionResponse, model: string): TranscriptionResult {
|
|
186
|
-
const segments: TranscriptionSegment[] = data.segments?.map((seg, i) => ({
|
|
187
|
-
id: i,
|
|
188
|
-
start: seg.start,
|
|
189
|
-
end: seg.end,
|
|
190
|
-
text: seg.text.trim(),
|
|
191
|
-
confidence: 1 - seg.no_speech_prob
|
|
192
|
-
})) || [];
|
|
193
|
-
|
|
194
|
-
return {
|
|
195
|
-
text: data.text,
|
|
196
|
-
segments: segments.length > 0 ? segments : undefined,
|
|
197
|
-
duration: data.duration,
|
|
198
|
-
language: data.language,
|
|
199
|
-
model,
|
|
200
|
-
provider: 'openai'
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types for transcript
|
|
3
|
-
* Audio/video transcription with automatic chunking
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export type Provider = 'elevenlabs' | 'openai' | 'gemini';
|
|
7
|
-
|
|
8
|
-
export interface TranscriptionOptions {
|
|
9
|
-
input: string;
|
|
10
|
-
output?: string;
|
|
11
|
-
provider: Provider;
|
|
12
|
-
language?: string;
|
|
13
|
-
model?: string;
|
|
14
|
-
diarize?: boolean; // Speaker diarization
|
|
15
|
-
timestamps?: boolean;
|
|
16
|
-
format?: 'text' | 'srt' | 'vtt' | 'json';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface TranscriptionResult {
|
|
20
|
-
text: string;
|
|
21
|
-
segments?: TranscriptionSegment[];
|
|
22
|
-
speakers?: Speaker[];
|
|
23
|
-
duration?: number;
|
|
24
|
-
language?: string;
|
|
25
|
-
model?: string;
|
|
26
|
-
provider: Provider;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface TranscriptionSegment {
|
|
30
|
-
id: number;
|
|
31
|
-
start: number;
|
|
32
|
-
end: number;
|
|
33
|
-
text: string;
|
|
34
|
-
speaker?: string;
|
|
35
|
-
confidence?: number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface Speaker {
|
|
39
|
-
id: string;
|
|
40
|
-
name?: string;
|
|
41
|
-
segments: number[];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface ChunkInfo {
|
|
45
|
-
index: number;
|
|
46
|
-
startTime: number;
|
|
47
|
-
endTime: number;
|
|
48
|
-
path: string;
|
|
49
|
-
size: number;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface TranscriptionProvider {
|
|
53
|
-
name: string;
|
|
54
|
-
maxFileSize: number; // in bytes
|
|
55
|
-
supportedFormats: string[];
|
|
56
|
-
transcribe(options: TranscriptionOptions): Promise<TranscriptionResult>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Provider-specific response types
|
|
60
|
-
export interface ElevenLabsResponse {
|
|
61
|
-
text: string;
|
|
62
|
-
words?: Array<{
|
|
63
|
-
word: string;
|
|
64
|
-
start: number;
|
|
65
|
-
end: number;
|
|
66
|
-
speaker?: string;
|
|
67
|
-
}>;
|
|
68
|
-
speakers?: Array<{
|
|
69
|
-
speaker_id: string;
|
|
70
|
-
name?: string;
|
|
71
|
-
}>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface OpenAITranscriptionResponse {
|
|
75
|
-
text: string;
|
|
76
|
-
task?: string;
|
|
77
|
-
language?: string;
|
|
78
|
-
duration?: number;
|
|
79
|
-
segments?: Array<{
|
|
80
|
-
id: number;
|
|
81
|
-
seek: number;
|
|
82
|
-
start: number;
|
|
83
|
-
end: number;
|
|
84
|
-
text: string;
|
|
85
|
-
tokens: number[];
|
|
86
|
-
temperature: number;
|
|
87
|
-
avg_logprob: number;
|
|
88
|
-
compression_ratio: number;
|
|
89
|
-
no_speech_prob: number;
|
|
90
|
-
}>;
|
|
91
|
-
words?: Array<{
|
|
92
|
-
word: string;
|
|
93
|
-
start: number;
|
|
94
|
-
end: number;
|
|
95
|
-
}>;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export interface GeminiResponse {
|
|
99
|
-
candidates: Array<{
|
|
100
|
-
content: {
|
|
101
|
-
parts: Array<{
|
|
102
|
-
text: string;
|
|
103
|
-
}>;
|
|
104
|
-
};
|
|
105
|
-
}>;
|
|
106
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Google Veo 2 (Vertex AI)
|
|
2
|
-
# Option 1: Use API key
|
|
3
|
-
GOOGLE_API_KEY=your_google_api_key_here
|
|
4
|
-
|
|
5
|
-
# Option 2: Use service account
|
|
6
|
-
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
|
|
7
|
-
GOOGLE_CLOUD_PROJECT=your-project-id
|
|
8
|
-
GOOGLE_CLOUD_LOCATION=us-central1
|
|
9
|
-
|
|
10
|
-
# OpenAI Sora
|
|
11
|
-
OPENAI_API_KEY=your_openai_api_key_here
|
|
12
|
-
|
|
13
|
-
# Runway
|
|
14
|
-
RUNWAY_API_KEY=your_runway_api_key_here
|