vibefast-cli 1.1.3 → 1.2.1
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/CHANGELOG.md +32 -0
- package/README.md +63 -169
- package/dist/__tests__/recipes.test.js +25 -3
- package/dist/__tests__/recipes.test.js.map +1 -1
- package/dist/commands/add.d.ts +1 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +547 -543
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/checklist.d.ts +1 -1
- package/dist/commands/checklist.d.ts.map +1 -1
- package/dist/commands/checklist.js +40 -39
- package/dist/commands/checklist.js.map +1 -1
- package/dist/commands/doctor.d.ts +1 -1
- package/dist/commands/doctor.js +22 -22
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env.d.ts +1 -1
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +58 -53
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/health.d.ts +1 -1
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +101 -93
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +416 -296
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/remove.d.ts +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +77 -64
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +15 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/core/__tests__/detect.test.js +68 -34
- package/dist/core/__tests__/detect.test.js.map +1 -1
- package/dist/core/ast.d.ts +14 -0
- package/dist/core/ast.d.ts.map +1 -0
- package/dist/core/ast.js +239 -0
- package/dist/core/ast.js.map +1 -0
- package/dist/core/codemod.d.ts.map +1 -1
- package/dist/core/codemod.js +62 -44
- package/dist/core/codemod.js.map +1 -1
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +51 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/detect.d.ts +8 -2
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +52 -21
- package/dist/core/detect.js.map +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +9 -8
- package/dist/core/errors.js.map +1 -1
- package/dist/core/exec.d.ts +16 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +48 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/manualSteps.d.ts +7 -0
- package/dist/core/manualSteps.d.ts.map +1 -0
- package/dist/core/manualSteps.js +59 -0
- package/dist/core/manualSteps.js.map +1 -0
- package/dist/core/paths.d.ts +3 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +14 -10
- package/dist/core/paths.js.map +1 -1
- package/dist/core/spinner.d.ts +1 -1
- package/dist/core/spinner.d.ts.map +1 -1
- package/dist/core/spinner.js +38 -8
- package/dist/core/spinner.js.map +1 -1
- package/dist/core/vosk.d.ts.map +1 -1
- package/dist/core/vosk.js +50 -39
- package/dist/core/vosk.js.map +1 -1
- package/docs/manual-testing.md +91 -0
- package/package.json +6 -3
- package/recipes/audio-recorder/apps/native/src/app/audio-recorder/index.tsx +5 -0
- package/recipes/audio-recorder/recipe.json +3 -3
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/index.ts +4 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
- package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +369 -0
- package/recipes/audio-recorder-supabase/packages/backend/supabase/migrations/recordings.sql +70 -0
- package/recipes/audio-recorder-supabase/recipe.json +35 -0
- package/recipes/audio-recorder-supabase@latest.zip +0 -0
- package/recipes/audio-recorder@latest.zip +0 -0
- package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -3
- package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +2 -2
- package/recipes/charts/apps/native/src/features/charts/components/chart-card.tsx +5 -5
- package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -3
- package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +20 -4
- package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +7 -6
- package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +6 -4
- package/recipes/charts/apps/native/src/features/charts/components/radial-bar-chart.tsx +1 -1
- package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +5 -4
- package/recipes/charts/recipe.json +4 -13
- package/recipes/charts@latest.zip +0 -0
- package/recipes/chatbot/apps/native/src/app/chatbot/index.tsx +1 -0
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
- package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
- package/recipes/chatbot/recipe.json +26 -92
- package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +515 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/app/index.tsx +257 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +59 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-input-bar.tsx +485 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +575 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +223 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +161 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +165 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/index.ts +10 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +129 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-error-boundary.tsx +78 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/message-list.tsx +170 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/model-selector.tsx +283 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/report-content-modal.tsx +188 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/suggested-messages.tsx +67 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/models.ts +20 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/constants/report-reasons.ts +9 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +142 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-config.ts +458 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +429 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +89 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-conversation.ts +90 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-image-picker.ts +122 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +161 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +213 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/index.ts +86 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/models.ts +162 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/providers.ts +62 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/models/types.ts +40 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/file-uploader.ts +287 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/services/message-handler-service.ts +189 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/types/index.ts +70 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/utils/chat-telemetry.ts +91 -0
- package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +243 -0
- package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +327 -0
- package/recipes/chatbot-supabase/packages/backend/supabase/functions/chat-stream/index.ts +347 -0
- package/recipes/chatbot-supabase/packages/backend/supabase/migrations/chatbot.sql +104 -0
- package/recipes/chatbot-supabase/recipe.json +79 -0
- package/recipes/chatbot-supabase@latest.zip +0 -0
- package/recipes/chatbot.zip +0 -0
- package/recipes/chatbot@latest.zip +0 -0
- package/recipes/image-analysis/packages/backend/convex/imageAnalysis/index.ts +2 -2
- package/recipes/image-analysis/packages/backend/convex/{imageAnalysisFunctions.ts → imageAnalysis.ts} +5 -5
- package/recipes/image-analysis/recipe.json +15 -55
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading-screen.tsx +214 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/loading.tsx +191 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +160 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +38 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +208 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
- package/recipes/image-analysis-supabase/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
- package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +132 -0
- package/recipes/image-analysis-supabase/packages/backend/supabase/functions/analyze-image/index.ts +312 -0
- package/recipes/image-analysis-supabase/packages/backend/supabase/migrations/image_analysis.sql +42 -0
- package/recipes/image-analysis-supabase/recipe.json +57 -0
- package/recipes/image-analysis-supabase@latest.zip +0 -0
- package/recipes/image-analysis@latest.zip +0 -0
- package/recipes/image-generator/apps/native/src/features/image-generator/app/index.tsx +16 -2
- package/recipes/image-generator/apps/native/src/features/image-generator/components/image-model-selector.tsx +11 -5
- package/recipes/image-generator/apps/native/src/features/image-generator/hooks/use-image-generator.ts +11 -5
- package/recipes/image-generator/packages/backend/convex/imageGeneration/index.ts +2 -2
- package/recipes/image-generator/recipe.json +16 -39
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/app/index.tsx +251 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-model-selector.tsx +216 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/hooks/use-image-generator.ts +103 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/models/models.ts +66 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-gallery-service.ts +96 -0
- package/recipes/image-generator-supabase/apps/native/src/features/image-generator/services/image-save-service.ts +120 -0
- package/recipes/image-generator-supabase/packages/backend/supabase/functions/generate-image/index.ts +291 -0
- package/recipes/image-generator-supabase/packages/backend/supabase/migrations/image_generator.sql +71 -0
- package/recipes/image-generator-supabase/recipe.json +59 -0
- package/recipes/image-generator-supabase@latest.zip +0 -0
- package/recipes/image-generator@latest.zip +0 -0
- package/recipes/ios-widget/recipe.json +15 -24
- package/recipes/ios-widget@latest.zip +0 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/analytics/index.ts +9 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/app/index.tsx +42 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/app/index.tsx +43 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +222 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +133 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +165 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +199 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +154 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +156 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +158 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +139 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +129 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +138 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +190 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +98 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +181 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +110 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +139 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +217 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +58 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/constants.ts +179 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
- package/recipes/onboarding/recipe.json +15 -0
- package/recipes/onboarding@latest.zip +0 -0
- package/recipes/payments/recipe.json +28 -61
- package/recipes/payments-supabase/apps/native/src/features/payments/README.md +200 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/index.ts +8 -0
- package/recipes/payments-supabase/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
- package/recipes/payments-supabase/packages/backend/src/services/payments.ts +201 -0
- package/recipes/payments-supabase/packages/backend/supabase/migrations/payments.sql +35 -0
- package/recipes/payments-supabase/recipe.json +51 -0
- package/recipes/payments-supabase@latest.zip +0 -0
- package/recipes/payments@latest.zip +0 -0
- package/recipes/quiz/apps/native/src/features/quiz/index.tsx +1 -2
- package/recipes/quiz/recipe.json +6 -9
- package/recipes/quiz@latest.zip +0 -0
- package/recipes/tracker-app/apps/native/src/features/tracker-app/app/index.tsx +1 -2
- package/recipes/tracker-app/recipe.json +7 -10
- package/recipes/tracker-app@latest.zip +0 -0
- package/recipes/voice-bot/recipe.json +8 -68
- package/recipes/voice-bot.zip +0 -0
- package/recipes/voice-bot@latest.zip +0 -0
- package/recipes/wake-word/recipe.json +10 -9
- package/recipes/wake-word.zip +0 -0
- package/recipes/wake-word@latest.zip +0 -0
- package/recipes/charts/apps/native/src/app/(root)/(protected)/charts/index.tsx +0 -3
- package/recipes/chatbot/packages/backend/convex/lib/rateLimit.ts +0 -100
- package/recipes/chatbot/packages/backend/convex/lib/telemetry.ts +0 -29
- package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +0 -0
- package/recipes/image-analysis/apps/native/assets/features/image-analyzer/front.jpg +0 -0
- package/recipes/image-analysis/apps/native/assets/features/image-analyzer/side.jpg +0 -0
- package/recipes/image-analysis/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +0 -5
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +0 -50
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +0 -2
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +0 -50
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +0 -50
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +0 -2
- package/recipes/image-analysis/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +0 -3
- package/recipes/image-analysis/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +0 -200
- package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/index.tsx +0 -74
- package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/local.tsx +0 -25
- package/recipes/payments/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +0 -23
- package/recipes/quiz/apps/native/src/app/(root)/(protected)/quiz/index.tsx +0 -47
- package/recipes/tracker-app/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +0 -1
- package/recipes/voice-bot/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +0 -27
- package/recipes/voice-bot/packages/backend/convex/router.ts +0 -81
- /package/recipes/{chatbot/apps/native/src/app/(root)/(protected) → chatbot-supabase/apps/native/src/app}/chatbot/index.tsx +0 -0
- /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/gallery.tsx +0 -0
- /package/recipes/{image-generator/apps/native/src/app/(root)/(protected) → image-generator-supabase/apps/native/src/app}/image-generator/index.tsx +0 -0
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
'use node';
|
|
2
|
-
|
|
3
|
-
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
4
|
-
import { createOpenAI } from '@ai-sdk/openai';
|
|
5
|
-
import { generateObject } from 'ai';
|
|
6
|
-
|
|
7
|
-
import { getAnalysisConfig } from './analysisConfigs';
|
|
8
|
-
import { type AIProvider, getAIConfig } from './config';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Generic analysis result type
|
|
12
|
-
*/
|
|
13
|
-
export type GenericAnalysisResult = {
|
|
14
|
-
overallScore: number;
|
|
15
|
-
overallMessage: string;
|
|
16
|
-
confidence: number;
|
|
17
|
-
traitScores: Record<
|
|
18
|
-
string,
|
|
19
|
-
{
|
|
20
|
-
score: number;
|
|
21
|
-
feedback: string;
|
|
22
|
-
strengths: string[];
|
|
23
|
-
improvements: string[];
|
|
24
|
-
}
|
|
25
|
-
>;
|
|
26
|
-
recommendations: string[];
|
|
27
|
-
analysisType: string;
|
|
28
|
-
processingTime: number;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Truncate an oversized base64 string while preserving a valid encoding.
|
|
33
|
-
*
|
|
34
|
-
* Base64 strings must have a length that is a multiple of 4 and must end with
|
|
35
|
-
* optional padding characters ("="). A naive substring can break the encoding
|
|
36
|
-
* and lead to downstream "unsupported image" errors from the OpenAI API. This
|
|
37
|
-
* helper trims the string **only** when it exceeds the chosen limit and always
|
|
38
|
-
* rounds the length down to the nearest multiple of 4 to keep the data valid.
|
|
39
|
-
*
|
|
40
|
-
* NOTE: The client already compresses/resize images before upload, so the limit
|
|
41
|
-
* here is intentionally generous (4 MB of base64 text ≈ 3 MB binary). This
|
|
42
|
-
* should fit within OpenAI's 30 MB image cap while safeguarding Convex memory.
|
|
43
|
-
*/
|
|
44
|
-
function optimizeImageForMemory(base64: string): string {
|
|
45
|
-
const MAX_CHARS = 4 * 1024 * 1024; // 4 MB worth of base64 characters
|
|
46
|
-
|
|
47
|
-
if (base64.length <= MAX_CHARS) {
|
|
48
|
-
return base64;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
console.log(
|
|
52
|
-
`[Memory Optimization] Truncating image from ${base64.length} to ${MAX_CHARS} chars (safe multiple-of-4)`,
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// Round down to nearest multiple of 4 to preserve base64 integrity
|
|
56
|
-
const safeLength = MAX_CHARS - (MAX_CHARS % 4);
|
|
57
|
-
const truncated = base64.substring(0, safeLength);
|
|
58
|
-
|
|
59
|
-
// Ensure proper padding – if the truncated string ends with partial padding
|
|
60
|
-
// remove it and re-append correct padding.
|
|
61
|
-
const withoutPartialPad = truncated.replace(/=+$/, '');
|
|
62
|
-
const padNeeded = (4 - (withoutPartialPad.length % 4)) % 4;
|
|
63
|
-
return withoutPartialPad + '='.repeat(padNeeded);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Generate structured analysis using AI SDK (generic for any analysis type)
|
|
68
|
-
*/
|
|
69
|
-
export async function generateImageAnalysis(
|
|
70
|
-
imagesAsBase64: string[],
|
|
71
|
-
preferences: {
|
|
72
|
-
goal: string;
|
|
73
|
-
feedbackStyle: string;
|
|
74
|
-
},
|
|
75
|
-
analysisConfigId = 'face_analysis',
|
|
76
|
-
): Promise<GenericAnalysisResult> {
|
|
77
|
-
const config = getAIConfig();
|
|
78
|
-
const analysisConfig = getAnalysisConfig(analysisConfigId);
|
|
79
|
-
const startTime = Date.now();
|
|
80
|
-
|
|
81
|
-
// Memory optimization: Limit to max 3 images and optimize them
|
|
82
|
-
const maxImages = 3;
|
|
83
|
-
const optimizedImages = imagesAsBase64
|
|
84
|
-
.slice(0, maxImages)
|
|
85
|
-
.map(optimizeImageForMemory);
|
|
86
|
-
|
|
87
|
-
console.log(
|
|
88
|
-
`[Memory Optimization] Processing ${optimizedImages.length} images (max ${maxImages})`,
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// Create the appropriate AI provider
|
|
92
|
-
const provider = createAIProvider(config.provider);
|
|
93
|
-
const model = provider(config.model);
|
|
94
|
-
|
|
95
|
-
// Build a simpler, shorter prompt to reduce memory usage
|
|
96
|
-
const prompt = buildOptimizedPrompt(
|
|
97
|
-
analysisConfig,
|
|
98
|
-
preferences,
|
|
99
|
-
optimizedImages.length,
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
// Convert base64 images to the format expected by AI SDK
|
|
103
|
-
const imageMessages = optimizedImages.map((base64) => ({
|
|
104
|
-
type: 'image' as const,
|
|
105
|
-
image: `data:image/jpeg;base64,${base64}`,
|
|
106
|
-
}));
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
// Generate structured output using AI SDK with reduced complexity
|
|
110
|
-
const { object } = await generateObject({
|
|
111
|
-
model,
|
|
112
|
-
schema: analysisConfig.schema,
|
|
113
|
-
messages: [
|
|
114
|
-
{
|
|
115
|
-
role: 'user',
|
|
116
|
-
content: [{ type: 'text', text: prompt }, ...imageMessages],
|
|
117
|
-
},
|
|
118
|
-
],
|
|
119
|
-
temperature: config.temperature,
|
|
120
|
-
maxTokens: Math.min(config.maxTokens, 2000), // Reduce max tokens to save memory
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
// Add processing metadata
|
|
124
|
-
const processingTime = Date.now() - startTime;
|
|
125
|
-
return {
|
|
126
|
-
...object,
|
|
127
|
-
processingTime,
|
|
128
|
-
analysisType: `${analysisConfigId}_${preferences.goal}_${preferences.feedbackStyle}`,
|
|
129
|
-
} as GenericAnalysisResult;
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.error('Error generating analysis:', error);
|
|
132
|
-
throw new Error(
|
|
133
|
-
`Failed to generate analysis: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Build optimized, shorter prompt to reduce memory usage
|
|
140
|
-
*/
|
|
141
|
-
function buildOptimizedPrompt(
|
|
142
|
-
analysisConfig: any,
|
|
143
|
-
preferences: { goal: string; feedbackStyle: string },
|
|
144
|
-
imageCount: number,
|
|
145
|
-
): string {
|
|
146
|
-
const traitNames = Object.keys(analysisConfig.traits).slice(0, 6); // Limit traits to reduce complexity
|
|
147
|
-
|
|
148
|
-
return `Analyze the ${imageCount} image(s) for ${analysisConfig.name.toLowerCase()}.
|
|
149
|
-
|
|
150
|
-
Goal: ${preferences.goal}
|
|
151
|
-
Style: ${preferences.feedbackStyle}
|
|
152
|
-
|
|
153
|
-
Provide scores (0-100) and feedback for: ${traitNames.join(', ')}.
|
|
154
|
-
|
|
155
|
-
Include:
|
|
156
|
-
- Overall score and message
|
|
157
|
-
- Individual trait scores with feedback
|
|
158
|
-
- 2-3 recommendations
|
|
159
|
-
- Confidence level (0-1)
|
|
160
|
-
|
|
161
|
-
Be concise and ${preferences.feedbackStyle}.`;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Legacy function for backward compatibility (face analysis)
|
|
166
|
-
* @deprecated Use generateImageAnalysis instead
|
|
167
|
-
*/
|
|
168
|
-
export async function generateFacialAnalysis(
|
|
169
|
-
imagesAsBase64: string[],
|
|
170
|
-
preferences: {
|
|
171
|
-
goal: string;
|
|
172
|
-
feedbackStyle: string;
|
|
173
|
-
},
|
|
174
|
-
): Promise<GenericAnalysisResult> {
|
|
175
|
-
return generateImageAnalysis(imagesAsBase64, preferences, 'face_analysis');
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Create AI provider based on configuration
|
|
180
|
-
*/
|
|
181
|
-
function createAIProvider(provider: AIProvider) {
|
|
182
|
-
switch (provider) {
|
|
183
|
-
case 'openai': {
|
|
184
|
-
const apiKey = process.env.OPENAI_API_KEY;
|
|
185
|
-
if (!apiKey) {
|
|
186
|
-
throw new Error('OPENAI_API_KEY environment variable is required');
|
|
187
|
-
}
|
|
188
|
-
return createOpenAI({ apiKey });
|
|
189
|
-
}
|
|
190
|
-
case 'gemini': {
|
|
191
|
-
const apiKey = process.env.GEMINI_API_KEY;
|
|
192
|
-
if (!apiKey) {
|
|
193
|
-
throw new Error('GEMINI_API_KEY environment variable is required');
|
|
194
|
-
}
|
|
195
|
-
return createGoogleGenerativeAI({ apiKey });
|
|
196
|
-
}
|
|
197
|
-
default:
|
|
198
|
-
throw new Error(`Unsupported AI provider: ${provider}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { router, Stack } from 'expo-router';
|
|
2
|
-
import React, { useMemo } from 'react';
|
|
3
|
-
import { ScrollView, View } from 'react-native';
|
|
4
|
-
|
|
5
|
-
import { FeatureButton, FocusAwareStatusBar } from '@/components/ui';
|
|
6
|
-
import { translate } from '@/lib';
|
|
7
|
-
import { useThemeConfig } from '@/lib/use-theme-config';
|
|
8
|
-
|
|
9
|
-
export default function PaywallSelection() {
|
|
10
|
-
const theme = useThemeConfig();
|
|
11
|
-
const optionsTitle = translate('paywall.options_title');
|
|
12
|
-
const screenOptions = useMemo(
|
|
13
|
-
() => ({
|
|
14
|
-
title: optionsTitle,
|
|
15
|
-
headerShown: true,
|
|
16
|
-
headerBackButtonDisplayMode: 'generic' as const,
|
|
17
|
-
}),
|
|
18
|
-
[optionsTitle],
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
const paywallOptions = [
|
|
22
|
-
{
|
|
23
|
-
id: 'remote',
|
|
24
|
-
title: translate('paywall.remote_title'),
|
|
25
|
-
icon: '💳',
|
|
26
|
-
color: '#FBBF24', // Amber
|
|
27
|
-
description: translate('paywall.remote_description'),
|
|
28
|
-
route: '/paywall/remote',
|
|
29
|
-
testID: 'remote-paywall-option',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
id: 'local',
|
|
33
|
-
title: translate('paywall.local_title'),
|
|
34
|
-
icon: '🛒',
|
|
35
|
-
color: '#10B981', // Emerald
|
|
36
|
-
description: translate('paywall.local_description'),
|
|
37
|
-
route: '/paywall/local',
|
|
38
|
-
testID: 'local-paywall-option',
|
|
39
|
-
},
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const handleOptionPress = (route: string) => {
|
|
43
|
-
router.push(route as any);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<>
|
|
48
|
-
<FocusAwareStatusBar />
|
|
49
|
-
<Stack.Screen options={screenOptions} />
|
|
50
|
-
<ScrollView
|
|
51
|
-
style={{ backgroundColor: theme.colors.background }}
|
|
52
|
-
className="flex-1"
|
|
53
|
-
showsVerticalScrollIndicator={false}
|
|
54
|
-
>
|
|
55
|
-
<View className="px-6 py-8">
|
|
56
|
-
<View className="-mx-2 flex-row flex-wrap">
|
|
57
|
-
{paywallOptions.map((option) => (
|
|
58
|
-
<View key={option.id} className="w-1/2 px-2 pb-4">
|
|
59
|
-
<FeatureButton
|
|
60
|
-
title={option.title}
|
|
61
|
-
icon={option.icon}
|
|
62
|
-
color={option.color}
|
|
63
|
-
description={option.description}
|
|
64
|
-
testID={option.testID}
|
|
65
|
-
onPress={() => handleOptionPress(option.route)}
|
|
66
|
-
/>
|
|
67
|
-
</View>
|
|
68
|
-
))}
|
|
69
|
-
</View>
|
|
70
|
-
</View>
|
|
71
|
-
</ScrollView>
|
|
72
|
-
</>
|
|
73
|
-
);
|
|
74
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Stack } from 'expo-router';
|
|
2
|
-
import React, { useMemo } from 'react';
|
|
3
|
-
|
|
4
|
-
import LocalPaywall from '@/features/payments/app/local-paywall';
|
|
5
|
-
import { RevenueCatAdapter } from '@/features/payments/services/revenuecat-adapter';
|
|
6
|
-
import { translate } from '@/lib';
|
|
7
|
-
|
|
8
|
-
export default function LocalPaywallScreen() {
|
|
9
|
-
const paymentService = useMemo(() => new RevenueCatAdapter(), []);
|
|
10
|
-
const localTitle = translate('paywall.local_title');
|
|
11
|
-
const screenOptions = useMemo(
|
|
12
|
-
() => ({
|
|
13
|
-
title: localTitle,
|
|
14
|
-
headerShown: false,
|
|
15
|
-
}),
|
|
16
|
-
[localTitle],
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<>
|
|
21
|
-
<Stack.Screen options={screenOptions} />
|
|
22
|
-
<LocalPaywall paymentService={paymentService} />
|
|
23
|
-
</>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Stack } from 'expo-router';
|
|
2
|
-
import React, { useMemo } from 'react';
|
|
3
|
-
|
|
4
|
-
import RemotePaywall from '@/features/payments/app/remote-paywall';
|
|
5
|
-
import { translate } from '@/lib';
|
|
6
|
-
|
|
7
|
-
export default function RemotePaywallScreen() {
|
|
8
|
-
const remoteTitle = translate('paywall.remote_title');
|
|
9
|
-
const screenOptions = useMemo(
|
|
10
|
-
() => ({
|
|
11
|
-
title: remoteTitle,
|
|
12
|
-
headerShown: true,
|
|
13
|
-
}),
|
|
14
|
-
[remoteTitle],
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<>
|
|
19
|
-
<Stack.Screen options={screenOptions} />
|
|
20
|
-
<RemotePaywall />
|
|
21
|
-
</>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import Quiz from '@/features/quiz';
|
|
2
|
-
import { QuestionMode } from '@/features/quiz/config';
|
|
3
|
-
|
|
4
|
-
const questions = [
|
|
5
|
-
{
|
|
6
|
-
text: 'What is your favorite color?',
|
|
7
|
-
mode: QuestionMode.AutoAdvance,
|
|
8
|
-
options: [
|
|
9
|
-
{ id: 'red', text: 'Red', note: 'Red is the color of passion.' },
|
|
10
|
-
{ id: 'blue', text: 'Blue', note: 'Blue is the color of calm.' },
|
|
11
|
-
{ id: 'green', text: 'Green', note: 'Green is the color of nature.' },
|
|
12
|
-
],
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
text: 'What is your favorite animal?',
|
|
16
|
-
mode: QuestionMode.ManualAdvance,
|
|
17
|
-
options: [
|
|
18
|
-
{ id: 'dog', text: 'Dog', note: 'Dogs are loyal.' },
|
|
19
|
-
{ id: 'cat', text: 'Cat', note: 'Cats are independent.' },
|
|
20
|
-
{ id: 'bird', text: 'Bird', note: 'Birds can fly.' },
|
|
21
|
-
],
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
text: 'What is your favorite animal?',
|
|
25
|
-
mode: QuestionMode.ManualAdvance,
|
|
26
|
-
options: [
|
|
27
|
-
{ id: 'dog', text: 'Dog', note: 'Dogs are loyal.' },
|
|
28
|
-
{ id: 'cat', text: 'Cat', note: 'Cats are independent.' },
|
|
29
|
-
{ id: 'bird', text: 'Bird', note: 'Birds can fly.' },
|
|
30
|
-
],
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
text: 'What is your favorite animal?',
|
|
34
|
-
mode: QuestionMode.ManualAdvance,
|
|
35
|
-
options: [
|
|
36
|
-
{ id: 'dog', text: 'Dog', note: 'Dogs are loyal.' },
|
|
37
|
-
{ id: 'cat', text: 'Cat', note: 'Cats are independent.' },
|
|
38
|
-
{ id: 'bird', text: 'Bird', note: 'Birds can fly.' },
|
|
39
|
-
],
|
|
40
|
-
},
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
const QuizScreen = () => {
|
|
44
|
-
return <Quiz questions={questions} />;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export default QuizScreen;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { default } from '@/features/tracker-app/app';
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Env } from '@env';
|
|
2
|
-
import { Stack } from 'expo-router';
|
|
3
|
-
import React, { useMemo } from 'react';
|
|
4
|
-
|
|
5
|
-
import { VoiceBotScreen } from '@/features/voice-bot';
|
|
6
|
-
|
|
7
|
-
export default function VoiceBotRoute() {
|
|
8
|
-
const agentId = Env.ELEVENLABS_AGENT_ID;
|
|
9
|
-
const screenOptions = useMemo(
|
|
10
|
-
() => ({
|
|
11
|
-
title: 'Voice Assistant',
|
|
12
|
-
headerShown: true,
|
|
13
|
-
}),
|
|
14
|
-
[],
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<>
|
|
19
|
-
<Stack.Screen options={screenOptions} />
|
|
20
|
-
<VoiceBotScreen
|
|
21
|
-
config={{ agentId }}
|
|
22
|
-
title="Voice Assistant"
|
|
23
|
-
subtitle="Start a conversation with your AI assistant"
|
|
24
|
-
/>
|
|
25
|
-
</>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { httpRouter } from 'convex/server';
|
|
2
|
-
|
|
3
|
-
import { httpAction } from './_generated/server';
|
|
4
|
-
|
|
5
|
-
const http = httpRouter();
|
|
6
|
-
|
|
7
|
-
const ELEVENLABS_TOKEN_ENDPOINT =
|
|
8
|
-
'https://api.elevenlabs.io/v1/convai/conversation/token';
|
|
9
|
-
|
|
10
|
-
const fetchElevenLabsConversationToken = httpAction(
|
|
11
|
-
async (_ctx, request): Promise<Response> => {
|
|
12
|
-
const apiKey = process.env.ELEVENLABS_API_KEY;
|
|
13
|
-
if (!apiKey) {
|
|
14
|
-
return new Response(
|
|
15
|
-
JSON.stringify({
|
|
16
|
-
error: 'ELEVENLABS_API_KEY is not configured on the backend',
|
|
17
|
-
}),
|
|
18
|
-
{
|
|
19
|
-
status: 500,
|
|
20
|
-
headers: { 'content-type': 'application/json' },
|
|
21
|
-
},
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const url = new URL(request.url);
|
|
26
|
-
const agentId = url.searchParams.get('agent_id');
|
|
27
|
-
if (!agentId) {
|
|
28
|
-
return new Response(
|
|
29
|
-
JSON.stringify({ error: 'agent_id query parameter is required' }),
|
|
30
|
-
{
|
|
31
|
-
status: 400,
|
|
32
|
-
headers: { 'content-type': 'application/json' },
|
|
33
|
-
},
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const upstreamUrl = new URL(ELEVENLABS_TOKEN_ENDPOINT);
|
|
38
|
-
url.searchParams.forEach((value, key) => {
|
|
39
|
-
upstreamUrl.searchParams.set(key, value);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const upstreamResponse = await fetch(upstreamUrl, {
|
|
44
|
-
method: 'GET',
|
|
45
|
-
headers: {
|
|
46
|
-
'xi-api-key': apiKey,
|
|
47
|
-
accept: 'application/json',
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const payload = await upstreamResponse.text();
|
|
52
|
-
return new Response(payload, {
|
|
53
|
-
status: upstreamResponse.status,
|
|
54
|
-
headers: {
|
|
55
|
-
'content-type':
|
|
56
|
-
upstreamResponse.headers.get('content-type') || 'application/json',
|
|
57
|
-
},
|
|
58
|
-
});
|
|
59
|
-
} catch (error) {
|
|
60
|
-
console.error(
|
|
61
|
-
'[voice.token] Failed to fetch ElevenLabs conversation token',
|
|
62
|
-
error,
|
|
63
|
-
);
|
|
64
|
-
return new Response(
|
|
65
|
-
JSON.stringify({ error: 'Failed to fetch ElevenLabs token' }),
|
|
66
|
-
{
|
|
67
|
-
status: 502,
|
|
68
|
-
headers: { 'content-type': 'application/json' },
|
|
69
|
-
},
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
http.route({
|
|
76
|
-
path: '/voice/conversation-token',
|
|
77
|
-
method: 'GET',
|
|
78
|
-
handler: fetchElevenLabsConversationToken,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
export default http;
|
|
File without changes
|
|
File without changes
|