vibefast-cli 0.2.3 → 0.3.0
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/.wrangler/state/v3/r2/miniflare-R2BucketObject/d1cc388a1a0ef44dd5669fd1a165d168b61362136c8b5fa50aefd96c72688e54.sqlite +0 -0
- package/.wrangler/state/v3/r2/miniflare-R2BucketObject/d1cc388a1a0ef44dd5669fd1a165d168b61362136c8b5fa50aefd96c72688e54.sqlite-shm +0 -0
- package/.wrangler/state/v3/r2/miniflare-R2BucketObject/d1cc388a1a0ef44dd5669fd1a165d168b61362136c8b5fa50aefd96c72688e54.sqlite-wal +0 -0
- package/.wrangler/state/v3/r2/vibefast-recipes/blobs/177b5d7279681c1bec396cafe63779a2d89eaf538109e55733147727276e2b9f0000019a81f04ba2 +0 -0
- package/.wrangler/state/v3/r2/vibefast-recipes/blobs/4fe398bba6e2d5f13b569bc1be4244e696d86caa04c323db2d9fb0b9381c508f0000019a81f0503f +0 -0
- package/.wrangler/state/v3/r2/vibefast-recipes/blobs/f68f19a655380ac7fb575eb49c0623cde74046261ed89c498ba5107b8aacde9d0000019a81f05484 +0 -0
- package/2/.claude/agents/architect.md +74 -0
- package/2/.claude/agents/convex-reviewer.md +267 -0
- package/2/.claude/agents/debug-detective.md +62 -0
- package/2/.claude/agents/learner.md +64 -0
- package/2/.claude/agents/perf-optimizer.md +71 -0
- package/2/.claude/agents/security-researcher.md +42 -0
- package/2/.claude/agents/tech-researcher.md +46 -0
- package/2/.claude/agents/ux-designer.md +45 -0
- package/2/.claude/commands/create-app-design.md +279 -0
- package/2/.claude/commands/create-prd-interactive.md +113 -0
- package/2/.claude/commands/create-prd.md +111 -0
- package/2/.claude/commands/create-tech-stack.md +345 -0
- package/2/.claude/commands/update-app-design.md +298 -0
- package/2/.claude/commands/update-project-structure.md +14 -0
- package/2/.claude/commands/update-tech-stack.md +325 -0
- package/2/.claude/docs/CONVEX_FEATURES_PLAN.md +249 -0
- package/2/.claude/docs/app-design-document.md +0 -0
- package/2/.claude/docs/project-status.md +25 -0
- package/2/.claude/docs/project-structure.md +7 -0
- package/2/.claude/docs/tech-stack.md +157 -0
- package/2/.claude/scripts/tree.sh +70 -0
- package/2/.claude/settings.json +30 -0
- package/2/.cursor/commands/code-review-high.md +190 -0
- package/2/.cursorignore +3 -0
- package/2/.github/ISSUE_TEMPLATE.md +13 -0
- package/2/.github/PULL_REQUEST_TEMPLATE.md +23 -0
- package/2/.github/actions/eas-build/action.yml +85 -0
- package/2/.github/actions/setup-jdk-generate-apk/action.yml +48 -0
- package/2/.github/actions/setup-node-pnpm-install/action.yml +29 -0
- package/2/.github/scripts/expo-doctor.sh +26 -0
- package/2/.github/workflows/compress-images.yml +48 -0
- package/2/.github/workflows/e2e-android-eas-build.yml +111 -0
- package/2/.github/workflows/e2e-android-maestro.yml +52 -0
- package/2/.github/workflows/e2e-android.yml +119 -0
- package/2/.github/workflows/eas-build-prod.yml +43 -0
- package/2/.github/workflows/eas-build-qa.yml +47 -0
- package/2/.github/workflows/expo-doctor.yml +61 -0
- package/2/.github/workflows/lint-ts.yml +49 -0
- package/2/.github/workflows/new-app-version.yml +65 -0
- package/2/.github/workflows/new-github-release.yml +34 -0
- package/2/.github/workflows/stale.yml +24 -0
- package/2/.github/workflows/test.yml +50 -0
- package/2/.github/workflows/type-check.yml +54 -0
- package/2/.husky/commit-msg +1 -0
- package/2/.husky/common.sh +8 -0
- package/2/.husky/post-merge +18 -0
- package/2/.husky/pre-commit +24 -0
- package/2/.prettierignore +14 -0
- package/2/.prettierrc.json +10 -0
- package/2/.vibefast/README.md +59 -0
- package/2/.vibefast/config.json +4 -0
- package/2/.vibefast/journal.json +234 -0
- package/2/.vibefast/starter.json +5 -0
- package/2/AGENTS.md +48 -0
- package/2/LICENSE +21 -0
- package/2/README.md +127 -0
- package/2/apps/native/__mocks__/bottom-sheet.js +6 -0
- package/2/apps/native/__mocks__/expo-router.js +16 -0
- package/2/apps/native/__mocks__/react-native-gesture-handler.ts +17 -0
- package/2/apps/native/app-env.d.ts +2 -0
- package/2/apps/native/app.config.ts +167 -0
- package/2/apps/native/assets/adaptive-icon.png +0 -0
- package/2/apps/native/assets/favicon.png +0 -0
- package/2/apps/native/assets/features/image-analyzer/front.jpg +0 -0
- package/2/apps/native/assets/features/image-analyzer/side.jpg +0 -0
- package/2/apps/native/assets/features/image-analyzer/threeQuarter.jpg +0 -0
- package/2/apps/native/assets/fonts/Inter.ttf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Bold.otf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Medium.otf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Regular.otf +0 -0
- package/2/apps/native/assets/fonts/SF-Pro-Display-Semibold.otf +0 -0
- package/2/apps/native/assets/fonts/SpaceMono-Regular.ttf +0 -0
- package/2/apps/native/assets/icon.png +0 -0
- package/2/apps/native/assets/images/cover-image.png +0 -0
- package/2/apps/native/assets/lottie-animations/onboarding-1.json +6504 -0
- package/2/apps/native/assets/lottie-animations/onboarding-2.json +1993 -0
- package/2/apps/native/assets/lottie-animations/onboarding-3.json +50159 -0
- package/2/apps/native/assets/lottie-animations/onboarding-4.json +735 -0
- package/2/apps/native/assets/lottie-animations/onboarding-6.json +2167 -0
- package/2/apps/native/assets/splash-icon.png +0 -0
- package/2/apps/native/babel.config.js +39 -0
- package/2/apps/native/eas.json +75 -0
- package/2/apps/native/env.js +196 -0
- package/2/apps/native/global.css +51 -0
- package/2/apps/native/index.ts +5 -0
- package/2/apps/native/jest-setup.ts +7 -0
- package/2/apps/native/jest.config.js +72 -0
- package/2/apps/native/metro.config.js +85 -0
- package/2/apps/native/nativewind-env.d.ts +1 -0
- package/2/apps/native/package.json +232 -0
- package/2/apps/native/scripts/DRY_RUN_REPORT.md +0 -0
- package/2/apps/native/scripts/QUICK_START.md +76 -0
- package/2/apps/native/scripts/README.md +187 -0
- package/2/apps/native/scripts/convex-setup.js +48 -0
- package/2/apps/native/scripts/download-vosk-model.mjs +121 -0
- package/2/apps/native/scripts/genrate-apk-and-install +39 -0
- package/2/apps/native/scripts/i18next-syntax-validation.js +23 -0
- package/2/apps/native/scripts/starter-setup.mjs +246 -0
- package/2/apps/native/src/api-client/auth.ts +68 -0
- package/2/apps/native/src/api-client/chatbot.ts +83 -0
- package/2/apps/native/src/api-client/client.ts +4 -0
- package/2/apps/native/src/api-client/image-analyzer.ts +62 -0
- package/2/apps/native/src/api-client/image-generator.ts +34 -0
- package/2/apps/native/src/api-client/index.ts +27 -0
- package/2/apps/native/src/api-client/payments.ts +44 -0
- package/2/apps/native/src/api-client/reporting.ts +29 -0
- package/2/apps/native/src/api-client/shared.ts +43 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/_layout.tsx +166 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/index.tsx +174 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/profile.tsx +320 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/settings.tsx +344 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/_layout.tsx +198 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/accordion.tsx +60 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/advanced.tsx +24 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/avatar.tsx +154 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/badge-chips-toggle.tsx +81 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/buttons.tsx +24 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/charts.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/date-picker.tsx +120 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/file-picker.tsx +133 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/gallery-video.tsx +119 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/index.tsx +69 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/inputs-stepper.tsx +78 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/picker-dropdown.tsx +56 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/popover-bottomsheet.tsx +229 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/progress.tsx +38 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/searchbar.tsx +70 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/sliders.tsx +93 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/spinner.tsx +80 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/switch.tsx +47 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/table.tsx +352 -0
- package/2/apps/native/src/app/(root)/(protected)/(tabs)/style/tabs-timeline.tsx +122 -0
- package/2/apps/native/src/app/(root)/(protected)/_layout.tsx +143 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/_layout.tsx +5 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/analysis-options.tsx +50 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/camera.tsx +2 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/index.tsx +50 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/loading.tsx +50 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/results.tsx +2 -0
- package/2/apps/native/src/app/(root)/(protected)/analysis/[type]/trait-details.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/audio-recorder/index.tsx +5 -0
- package/2/apps/native/src/app/(root)/(protected)/charts/index.tsx +6 -0
- package/2/apps/native/src/app/(root)/(protected)/chatbot/index.tsx +2 -0
- package/2/apps/native/src/app/(root)/(protected)/image-generator/gallery.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/image-generator/index.tsx +3 -0
- package/2/apps/native/src/app/(root)/(protected)/paywall/index.tsx +74 -0
- package/2/apps/native/src/app/(root)/(protected)/paywall/local.tsx +25 -0
- package/2/apps/native/src/app/(root)/(protected)/paywall/remote.tsx +23 -0
- package/2/apps/native/src/app/(root)/(protected)/quick-actions-demo/index.tsx +32 -0
- package/2/apps/native/src/app/(root)/(protected)/quiz/index.tsx +47 -0
- package/2/apps/native/src/app/(root)/(protected)/test-wake-word.tsx +214 -0
- package/2/apps/native/src/app/(root)/(protected)/tracker-app/index.tsx +1 -0
- package/2/apps/native/src/app/(root)/(protected)/voice-bot/index.tsx +27 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/_layout.tsx +44 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/forgot-password.tsx +185 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/login.tsx +219 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/otp-verification.tsx +369 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/reset-password.tsx +247 -0
- package/2/apps/native/src/app/(root)/(public)/(auth)/signup.tsx +207 -0
- package/2/apps/native/src/app/(root)/(public)/_layout.tsx +60 -0
- package/2/apps/native/src/app/(root)/(public)/onboarding/demo-one.tsx +5 -0
- package/2/apps/native/src/app/(root)/(public)/onboarding/demo-two.tsx +52 -0
- package/2/apps/native/src/app/(root)/(public)/onboarding/index.tsx +82 -0
- package/2/apps/native/src/app/(root)/_layout.tsx +30 -0
- package/2/apps/native/src/app/+html.tsx +46 -0
- package/2/apps/native/src/app/[...messing].tsx +24 -0
- package/2/apps/native/src/app/_layout.tsx +56 -0
- package/2/apps/native/src/app/tsconfig.json +3 -0
- package/2/apps/native/src/components/advanced-ui/buttons/demo.tsx +19 -0
- package/2/apps/native/src/components/advanced-ui/buttons/glowing-button.tsx +366 -0
- package/2/apps/native/src/components/advanced-ui/chip/animated-chip.tsx +118 -0
- package/2/apps/native/src/components/advanced-ui/chip/chip.tsx +49 -0
- package/2/apps/native/src/components/advanced-ui/chip/demo.tsx +191 -0
- package/2/apps/native/src/components/advanced-ui/chip/types.ts +21 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/animated-progress-bar.tsx +182 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/dropdown-picker-page.tsx +124 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/progress-circle-page.tsx +111 -0
- package/2/apps/native/src/components/advanced-ui/progress-bars/progress-circle.tsx +223 -0
- package/2/apps/native/src/components/advanced-ui/sliders/swipe-slider-page.tsx +203 -0
- package/2/apps/native/src/components/advanced-ui/sliders/swipe-slider.tsx +266 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/button/stepper-button.tsx +96 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/button/types.ts +16 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/content/stepper-content.tsx +19 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/content/types.ts +6 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/value/stepper-value.tsx +43 -0
- package/2/apps/native/src/components/advanced-ui/stepper/children/value/types.ts +25 -0
- package/2/apps/native/src/components/advanced-ui/stepper/context/stepper-context.ts +19 -0
- package/2/apps/native/src/components/advanced-ui/stepper/context/types.ts +9 -0
- package/2/apps/native/src/components/advanced-ui/stepper/demo.tsx +346 -0
- package/2/apps/native/src/components/advanced-ui/stepper/index.ts +4 -0
- package/2/apps/native/src/components/advanced-ui/stepper/stepper.tsx +96 -0
- package/2/apps/native/src/components/advanced-ui/stepper/types.ts +13 -0
- package/2/apps/native/src/components/advanced-ui/switch/animated-switch.tsx +312 -0
- package/2/apps/native/src/components/advanced-ui/switch/demo.tsx +851 -0
- package/2/apps/native/src/components/advanced-ui/switch/types.ts +32 -0
- package/2/apps/native/src/components/advanced-ui/timeline/demo.tsx +444 -0
- package/2/apps/native/src/components/advanced-ui/timeline/timeline-view.tsx +355 -0
- package/2/apps/native/src/components/advanced-ui/timeline/types.ts +31 -0
- package/2/apps/native/src/components/analytics/navigation-tracker.tsx +10 -0
- package/2/apps/native/src/components/demo/advanced-ui-components.tsx +46 -0
- package/2/apps/native/src/components/demo/buttons-demo.tsx +56 -0
- package/2/apps/native/src/components/demo/colors-demo.tsx +52 -0
- package/2/apps/native/src/components/demo/dropdown-picker-demo.tsx +274 -0
- package/2/apps/native/src/components/demo/inputs-demo.tsx +99 -0
- package/2/apps/native/src/components/demo/notification-demo.tsx +434 -0
- package/2/apps/native/src/components/demo/title-demo.tsx +16 -0
- package/2/apps/native/src/components/demo/toast-demo.tsx +81 -0
- package/2/apps/native/src/components/demo/typography-demo.tsx +28 -0
- package/2/apps/native/src/components/performance/render-performance-monitor.tsx +36 -0
- package/2/apps/native/src/components/ui/accordion.tsx +138 -0
- package/2/apps/native/src/components/ui/avatar.tsx +66 -0
- package/2/apps/native/src/components/ui/badge.tsx +68 -0
- package/2/apps/native/src/components/ui/bottom-sheet.tsx +61 -0
- package/2/apps/native/src/components/ui/colors.js +290 -0
- package/2/apps/native/src/components/ui/core/button.tsx +317 -0
- package/2/apps/native/src/components/ui/core/card.tsx +40 -0
- package/2/apps/native/src/components/ui/core/checkbox.tsx +264 -0
- package/2/apps/native/src/components/ui/core/feature-button.tsx +162 -0
- package/2/apps/native/src/components/ui/core/focus-aware-status-bar.tsx +21 -0
- package/2/apps/native/src/components/ui/core/image.tsx +30 -0
- package/2/apps/native/src/components/ui/core/inputs/floating-text-input.tsx +369 -0
- package/2/apps/native/src/components/ui/core/inputs/input-otp.tsx +304 -0
- package/2/apps/native/src/components/ui/core/inputs/input.tsx +373 -0
- package/2/apps/native/src/components/ui/core/list.tsx +60 -0
- package/2/apps/native/src/components/ui/core/navigation/animated-header.tsx +87 -0
- package/2/apps/native/src/components/ui/core/navigation/screen-footer.tsx +67 -0
- package/2/apps/native/src/components/ui/core/overlays/dropdown.tsx +290 -0
- package/2/apps/native/src/components/ui/core/overlays/full-screen-loading.tsx +15 -0
- package/2/apps/native/src/components/ui/core/overlays/modal-keyboard-aware-scroll-view.tsx +46 -0
- package/2/apps/native/src/components/ui/core/overlays/modal.tsx +247 -0
- package/2/apps/native/src/components/ui/core/pagination-dots.tsx +231 -0
- package/2/apps/native/src/components/ui/core/pressable.tsx +48 -0
- package/2/apps/native/src/components/ui/core/progress-bar.tsx +47 -0
- package/2/apps/native/src/components/ui/core/progress.tsx +149 -0
- package/2/apps/native/src/components/ui/core/select.tsx +261 -0
- package/2/apps/native/src/components/ui/core/spinner.tsx +387 -0
- package/2/apps/native/src/components/ui/core/text.tsx +45 -0
- package/2/apps/native/src/components/ui/core/toast.tsx +190 -0
- package/2/apps/native/src/components/ui/custom-switch.tsx +90 -0
- package/2/apps/native/src/components/ui/date-time-picker.tsx +268 -0
- package/2/apps/native/src/components/ui/debug.ts +2 -0
- package/2/apps/native/src/components/ui/extras/debug-credit-tester.tsx +107 -0
- package/2/apps/native/src/components/ui/extras/debug-mmkv-state.tsx +53 -0
- package/2/apps/native/src/components/ui/extras/handle-error.ts +191 -0
- package/2/apps/native/src/components/ui/extras/hello-wave.tsx +70 -0
- package/2/apps/native/src/components/ui/extras/icon.tsx +36 -0
- package/2/apps/native/src/components/ui/extras/network-connectivity-wrapper.tsx +36 -0
- package/2/apps/native/src/components/ui/extras/offline-indicator.tsx +55 -0
- package/2/apps/native/src/components/ui/extras/social-login-buttons.tsx +296 -0
- package/2/apps/native/src/components/ui/file-picker.tsx +177 -0
- package/2/apps/native/src/components/ui/gallery.tsx +79 -0
- package/2/apps/native/src/components/ui/icons/apple.tsx +19 -0
- package/2/apps/native/src/components/ui/icons/arrow-right.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/camera.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/caret-down.tsx +20 -0
- package/2/apps/native/src/components/ui/icons/chevron-up.tsx +21 -0
- package/2/apps/native/src/components/ui/icons/claude.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/copy.tsx +27 -0
- package/2/apps/native/src/components/ui/icons/deepseek.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/download.tsx +32 -0
- package/2/apps/native/src/components/ui/icons/feed.tsx +12 -0
- package/2/apps/native/src/components/ui/icons/gemini.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/github.tsx +30 -0
- package/2/apps/native/src/components/ui/icons/google.tsx +24 -0
- package/2/apps/native/src/components/ui/icons/groq.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/home.tsx +19 -0
- package/2/apps/native/src/components/ui/icons/index.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/language.tsx +33 -0
- package/2/apps/native/src/components/ui/icons/llama.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/microphone.tsx +20 -0
- package/2/apps/native/src/components/ui/icons/mistral.tsx +22 -0
- package/2/apps/native/src/components/ui/icons/nutrition.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/openai.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/perplexity.tsx +22 -0
- package/2/apps/native/src/components/ui/icons/qwen.tsx +15 -0
- package/2/apps/native/src/components/ui/icons/rate.tsx +24 -0
- package/2/apps/native/src/components/ui/icons/report.tsx +20 -0
- package/2/apps/native/src/components/ui/icons/send-horizontal.tsx +26 -0
- package/2/apps/native/src/components/ui/icons/settings.tsx +12 -0
- package/2/apps/native/src/components/ui/icons/share.tsx +16 -0
- package/2/apps/native/src/components/ui/icons/square.tsx +9 -0
- package/2/apps/native/src/components/ui/icons/style.tsx +22 -0
- package/2/apps/native/src/components/ui/icons/support.tsx +27 -0
- package/2/apps/native/src/components/ui/icons/trash2.tsx +42 -0
- package/2/apps/native/src/components/ui/icons/user.tsx +12 -0
- package/2/apps/native/src/components/ui/icons/website.tsx +28 -0
- package/2/apps/native/src/components/ui/icons/wifi-off.tsx +17 -0
- package/2/apps/native/src/components/ui/index.tsx +14 -0
- package/2/apps/native/src/components/ui/nav-item.tsx +42 -0
- package/2/apps/native/src/components/ui/patterns/index.ts +16 -0
- package/2/apps/native/src/components/ui/picker.tsx +244 -0
- package/2/apps/native/src/components/ui/popover.tsx +313 -0
- package/2/apps/native/src/components/ui/primitives/index.ts +38 -0
- package/2/apps/native/src/components/ui/radio-group.tsx +47 -0
- package/2/apps/native/src/components/ui/searchbar.tsx +118 -0
- package/2/apps/native/src/components/ui/sheet.tsx +93 -0
- package/2/apps/native/src/components/ui/switch.tsx +37 -0
- package/2/apps/native/src/components/ui/table.tsx +296 -0
- package/2/apps/native/src/components/ui/tabs.tsx +115 -0
- package/2/apps/native/src/components/ui/toggle.tsx +50 -0
- package/2/apps/native/src/components/ui/utils.tsx +34 -0
- package/2/apps/native/src/components/ui/video.tsx +39 -0
- package/2/apps/native/src/core/analytics/analytics-service.ts +94 -0
- package/2/apps/native/src/core/analytics/index.ts +2 -0
- package/2/apps/native/src/core/analytics/posthog-analytics-adapter.ts +192 -0
- package/2/apps/native/src/core/auth/auth-service.ts +33 -0
- package/2/apps/native/src/core/auth/index.ts +1 -0
- package/2/apps/native/src/core/cache/__tests__/cache-service.test.ts +599 -0
- package/2/apps/native/src/core/cache/cache-service.ts +89 -0
- package/2/apps/native/src/core/cache/index.ts +45 -0
- package/2/apps/native/src/core/config/config.service.ts +153 -0
- package/2/apps/native/src/core/config/index.ts +2 -0
- package/2/apps/native/src/core/config/telemetry.ts +38 -0
- package/2/apps/native/src/core/local-notifications/local-notification-manager.ts +409 -0
- package/2/apps/native/src/core/logging/custom-transports.ts +126 -0
- package/2/apps/native/src/core/logging/index.ts +1 -0
- package/2/apps/native/src/core/logging/logger.ts +182 -0
- package/2/apps/native/src/core/navigation/deep-link-handler.ts +295 -0
- package/2/apps/native/src/core/navigation/navigation-types.ts +53 -0
- package/2/apps/native/src/core/payments/index.ts +1 -0
- package/2/apps/native/src/core/payments/payment-service.ts +32 -0
- package/2/apps/native/src/core/quick-actions/index.ts +2 -0
- package/2/apps/native/src/core/quick-actions/quick-actions-adapter.ts +54 -0
- package/2/apps/native/src/core/quick-actions/types.ts +29 -0
- package/2/apps/native/src/core/storage/index.ts +1 -0
- package/2/apps/native/src/core/storage/mmkv.ts +62 -0
- package/2/apps/native/src/core/storage/notification-storage.ts +312 -0
- package/2/apps/native/src/core/types/common.ts +0 -0
- package/2/apps/native/src/core/utils/convex-http-api.ts +30 -0
- package/2/apps/native/src/features/audio-recorder/components/audio-player.tsx +301 -0
- package/2/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +373 -0
- package/2/apps/native/src/features/audio-recorder/components/audio-waveform.tsx +270 -0
- package/2/apps/native/src/features/audio-recorder/components/index.ts +4 -0
- package/2/apps/native/src/features/audio-recorder/components/recording-list.tsx +89 -0
- package/2/apps/native/src/features/audio-recorder/demo/audio-player-demo.tsx +66 -0
- package/2/apps/native/src/features/audio-recorder/demo/audio-recorder-cloud.tsx +68 -0
- package/2/apps/native/src/features/audio-recorder/demo/audio-recorder-interview.tsx +102 -0
- package/2/apps/native/src/features/audio-recorder/demo/basic.tsx +27 -0
- package/2/apps/native/src/features/audio-recorder/demo/index.ts +5 -0
- package/2/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +82 -0
- package/2/apps/native/src/features/authentication/components/auth-watcher.tsx +115 -0
- package/2/apps/native/src/features/authentication/components/login-form.tsx +85 -0
- package/2/apps/native/src/features/authentication/services/__tests__/convex-auth.adapter.test.ts +399 -0
- package/2/apps/native/src/features/authentication/services/convex-auth.adapter.ts +497 -0
- package/2/apps/native/src/features/authentication/services/index.ts +2 -0
- package/2/apps/native/src/features/charts/README.md +185 -0
- package/2/apps/native/src/features/charts/app/preview.tsx +226 -0
- package/2/apps/native/src/features/charts/components/area-chart.tsx +43 -0
- package/2/apps/native/src/features/charts/components/bar-chart.tsx +146 -0
- package/2/apps/native/src/features/charts/components/candlestick-chart.tsx +199 -0
- package/2/apps/native/src/features/charts/components/chart-card.tsx +68 -0
- package/2/apps/native/src/features/charts/components/column-chart.tsx +146 -0
- package/2/apps/native/src/features/charts/components/doughnut-chart.tsx +260 -0
- package/2/apps/native/src/features/charts/components/index.ts +13 -0
- package/2/apps/native/src/features/charts/components/line-chart.tsx +311 -0
- package/2/apps/native/src/features/charts/components/radar-chart.tsx +183 -0
- package/2/apps/native/src/features/charts/components/radial-bar-chart.tsx +191 -0
- package/2/apps/native/src/features/charts/components/stacked-area-chart.tsx +268 -0
- package/2/apps/native/src/features/charts/components/stacked-bar-chart.tsx +325 -0
- package/2/apps/native/src/features/charts/data/mock-data.ts +186 -0
- package/2/apps/native/src/features/charts/types/index.ts +69 -0
- package/2/apps/native/src/features/chatbot/app/index.tsx +303 -0
- package/2/apps/native/src/features/chatbot/components/chat-header-buttons.tsx +60 -0
- package/2/apps/native/src/features/chatbot/components/chat-input-bar.tsx +470 -0
- package/2/apps/native/src/features/chatbot/components/chat-markdown.tsx +576 -0
- package/2/apps/native/src/features/chatbot/components/chat-message-bubble.tsx +247 -0
- package/2/apps/native/src/features/chatbot/components/chat-settings-modal.tsx +162 -0
- package/2/apps/native/src/features/chatbot/components/image-preview-list.tsx +116 -0
- package/2/apps/native/src/features/chatbot/components/markdown/code-block.tsx +166 -0
- package/2/apps/native/src/features/chatbot/components/markdown/index.ts +11 -0
- package/2/apps/native/src/features/chatbot/components/markdown/table-renderer.tsx +130 -0
- package/2/apps/native/src/features/chatbot/components/message-error-boundary.tsx +79 -0
- package/2/apps/native/src/features/chatbot/components/message-list.tsx +174 -0
- package/2/apps/native/src/features/chatbot/components/model-selector.tsx +284 -0
- package/2/apps/native/src/features/chatbot/components/report-content-modal.tsx +189 -0
- package/2/apps/native/src/features/chatbot/components/suggested-messages.tsx +68 -0
- package/2/apps/native/src/features/chatbot/constants/models.ts +21 -0
- package/2/apps/native/src/features/chatbot/constants/report-reasons.ts +10 -0
- package/2/apps/native/src/features/chatbot/hooks/use-attachment-cache.ts +144 -0
- package/2/apps/native/src/features/chatbot/hooks/use-chat-config.ts +665 -0
- package/2/apps/native/src/features/chatbot/hooks/use-chat-handlers.ts +360 -0
- package/2/apps/native/src/features/chatbot/hooks/use-chatbot-settings.ts +90 -0
- package/2/apps/native/src/features/chatbot/hooks/use-conversation.ts +80 -0
- package/2/apps/native/src/features/chatbot/hooks/use-image-picker.ts +123 -0
- package/2/apps/native/src/features/chatbot/hooks/use-keyboard-coordinator.ts +162 -0
- package/2/apps/native/src/features/chatbot/hooks/use-smart-scroll-manager.ts +214 -0
- package/2/apps/native/src/features/chatbot/models/index.ts +87 -0
- package/2/apps/native/src/features/chatbot/models/models.ts +163 -0
- package/2/apps/native/src/features/chatbot/models/providers.ts +63 -0
- package/2/apps/native/src/features/chatbot/models/types.ts +41 -0
- package/2/apps/native/src/features/chatbot/services/file-uploader.ts +239 -0
- package/2/apps/native/src/features/chatbot/services/message-handler-service.ts +181 -0
- package/2/apps/native/src/features/chatbot/types/index.ts +61 -0
- package/2/apps/native/src/features/chatbot/utils/chat-telemetry.ts +92 -0
- package/2/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +304 -0
- package/2/apps/native/src/features/image-analyzer/app/camera.tsx +221 -0
- package/2/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +333 -0
- package/2/apps/native/src/features/image-analyzer/app/loading-screen.tsx +217 -0
- package/2/apps/native/src/features/image-analyzer/app/loading.tsx +194 -0
- package/2/apps/native/src/features/image-analyzer/app/results.tsx +137 -0
- package/2/apps/native/src/features/image-analyzer/app/trait-details.tsx +172 -0
- package/2/apps/native/src/features/image-analyzer/app/use-analysis-data.ts +143 -0
- package/2/apps/native/src/features/image-analyzer/app/use-results-screen.ts +151 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievement-badge.tsx +77 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievement-card.tsx +75 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievement-unlocked-modal.tsx +162 -0
- package/2/apps/native/src/features/image-analyzer/components/results/achievements-section.tsx +44 -0
- package/2/apps/native/src/features/image-analyzer/components/results/advice-list.tsx +42 -0
- package/2/apps/native/src/features/image-analyzer/components/results/circular-progress.tsx +233 -0
- package/2/apps/native/src/features/image-analyzer/components/results/content-card.tsx +38 -0
- package/2/apps/native/src/features/image-analyzer/components/results/error-state.tsx +42 -0
- package/2/apps/native/src/features/image-analyzer/components/results/index.ts +9 -0
- package/2/apps/native/src/features/image-analyzer/components/results/loading-state.tsx +26 -0
- package/2/apps/native/src/features/image-analyzer/components/results/profile-image.tsx +60 -0
- package/2/apps/native/src/features/image-analyzer/components/results/results-header.tsx +62 -0
- package/2/apps/native/src/features/image-analyzer/components/results/score-display.tsx +54 -0
- package/2/apps/native/src/features/image-analyzer/components/results/share-options-modal.tsx +110 -0
- package/2/apps/native/src/features/image-analyzer/components/results/traits-grid.tsx +74 -0
- package/2/apps/native/src/features/image-analyzer/config/analysis-config.ts +80 -0
- package/2/apps/native/src/features/image-analyzer/config/master-analysis-config.ts +157 -0
- package/2/apps/native/src/features/image-analyzer/hooks/index.ts +1 -0
- package/2/apps/native/src/features/image-analyzer/hooks/use-analysis.ts +37 -0
- package/2/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +202 -0
- package/2/apps/native/src/features/image-analyzer/services/analysis-service.ts +262 -0
- package/2/apps/native/src/features/image-analyzer/services/share-service.ts +176 -0
- package/2/apps/native/src/features/image-analyzer/services/trait-details-service.ts +289 -0
- package/2/apps/native/src/features/image-generator/app/_layout.tsx +26 -0
- package/2/apps/native/src/features/image-generator/app/gallery.tsx +217 -0
- package/2/apps/native/src/features/image-generator/app/index.tsx +237 -0
- package/2/apps/native/src/features/image-generator/components/gallery-image.tsx +25 -0
- package/2/apps/native/src/features/image-generator/components/image-detail-modal.tsx +215 -0
- package/2/apps/native/src/features/image-generator/components/image-model-selector.tsx +210 -0
- package/2/apps/native/src/features/image-generator/components/image-placeholder.tsx +26 -0
- package/2/apps/native/src/features/image-generator/hooks/use-image-gallery.ts +71 -0
- package/2/apps/native/src/features/image-generator/hooks/use-image-generator-settings.ts +152 -0
- package/2/apps/native/src/features/image-generator/hooks/use-image-generator.ts +93 -0
- package/2/apps/native/src/features/image-generator/models/models.ts +66 -0
- package/2/apps/native/src/features/image-generator/services/image-gallery-service.ts +98 -0
- package/2/apps/native/src/features/image-generator/services/image-save-service.ts +121 -0
- package/2/apps/native/src/features/onboarding/analytics/index.ts +9 -0
- package/2/apps/native/src/features/onboarding/components/onboarding-with-analytics.tsx +141 -0
- package/2/apps/native/src/features/onboarding/components/onboarding.tsx +173 -0
- package/2/apps/native/src/features/onboarding/config/onboarding-flow-config.ts +189 -0
- package/2/apps/native/src/features/onboarding/demo-one/app/index.tsx +43 -0
- package/2/apps/native/src/features/onboarding/demo-one/data.ts +32 -0
- package/2/apps/native/src/features/onboarding/hooks/use-onboarding-analytics.ts +323 -0
- package/2/apps/native/src/features/onboarding/services/onboarding-analytics.ts +432 -0
- package/2/apps/native/src/features/payments/README.md +200 -0
- package/2/apps/native/src/features/payments/app/local-paywall.tsx +194 -0
- package/2/apps/native/src/features/payments/app/remote-paywall.tsx +79 -0
- package/2/apps/native/src/features/payments/components/payment-initializer.tsx +95 -0
- package/2/apps/native/src/features/payments/components/paywall-error-state.tsx +60 -0
- package/2/apps/native/src/features/payments/components/paywall-local-mode.tsx +116 -0
- package/2/apps/native/src/features/payments/components/paywall-product-card.tsx +133 -0
- package/2/apps/native/src/features/payments/components/paywall-remote-mode.tsx +146 -0
- package/2/apps/native/src/features/payments/hooks/use-entitlement.ts +63 -0
- package/2/apps/native/src/features/payments/index.ts +8 -0
- package/2/apps/native/src/features/payments/services/revenuecat-adapter.ts +407 -0
- package/2/apps/native/src/features/quick-actions/components/quick-actions-demo.tsx +139 -0
- package/2/apps/native/src/features/quick-actions/config/default-actions.ts +83 -0
- package/2/apps/native/src/features/quick-actions/hooks/use-quick-actions.ts +45 -0
- package/2/apps/native/src/features/quick-actions/index.ts +4 -0
- package/2/apps/native/src/features/quick-actions/utils/quick-actions-manager.ts +105 -0
- package/2/apps/native/src/features/quiz/components/question.tsx +67 -0
- package/2/apps/native/src/features/quiz/config.ts +11 -0
- package/2/apps/native/src/features/quiz/index.tsx +133 -0
- package/2/apps/native/src/features/settings/ui/debug-info.tsx +75 -0
- package/2/apps/native/src/features/settings/ui/dev-tools.tsx +1 -0
- package/2/apps/native/src/features/settings/ui/item.tsx +45 -0
- package/2/apps/native/src/features/settings/ui/items-container.tsx +23 -0
- package/2/apps/native/src/features/settings/ui/language-item.tsx +52 -0
- package/2/apps/native/src/features/settings/ui/notification-item.tsx +59 -0
- package/2/apps/native/src/features/settings/ui/theme-item.tsx +45 -0
- package/2/apps/native/src/features/tracker-app/app/index.tsx +108 -0
- package/2/apps/native/src/features/tracker-app/components/animated-number.tsx +102 -0
- package/2/apps/native/src/features/tracker-app/components/calorie-card.tsx +66 -0
- package/2/apps/native/src/features/tracker-app/components/circular-progress.tsx +97 -0
- package/2/apps/native/src/features/tracker-app/components/floating-add-button.tsx +27 -0
- package/2/apps/native/src/features/tracker-app/components/macro-card.tsx +80 -0
- package/2/apps/native/src/features/tracker-app/components/promo-banner.tsx +98 -0
- package/2/apps/native/src/features/tracker-app/components/recently-logged.tsx +64 -0
- package/2/apps/native/src/features/tracker-app/components/week-calendar.tsx +68 -0
- package/2/apps/native/src/features/vibefast-features.ts +42 -0
- package/2/apps/native/src/features/voice-bot/README.md +185 -0
- package/2/apps/native/src/features/voice-bot/components/conversation-status.tsx +76 -0
- package/2/apps/native/src/features/voice-bot/components/index.ts +4 -0
- package/2/apps/native/src/features/voice-bot/components/message-input.tsx +98 -0
- package/2/apps/native/src/features/voice-bot/components/voice-bot-screen.tsx +173 -0
- package/2/apps/native/src/features/voice-bot/components/voice-controls.tsx +73 -0
- package/2/apps/native/src/features/voice-bot/index.ts +3 -0
- package/2/apps/native/src/features/voice-bot/services/index.ts +1 -0
- package/2/apps/native/src/features/voice-bot/services/use-voice-bot.ts +161 -0
- package/2/apps/native/src/features/voice-bot/types.ts +29 -0
- package/2/apps/native/src/features/wake-word/components/index.ts +1 -0
- package/2/apps/native/src/features/wake-word/components/wake-word-indicator.tsx +61 -0
- package/2/apps/native/src/features/wake-word/constants.ts +10 -0
- package/2/apps/native/src/features/wake-word/hooks/use-wake-word.ts +181 -0
- package/2/apps/native/src/features/wake-word/index.ts +22 -0
- package/2/apps/native/src/features/wake-word/services/audio-session.ts +40 -0
- package/2/apps/native/src/features/wake-word/services/event-bus.ts +31 -0
- package/2/apps/native/src/features/wake-word/services/keywords.ts +88 -0
- package/2/apps/native/src/features/wake-word/services/wake-word-manager.ts +249 -0
- package/2/apps/native/src/features/wake-word/types.ts +22 -0
- package/2/apps/native/src/lib/env.js +13 -0
- package/2/apps/native/src/lib/hooks/index.tsx +6 -0
- package/2/apps/native/src/lib/hooks/use-device-identifier.tsx +80 -0
- package/2/apps/native/src/lib/hooks/use-gradual-animation.ts +28 -0
- package/2/apps/native/src/lib/hooks/use-is-first-time.tsx +25 -0
- package/2/apps/native/src/lib/hooks/use-navigation-analytics.ts +44 -0
- package/2/apps/native/src/lib/hooks/use-navigation-options.tsx +87 -0
- package/2/apps/native/src/lib/hooks/use-push-notifications.ts +250 -0
- package/2/apps/native/src/lib/hooks/use-responsive-size.tsx +37 -0
- package/2/apps/native/src/lib/hooks/use-selected-theme.tsx +38 -0
- package/2/apps/native/src/lib/hooks/use-viewport-lazy-loading.tsx +124 -0
- package/2/apps/native/src/lib/i18n/index.tsx +30 -0
- package/2/apps/native/src/lib/i18n/react-i18next.d.ts +9 -0
- package/2/apps/native/src/lib/i18n/resources.ts +25 -0
- package/2/apps/native/src/lib/i18n/types.ts +23 -0
- package/2/apps/native/src/lib/i18n/utils.tsx +112 -0
- package/2/apps/native/src/lib/index.tsx +3 -0
- package/2/apps/native/src/lib/state/auth-client-slice.ts +34 -0
- package/2/apps/native/src/lib/state/index.ts +1 -0
- package/2/apps/native/src/lib/storage.tsx +7 -0
- package/2/apps/native/src/lib/test-utils.tsx +43 -0
- package/2/apps/native/src/lib/use-theme-config.tsx +108 -0
- package/2/apps/native/src/lib/utils.ts +29 -0
- package/2/apps/native/src/polyfills.ts +61 -0
- package/2/apps/native/src/providers/convex-provider.tsx +31 -0
- package/2/apps/native/src/providers/index.tsx +6 -0
- package/2/apps/native/src/providers/notification-provider.tsx +168 -0
- package/2/apps/native/src/providers/posthog-provider.tsx +47 -0
- package/2/apps/native/src/providers/root-providers.tsx +46 -0
- package/2/apps/native/src/providers/sentry-provider.tsx +62 -0
- package/2/apps/native/src/providers/splash-screen-provider.tsx +122 -0
- package/2/apps/native/src/providers/theme-provider.tsx +67 -0
- package/2/apps/native/src/translations/ar.json +394 -0
- package/2/apps/native/src/translations/de.json +394 -0
- package/2/apps/native/src/translations/en.json +394 -0
- package/2/apps/native/src/translations/es.json +394 -0
- package/2/apps/native/src/translations/fr.json +394 -0
- package/2/apps/native/src/types/flash-list.d.ts +3 -0
- package/2/apps/native/src/types/index.ts +3 -0
- package/2/apps/native/src/types/react-native-reanimated.d.ts +5 -0
- package/2/apps/native/tailwind.config.js +57 -0
- package/2/apps/native/targets/widget/AppIntent.swift +46 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png +0 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/Contents.json +122 -0
- package/2/apps/native/targets/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png +0 -0
- package/2/apps/native/targets/widget/CalorieTrackerWidget.swift +424 -0
- package/2/apps/native/targets/widget/HabitTrackerWidget.swift +305 -0
- package/2/apps/native/targets/widget/Info.plist +11 -0
- package/2/apps/native/targets/widget/WidgetLiveActivity.swift +75 -0
- package/2/apps/native/targets/widget/expo-target.config.js +10 -0
- package/2/apps/native/targets/widget/generated.entitlements +5 -0
- package/2/apps/native/targets/widget/index.swift +18 -0
- package/2/apps/native/targets/widget/widgets.swift +96 -0
- package/2/apps/native/tsconfig.json +88 -0
- package/2/apps/native/vitest.config.mts +14 -0
- package/2/apps/web/README.md +36 -0
- package/2/apps/web/app/favicon.ico +0 -0
- package/2/apps/web/app/globals.css +122 -0
- package/2/apps/web/app/layout.tsx +38 -0
- package/2/apps/web/app/page.tsx +35 -0
- package/2/apps/web/app/users/page.tsx +301 -0
- package/2/apps/web/components/AdminDashboard.tsx +336 -0
- package/2/apps/web/components/AppleLogo.tsx +15 -0
- package/2/apps/web/components/GitHubLogo.tsx +11 -0
- package/2/apps/web/components/GoogleLogo.tsx +23 -0
- package/2/apps/web/components/Layout.tsx +77 -0
- package/2/apps/web/components/ThemeToggle.tsx +23 -0
- package/2/apps/web/components/UserMenu.tsx +66 -0
- package/2/apps/web/components/auth/CodeInput.tsx +24 -0
- package/2/apps/web/components/auth/ResetPasswordWithEmailCode.tsx +85 -0
- package/2/apps/web/components/auth/SignInFormEmailCode.tsx +72 -0
- package/2/apps/web/components/auth/SignInFormEmailLink.tsx +81 -0
- package/2/apps/web/components/auth/SignInFormPassword.tsx +17 -0
- package/2/apps/web/components/auth/SignInFormPasswordAndCustomField.tsx +42 -0
- package/2/apps/web/components/auth/SignInFormPasswordAndResetViaCode.tsx +32 -0
- package/2/apps/web/components/auth/SignInFormPasswordAndVerifyViaCode.tsx +86 -0
- package/2/apps/web/components/auth/SignInFormPhoneCode.tsx +89 -0
- package/2/apps/web/components/auth/SignInFormsShowcase.tsx +64 -0
- package/2/apps/web/components/auth/SignInMethodDivider.tsx +17 -0
- package/2/apps/web/components/auth/SignInWithEmailCode.tsx +49 -0
- package/2/apps/web/components/auth/SignInWithOAuth.tsx +16 -0
- package/2/apps/web/components/auth/SignInWithPassword.tsx +100 -0
- package/2/apps/web/components/auth/oauth/SignInWithApple.tsx +27 -0
- package/2/apps/web/components/auth/oauth/SignInWithGitHub.tsx +27 -0
- package/2/apps/web/components/auth/oauth/SignInWithGoogle.tsx +27 -0
- package/2/apps/web/components/ui/button.tsx +60 -0
- package/2/apps/web/components/ui/card.tsx +92 -0
- package/2/apps/web/components/ui/dialog.tsx +143 -0
- package/2/apps/web/components/ui/dropdown-menu.tsx +257 -0
- package/2/apps/web/components/ui/input-otp.tsx +77 -0
- package/2/apps/web/components/ui/input.tsx +21 -0
- package/2/apps/web/components/ui/skeleton.tsx +13 -0
- package/2/apps/web/components/ui/tabs.tsx +66 -0
- package/2/apps/web/components/ui/toast.tsx +130 -0
- package/2/apps/web/components/ui/toaster.tsx +36 -0
- package/2/apps/web/components/ui/toggle-group.tsx +83 -0
- package/2/apps/web/components/ui/toggle.tsx +47 -0
- package/2/apps/web/components/ui/use-toast.ts +192 -0
- package/2/apps/web/components.json +22 -0
- package/2/apps/web/eslint.config.mjs +18 -0
- package/2/apps/web/lib/convex-provider.tsx +18 -0
- package/2/apps/web/lib/utils.ts +6 -0
- package/2/apps/web/next.config.ts +7 -0
- package/2/apps/web/package.json +46 -0
- package/2/apps/web/postcss.config.mjs +7 -0
- package/2/apps/web/public/file.svg +1 -0
- package/2/apps/web/public/globe.svg +1 -0
- package/2/apps/web/public/next.svg +1 -0
- package/2/apps/web/public/vercel.svg +1 -0
- package/2/apps/web/public/window.svg +1 -0
- package/2/apps/web/tsconfig.json +34 -0
- package/2/bts.jsonc +21 -0
- package/2/commitlint.config.js +1 -0
- package/2/eslint.config.mjs +182 -0
- package/2/lint-staged.config.js +16 -0
- package/2/package.json +64 -0
- package/2/packages/backend/.env.example +20 -0
- package/2/packages/backend/convex/README.md +90 -0
- package/2/packages/backend/convex/_generated/api.d.ts +2599 -0
- package/2/packages/backend/convex/_generated/api.js +23 -0
- package/2/packages/backend/convex/_generated/dataModel.d.ts +60 -0
- package/2/packages/backend/convex/_generated/server.d.ts +149 -0
- package/2/packages/backend/convex/_generated/server.js +90 -0
- package/2/packages/backend/convex/agents.ts +116 -0
- package/2/packages/backend/convex/auth.config.ts +8 -0
- package/2/packages/backend/convex/auth.ts +103 -0
- package/2/packages/backend/convex/authCustomEmailOtpProvider.ts +175 -0
- package/2/packages/backend/convex/authOtp.ts +144 -0
- package/2/packages/backend/convex/authPasswordReset.ts +367 -0
- package/2/packages/backend/convex/authPasswordResetActions.ts +150 -0
- package/2/packages/backend/convex/chatbot/index.ts +30 -0
- package/2/packages/backend/convex/chatbotAgent.ts +1085 -0
- package/2/packages/backend/convex/chatbotHistory.ts +307 -0
- package/2/packages/backend/convex/convex.config.ts +13 -0
- package/2/packages/backend/convex/deviceGrants.ts +58 -0
- package/2/packages/backend/convex/grantFunctions.ts +444 -0
- package/2/packages/backend/convex/http.ts +8 -0
- package/2/packages/backend/convex/imageAnalysis/index.ts +18 -0
- package/2/packages/backend/convex/imageAnalysisFunctions.ts +325 -0
- package/2/packages/backend/convex/imageGeneration/index.ts +12 -0
- package/2/packages/backend/convex/imageGeneratorFunctions.ts +290 -0
- package/2/packages/backend/convex/lib/ai/analysisConfigs.ts +257 -0
- package/2/packages/backend/convex/lib/ai/config.ts +71 -0
- package/2/packages/backend/convex/lib/ai/geminiAdapter.ts +43 -0
- package/2/packages/backend/convex/lib/ai/imageAnalysisAdapter.ts +200 -0
- package/2/packages/backend/convex/lib/ai/openaiAdapter.ts +43 -0
- package/2/packages/backend/convex/lib/ai/schemas.ts +79 -0
- package/2/packages/backend/convex/lib/config.ts +111 -0
- package/2/packages/backend/convex/lib/rateLimit.ts +100 -0
- package/2/packages/backend/convex/lib/telemetry.ts +29 -0
- package/2/packages/backend/convex/paymentFunctions.ts +119 -0
- package/2/packages/backend/convex/payments/index.ts +13 -0
- package/2/packages/backend/convex/pushNotificationFunctions.ts +342 -0
- package/2/packages/backend/convex/ragKnowledge.ts +714 -0
- package/2/packages/backend/convex/rateLimit.ts +13 -0
- package/2/packages/backend/convex/recordingFunctions.ts +98 -0
- package/2/packages/backend/convex/reportFunctions.ts +344 -0
- package/2/packages/backend/convex/reporting/index.ts +9 -0
- package/2/packages/backend/convex/router.ts +81 -0
- package/2/packages/backend/convex/schema.ts +237 -0
- package/2/packages/backend/convex/shared/email.ts +172 -0
- package/2/packages/backend/convex/shared/files.ts +96 -0
- package/2/packages/backend/convex/shared/index.ts +17 -0
- package/2/packages/backend/convex/shared/templates/PasswordResetEmail.tsx +72 -0
- package/2/packages/backend/convex/shared/templates/VerificationCodeEmail.tsx +65 -0
- package/2/packages/backend/convex/sharedUsers.ts +48 -0
- package/2/packages/backend/convex/tools/index.ts +18 -0
- package/2/packages/backend/convex/tools/knowledgeRetrieval.ts +92 -0
- package/2/packages/backend/convex/tools/tavilySearch.ts +83 -0
- package/2/packages/backend/convex/tools/userProfile.ts +72 -0
- package/2/packages/backend/convex/tsconfig.json +25 -0
- package/2/packages/backend/convex/users.ts +54 -0
- package/2/packages/backend/index.ts +20 -0
- package/2/packages/backend/package.json +32 -0
- package/2/packages/ui/README.md +63 -0
- package/2/packages/ui/index.ts +1 -0
- package/2/packages/ui/package.json +21 -0
- package/2/packages/ui/src/components/SharedButton.tsx +31 -0
- package/2/packages/ui/src/components/SharedCard.tsx +48 -0
- package/2/packages/ui/src/components/index.ts +2 -0
- package/2/packages/ui/tsconfig.json +10 -0
- package/2/pnpm-lock.yaml +23292 -0
- package/2/pnpm-workspace.yaml +3 -0
- package/2/scripts/i18next-syntax-validation.js +1 -0
- package/2/tsconfig.json +43 -0
- package/2/turbo.json +33 -0
- package/2/vercel.json +6 -0
- package/2/vf-agent/agent-teams/team-vibefast.yaml +14 -0
- package/2/vf-agent/agents/analyst.md +53 -0
- package/2/vf-agent/agents/architect.md +105 -0
- package/2/vf-agent/agents/dev.md +40 -0
- package/2/vf-agent/agents/orchestrator.md +181 -0
- package/2/vf-agent/agents/pm.md +48 -0
- package/2/vf-agent/agents/po.md +38 -0
- package/2/vf-agent/agents/qa.md +30 -0
- package/2/vf-agent/agents/sm.md +38 -0
- package/2/vf-agent/agents/ux-expert.md +33 -0
- package/2/vf-agent/checklists/po-master-checklist.md +73 -0
- package/2/vf-agent/checklists/story-dod-checklist.md +37 -0
- package/2/vf-agent/core-config.yaml +43 -0
- package/2/vf-agent/data/knowledge_base/backend/convex-advanced.md +43 -0
- package/2/vf-agent/data/knowledge_base/backend/convex-database.md +53 -0
- package/2/vf-agent/data/knowledge_base/backend/convex-main.md +65 -0
- package/2/vf-agent/data/knowledge_base/backend/full-guidelines.md +795 -0
- package/2/vf-agent/data/knowledge_base/coding-standards.md +253 -0
- package/2/vf-agent/data/knowledge_base/frontend/full-guidelines.md +254 -0
- package/2/vf-agent/data/knowledge_base/frontend/image-handling.md +48 -0
- package/2/vf-agent/data/knowledge_base/frontend/react-native-main.md +24 -0
- package/2/vf-agent/data/knowledge_base/frontend/ui-and-styling.md +169 -0
- package/2/vf-agent/data/knowledge_base/general-principles.md +26 -0
- package/2/vf-agent/data/knowledge_base/master-rulebook.md +42 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/audio-recorder-reference.md +98 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/authentication-reference.md +155 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/charts-reference.md +149 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/chatbot-reference.md +123 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/feature-reference-index.md +211 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/features-overview.md +221 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/image-analyzer-reference.md +118 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/image-generator-reference.md +110 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/index.md +28 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/onboarding-reference.md +96 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/payments-reference.md +148 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/prd.md +82 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/push-notifications-reference.md +453 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/quick-actions-reference.md +253 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/quiz-reference.md +169 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/settings-reference.md +146 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/tech-stack.md +159 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/tracker-app-reference.md +150 -0
- package/2/vf-agent/data/knowledge_base/starter-docs/unified-project-structure.md +98 -0
- package/2/vf-agent/data/knowledge_base/testing/backend-testing.md +54 -0
- package/2/vf-agent/data/knowledge_base/testing/frontend-testing.md +71 -0
- package/2/vf-agent/data/knowledge_base/testing/testing-strategy.md +31 -0
- package/2/vf-agent/tasks/advanced-elicitation.md +117 -0
- package/2/vf-agent/tasks/brownfield-create-epic.md +160 -0
- package/2/vf-agent/tasks/create-deep-research-prompt.md +278 -0
- package/2/vf-agent/tasks/create-doc.md +42 -0
- package/2/vf-agent/tasks/create-story.md +43 -0
- package/2/vf-agent/tasks/document-project.md +343 -0
- package/2/vf-agent/tasks/facilitate-brainstorming-session.md +136 -0
- package/2/vf-agent/tasks/index-docs.md +173 -0
- package/2/vf-agent/tasks/kb-mode-interaction.md +75 -0
- package/2/vf-agent/tasks/review-story.md +154 -0
- package/2/vf-agent/tasks/shard-doc.md +185 -0
- package/2/vf-agent/tasks/troubleshoot-issue.md +65 -0
- package/2/vf-agent/tasks/validate-next-story.md +47 -0
- package/2/vf-agent/templates/brainstorming-output-tmpl.yaml +156 -0
- package/2/vf-agent/templates/brownfield-architecture-tmpl.yaml +111 -0
- package/2/vf-agent/templates/brownfield-prd-tmpl.yaml +247 -0
- package/2/vf-agent/templates/competitor-analysis-tmpl.yaml +293 -0
- package/2/vf-agent/templates/market-research-tmpl.yaml +252 -0
- package/2/vf-agent/templates/project-brief-tmpl.yaml +221 -0
- package/2/vf-agent/templates/story-tmpl.yaml +143 -0
- package/BEFORE-AFTER.md +327 -0
- package/CHANGELOG.md +73 -0
- package/CLI-ROADMAP.md +415 -0
- package/COMMAND-REFERENCE.md +341 -0
- package/IMPLEMENTATION-STATUS.md +316 -0
- package/MANUAL-TEST-CHECKLIST.md +264 -0
- package/OPTIONS-GLOSSARY.md +308 -0
- package/PHASE-1-2-3-COMPLETE.md +435 -0
- package/PHASE-1-2-IMPLEMENTATION.md +280 -0
- package/PHASE-1-2-SUMMARY.md +183 -0
- package/QUICK-START.md +352 -0
- package/RECIPES-GUIDE.md +325 -0
- package/RELEASE-CHECKLIST.md +269 -0
- package/VF-INIT-FLOW.md +446 -0
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +328 -66
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/checklist.d.ts.map +1 -1
- package/dist/commands/checklist.js +69 -5
- package/dist/commands/checklist.js.map +1 -1
- package/dist/commands/env.d.ts +3 -0
- package/dist/commands/env.d.ts.map +1 -0
- package/dist/commands/env.js +130 -0
- package/dist/commands/env.js.map +1 -0
- package/dist/commands/health.d.ts +3 -0
- package/dist/commands/health.d.ts.map +1 -0
- package/dist/commands/health.js +214 -0
- package/dist/commands/health.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +310 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts.map +1 -1
- package/dist/commands/list.js +36 -16
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +5 -0
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +11 -0
- package/dist/commands/remove.js.map +1 -1
- package/dist/core/__tests__/detect.test.d.ts +2 -0
- package/dist/core/__tests__/detect.test.d.ts.map +1 -0
- package/dist/core/__tests__/detect.test.js +73 -0
- package/dist/core/__tests__/detect.test.js.map +1 -0
- package/dist/core/detect.d.ts +10 -0
- package/dist/core/detect.d.ts.map +1 -0
- package/dist/core/detect.js +58 -0
- package/dist/core/detect.js.map +1 -0
- package/dist/core/env.d.ts +24 -0
- package/dist/core/env.d.ts.map +1 -0
- package/dist/core/env.js +83 -0
- package/dist/core/env.js.map +1 -0
- package/dist/core/errors.d.ts +13 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +111 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/prompt.d.ts +46 -2
- package/dist/core/prompt.d.ts.map +1 -1
- package/dist/core/prompt.js +179 -15
- package/dist/core/prompt.js.map +1 -1
- package/dist/core/prompts.d.ts +23 -0
- package/dist/core/prompts.d.ts.map +1 -0
- package/dist/core/prompts.js +85 -0
- package/dist/core/prompts.js.map +1 -0
- package/dist/core/recipes.d.ts +31 -0
- package/dist/core/recipes.d.ts.map +1 -0
- package/dist/core/recipes.js +138 -0
- package/dist/core/recipes.js.map +1 -0
- package/dist/core/spinner.d.ts +20 -0
- package/dist/core/spinner.d.ts.map +1 -0
- package/dist/core/spinner.js +72 -0
- package/dist/core/spinner.js.map +1 -0
- package/dist/core/vosk.d.ts +7 -0
- package/dist/core/vosk.d.ts.map +1 -0
- package/dist/core/vosk.js +94 -0
- package/dist/core/vosk.js.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
- package/recipes/README.md +156 -0
- package/recipes/chatbot/packages/backend/convex/agents.ts +116 -0
- package/recipes/chatbot/packages/backend/convex/chatbotAgent.ts +1085 -0
- package/recipes/chatbot/packages/backend/convex/chatbotHistory.ts +307 -0
- package/recipes/chatbot/packages/backend/convex/lib/rateLimit.ts +100 -0
- package/recipes/chatbot/packages/backend/convex/lib/telemetry.ts +29 -0
- package/recipes/chatbot/packages/backend/convex/ragKnowledge.ts +714 -0
- package/recipes/chatbot/packages/backend/convex/tools/index.ts +18 -0
- package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +92 -0
- package/recipes/chatbot/packages/backend/convex/tools/tavilySearch.ts +83 -0
- package/recipes/chatbot/packages/backend/convex/tools/userProfile.ts +72 -0
- package/recipes/chatbot/recipe.json +89 -1
- package/recipes/chatbot@latest.zip +0 -0
- package/recipes/image-analysis/recipe.json +61 -0
- package/recipes/image-analysis@latest.zip +0 -0
- package/recipes/image-generator/packages/backend/convex/imageGeneration/index.ts +12 -0
- package/recipes/image-generator/packages/backend/convex/imageGeneratorFunctions.ts +290 -0
- package/recipes/image-generator/recipe.json +36 -1
- package/recipes/image-generator@latest.zip +0 -0
- package/recipes/posthog.json +46 -0
- package/recipes/revenuecat.json +43 -0
- package/recipes/sentry.json +46 -0
- package/recipes/voice-bot/packages/backend/convex/router.ts +81 -0
- package/recipes/voice-bot/recipe.json +51 -1
- package/recipes/voice-bot@latest.zip +0 -0
- package/recipes/wake-word/apps/native/assets/vosk-model/README.md +103 -0
- package/recipes/wake-word/apps/native/src/app/(root)/(protected)/test-wake-word.tsx +216 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/components/index.ts +1 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/components/wake-word-indicator.tsx +61 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/constants.ts +10 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/hooks/use-wake-word.ts +181 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/index.ts +22 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/audio-session.ts +40 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/event-bus.ts +31 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/keywords.ts +88 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/services/wake-word-manager.ts +249 -0
- package/recipes/wake-word/apps/native/src/features/wake-word/types.ts +22 -0
- package/recipes/wake-word/recipe.json +50 -0
- package/recipes/wake-word/scripts/download-vosk-model.mjs +121 -0
- package/recipes/wake-word@latest.zip +0 -0
- package/scripts/sync-recipes.js +93 -0
- package/src/commands/add.ts +401 -68
- package/src/commands/checklist.ts +81 -6
- package/src/commands/env.ts +163 -0
- package/src/commands/health.ts +225 -0
- package/src/commands/init.ts +390 -0
- package/src/commands/list.ts +42 -16
- package/src/commands/login.ts +6 -0
- package/src/commands/remove.ts +12 -0
- package/src/core/__tests__/detect.test.ts +91 -0
- package/src/core/detect.ts +60 -0
- package/src/core/env.ts +109 -0
- package/src/core/errors.ts +122 -0
- package/src/core/prompt.ts +227 -16
- package/src/core/prompts.ts +115 -0
- package/src/core/recipes.ts +152 -0
- package/src/core/spinner.ts +87 -0
- package/src/core/vosk.ts +111 -0
- package/src/index.ts +50 -0
- package/test-locally.sh +145 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generic trait analysis schema
|
|
5
|
+
*/
|
|
6
|
+
export const TraitAnalysisSchema = z.object({
|
|
7
|
+
score: z.number().min(0).max(100).describe('Score for this trait (0-100)'),
|
|
8
|
+
feedback: z.string().describe('Specific feedback about this trait'),
|
|
9
|
+
strengths: z.array(z.string()).describe('Key strengths for this trait'),
|
|
10
|
+
improvements: z
|
|
11
|
+
.array(z.string())
|
|
12
|
+
.describe('Suggested improvements for this trait'),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Base analysis configuration interface
|
|
17
|
+
*/
|
|
18
|
+
export interface AnalysisConfig {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
traits: Record<string, TraitConfig>;
|
|
23
|
+
prompts: {
|
|
24
|
+
base: string;
|
|
25
|
+
instructions: string;
|
|
26
|
+
};
|
|
27
|
+
schema: z.ZodObject<any>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Trait configuration interface
|
|
32
|
+
*/
|
|
33
|
+
export interface TraitConfig {
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
instructions: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Face Analysis Configuration
|
|
41
|
+
*/
|
|
42
|
+
export const FACE_ANALYSIS_CONFIG: AnalysisConfig = {
|
|
43
|
+
id: 'face_analysis',
|
|
44
|
+
name: 'Facial Analysis',
|
|
45
|
+
description: 'Comprehensive facial feature analysis',
|
|
46
|
+
traits: {
|
|
47
|
+
jawline: {
|
|
48
|
+
name: 'Jawline',
|
|
49
|
+
description: 'Definition, structure, and contouring',
|
|
50
|
+
instructions: 'Analyze jawline definition, structure, and contouring',
|
|
51
|
+
},
|
|
52
|
+
skinHealth: {
|
|
53
|
+
name: 'Skin Health',
|
|
54
|
+
description: 'Clarity, texture, tone, and overall health',
|
|
55
|
+
instructions: 'Assess skin clarity, texture, tone, and overall health',
|
|
56
|
+
},
|
|
57
|
+
facialSymmetry: {
|
|
58
|
+
name: 'Facial Symmetry',
|
|
59
|
+
description: 'Balance and proportions across facial features',
|
|
60
|
+
instructions: 'Evaluate facial symmetry and proportional balance',
|
|
61
|
+
},
|
|
62
|
+
eyeArea: {
|
|
63
|
+
name: 'Eye Area',
|
|
64
|
+
description: 'Shape, clarity, expressiveness, and overall appeal',
|
|
65
|
+
instructions: 'Analyze eye shape, clarity, and expressiveness',
|
|
66
|
+
},
|
|
67
|
+
noseStructure: {
|
|
68
|
+
name: 'Nose Structure',
|
|
69
|
+
description: 'Proportions, definition, and harmony with other features',
|
|
70
|
+
instructions: 'Assess nose proportions and structural harmony',
|
|
71
|
+
},
|
|
72
|
+
lipFullness: {
|
|
73
|
+
name: 'Lip Fullness',
|
|
74
|
+
description: 'Shape, fullness, and definition',
|
|
75
|
+
instructions: 'Evaluate lip shape, fullness, and definition',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
prompts: {
|
|
79
|
+
base: 'You are an expert facial analysis AI. Analyze the provided image(s) and provide a comprehensive facial analysis.',
|
|
80
|
+
instructions: `Please analyze the following facial traits and provide scores (0-100), specific feedback, strengths, and improvement suggestions for each:
|
|
81
|
+
|
|
82
|
+
For each trait, provide:
|
|
83
|
+
- A score from 0-100 (where 70+ is good, 80+ is very good, 90+ is excellent)
|
|
84
|
+
- Specific feedback about what you observe
|
|
85
|
+
- Key strengths to highlight
|
|
86
|
+
- Constructive improvement suggestions
|
|
87
|
+
|
|
88
|
+
Also provide:
|
|
89
|
+
- An overall score (average of all traits)
|
|
90
|
+
- A comprehensive analysis summary
|
|
91
|
+
- Actionable recommendations for enhancement
|
|
92
|
+
- Your confidence level in the analysis (0-1)`,
|
|
93
|
+
},
|
|
94
|
+
schema: z.object({
|
|
95
|
+
overallScore: z.number().min(0).max(100).describe('Overall analysis score'),
|
|
96
|
+
overallMessage: z.string().describe('Comprehensive analysis summary'),
|
|
97
|
+
confidence: z
|
|
98
|
+
.number()
|
|
99
|
+
.min(0)
|
|
100
|
+
.max(1)
|
|
101
|
+
.describe('AI confidence in the analysis'),
|
|
102
|
+
traitScores: z.object({
|
|
103
|
+
jawline: TraitAnalysisSchema,
|
|
104
|
+
skinHealth: TraitAnalysisSchema,
|
|
105
|
+
facialSymmetry: TraitAnalysisSchema,
|
|
106
|
+
eyeArea: TraitAnalysisSchema,
|
|
107
|
+
noseStructure: TraitAnalysisSchema,
|
|
108
|
+
lipFullness: TraitAnalysisSchema,
|
|
109
|
+
}),
|
|
110
|
+
recommendations: z
|
|
111
|
+
.array(z.string())
|
|
112
|
+
.describe('Actionable recommendations for improvement'),
|
|
113
|
+
analysisType: z.string().describe('Type of analysis performed'),
|
|
114
|
+
processingTime: z
|
|
115
|
+
.number()
|
|
116
|
+
.describe('Time taken for analysis in milliseconds'),
|
|
117
|
+
}),
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Registry of all available analysis configurations
|
|
122
|
+
*/
|
|
123
|
+
export const ANALYSIS_CONFIGS: Record<string, AnalysisConfig> = {
|
|
124
|
+
face_analysis: FACE_ANALYSIS_CONFIG,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get analysis configuration by ID
|
|
129
|
+
*/
|
|
130
|
+
export function getAnalysisConfig(analysisId: string): AnalysisConfig {
|
|
131
|
+
const config = ANALYSIS_CONFIGS[analysisId];
|
|
132
|
+
if (!config) {
|
|
133
|
+
throw new Error(`Unknown analysis type: ${analysisId}`);
|
|
134
|
+
}
|
|
135
|
+
return config;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Build analysis prompt for any configuration
|
|
140
|
+
*/
|
|
141
|
+
export function buildGenericAnalysisPrompt(
|
|
142
|
+
config: AnalysisConfig,
|
|
143
|
+
preferences: { goal: string; feedbackStyle: string },
|
|
144
|
+
imageCount: number,
|
|
145
|
+
): string {
|
|
146
|
+
const traitInstructions = Object.entries(config.traits)
|
|
147
|
+
.map(
|
|
148
|
+
([, trait], index) =>
|
|
149
|
+
`${index + 1}. **${trait.name}**: ${trait.description}`,
|
|
150
|
+
)
|
|
151
|
+
.join('\n');
|
|
152
|
+
|
|
153
|
+
const basePrompt = `${config.prompts.base}
|
|
154
|
+
|
|
155
|
+
Analysis Goal: ${preferences.goal}
|
|
156
|
+
Feedback Style: ${preferences.feedbackStyle}
|
|
157
|
+
|
|
158
|
+
Analyze the provided ${imageCount} image(s):
|
|
159
|
+
|
|
160
|
+
${traitInstructions}
|
|
161
|
+
|
|
162
|
+
${config.prompts.instructions}
|
|
163
|
+
|
|
164
|
+
`;
|
|
165
|
+
|
|
166
|
+
// Add goal-specific guidance
|
|
167
|
+
const goalGuidance = getGoalSpecificGuidance(preferences.goal);
|
|
168
|
+
const styleGuidance = getStyleSpecificGuidance(preferences.feedbackStyle);
|
|
169
|
+
|
|
170
|
+
return `${basePrompt}
|
|
171
|
+
|
|
172
|
+
${goalGuidance}
|
|
173
|
+
|
|
174
|
+
${styleGuidance}
|
|
175
|
+
|
|
176
|
+
Be thorough, accurate, and ${preferences.feedbackStyle} in your analysis.`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get goal-specific analysis guidance
|
|
181
|
+
*/
|
|
182
|
+
function getGoalSpecificGuidance(goal: string): string {
|
|
183
|
+
switch (goal.toLowerCase()) {
|
|
184
|
+
case 'facial_beauty':
|
|
185
|
+
case 'beauty':
|
|
186
|
+
return 'Focus on aesthetic appeal, harmony between features, and overall attractiveness. Consider classical beauty standards while being inclusive of diverse features.';
|
|
187
|
+
|
|
188
|
+
case 'skin_health':
|
|
189
|
+
case 'health':
|
|
190
|
+
return 'Prioritize health-related aspects: condition, quality, signs of wear or damage, and overall health indicators.';
|
|
191
|
+
|
|
192
|
+
case 'facial_structure':
|
|
193
|
+
case 'structure':
|
|
194
|
+
return 'Emphasize structural elements, proportions, symmetry, and the geometric relationships between different components.';
|
|
195
|
+
|
|
196
|
+
case 'overall_attractiveness':
|
|
197
|
+
case 'attractiveness':
|
|
198
|
+
return 'Provide a holistic assessment considering all factors that contribute to overall appeal, including harmony, uniqueness, and visual impact.';
|
|
199
|
+
|
|
200
|
+
case 'condition':
|
|
201
|
+
return 'Focus on the current condition, wear, maintenance, and overall state of the subject being analyzed.';
|
|
202
|
+
|
|
203
|
+
default:
|
|
204
|
+
return 'Provide a balanced analysis considering all aspects with equal weight.';
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Get style-specific feedback guidance
|
|
210
|
+
*/
|
|
211
|
+
function getStyleSpecificGuidance(style: string): string {
|
|
212
|
+
switch (style.toLowerCase()) {
|
|
213
|
+
case 'constructive':
|
|
214
|
+
return 'Frame all feedback constructively, focusing on actionable improvements while highlighting existing strengths. Be encouraging and supportive.';
|
|
215
|
+
|
|
216
|
+
case 'detailed':
|
|
217
|
+
return 'Provide in-depth, technical analysis with specific observations. Include detailed explanations of your scoring rationale.';
|
|
218
|
+
|
|
219
|
+
case 'encouraging':
|
|
220
|
+
return 'Emphasize positive aspects and frame any suggestions for improvement in an uplifting, motivational manner. Build confidence.';
|
|
221
|
+
|
|
222
|
+
case 'professional':
|
|
223
|
+
return 'Maintain a clinical, objective tone similar to a professional consultation. Be precise and evidence-based.';
|
|
224
|
+
|
|
225
|
+
default:
|
|
226
|
+
return 'Provide balanced, honest feedback that is both informative and respectful.';
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Create dynamic schema for any trait configuration
|
|
232
|
+
*/
|
|
233
|
+
export function createDynamicSchema(traits: Record<string, TraitConfig>) {
|
|
234
|
+
const traitSchemas: Record<string, typeof TraitAnalysisSchema> = {};
|
|
235
|
+
|
|
236
|
+
Object.keys(traits).forEach((traitKey) => {
|
|
237
|
+
traitSchemas[traitKey] = TraitAnalysisSchema;
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
return z.object({
|
|
241
|
+
overallScore: z.number().min(0).max(100).describe('Overall analysis score'),
|
|
242
|
+
overallMessage: z.string().describe('Comprehensive analysis summary'),
|
|
243
|
+
confidence: z
|
|
244
|
+
.number()
|
|
245
|
+
.min(0)
|
|
246
|
+
.max(1)
|
|
247
|
+
.describe('AI confidence in the analysis'),
|
|
248
|
+
traitScores: z.object(traitSchemas),
|
|
249
|
+
recommendations: z
|
|
250
|
+
.array(z.string())
|
|
251
|
+
.describe('Actionable recommendations for improvement'),
|
|
252
|
+
analysisType: z.string().describe('Type of analysis performed'),
|
|
253
|
+
processingTime: z
|
|
254
|
+
.number()
|
|
255
|
+
.describe('Time taken for analysis in milliseconds'),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Configuration for Image Analysis
|
|
3
|
+
* Provides configurable provider and model selection
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type AIProvider = 'openai' | 'gemini';
|
|
7
|
+
|
|
8
|
+
export interface AIConfig {
|
|
9
|
+
provider: AIProvider;
|
|
10
|
+
model: string;
|
|
11
|
+
temperature: number;
|
|
12
|
+
maxTokens: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default AI configurations for different providers
|
|
17
|
+
*/
|
|
18
|
+
export const AI_CONFIGS: Record<AIProvider, AIConfig> = {
|
|
19
|
+
openai: {
|
|
20
|
+
provider: 'openai',
|
|
21
|
+
model: 'gpt-4o', // Latest GPT-4 with vision capabilities
|
|
22
|
+
temperature: 0.3, // Lower temperature for more consistent analysis
|
|
23
|
+
maxTokens: 2000,
|
|
24
|
+
},
|
|
25
|
+
gemini: {
|
|
26
|
+
provider: 'gemini',
|
|
27
|
+
model: 'gemini-1.5-pro', // Gemini Pro with vision capabilities
|
|
28
|
+
temperature: 0.3,
|
|
29
|
+
maxTokens: 2000,
|
|
30
|
+
},
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get AI configuration based on environment or default
|
|
35
|
+
*/
|
|
36
|
+
export function getAIConfig(): AIConfig {
|
|
37
|
+
const provider = (process.env.AI_PROVIDER as AIProvider) || 'openai';
|
|
38
|
+
const config = AI_CONFIGS[provider];
|
|
39
|
+
|
|
40
|
+
// Allow model override via environment variable
|
|
41
|
+
if (process.env.AI_MODEL) {
|
|
42
|
+
config.model = process.env.AI_MODEL;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return config;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Available analysis goals for image analysis
|
|
50
|
+
*/
|
|
51
|
+
export const ANALYSIS_GOALS = {
|
|
52
|
+
FACIAL_BEAUTY: 'facial_beauty',
|
|
53
|
+
SKIN_HEALTH: 'skin_health',
|
|
54
|
+
FACIAL_STRUCTURE: 'facial_structure',
|
|
55
|
+
OVERALL_ATTRACTIVENESS: 'overall_attractiveness',
|
|
56
|
+
} as const;
|
|
57
|
+
|
|
58
|
+
export type AnalysisGoal = (typeof ANALYSIS_GOALS)[keyof typeof ANALYSIS_GOALS];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Available feedback styles
|
|
62
|
+
*/
|
|
63
|
+
export const FEEDBACK_STYLES = {
|
|
64
|
+
CONSTRUCTIVE: 'constructive',
|
|
65
|
+
DETAILED: 'detailed',
|
|
66
|
+
ENCOURAGING: 'encouraging',
|
|
67
|
+
PROFESSIONAL: 'professional',
|
|
68
|
+
} as const;
|
|
69
|
+
|
|
70
|
+
export type FeedbackStyle =
|
|
71
|
+
(typeof FEEDBACK_STYLES)[keyof typeof FEEDBACK_STYLES];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createGoogleGenerativeAI } from '@ai-sdk/google';
|
|
2
|
+
import { type CoreMessage, streamText } from 'ai';
|
|
3
|
+
|
|
4
|
+
export interface GeminiStreamOptions {
|
|
5
|
+
model?: string;
|
|
6
|
+
temperature?: number;
|
|
7
|
+
maxTokens?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Stream chat completion from Google Gemini using Vercel AI SDK
|
|
12
|
+
*/
|
|
13
|
+
export async function streamGeminiChat(
|
|
14
|
+
messages: CoreMessage[],
|
|
15
|
+
options: GeminiStreamOptions = {},
|
|
16
|
+
onFinish?: (result: any) => Promise<void>,
|
|
17
|
+
) {
|
|
18
|
+
const {
|
|
19
|
+
model = 'gemini-2.0-flash',
|
|
20
|
+
temperature = 0.7,
|
|
21
|
+
maxTokens = 1000,
|
|
22
|
+
} = options;
|
|
23
|
+
|
|
24
|
+
// Get API key from environment variables
|
|
25
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
26
|
+
if (!apiKey) {
|
|
27
|
+
throw new Error('GEMINI_API_KEY environment variable is required');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Create Google provider with API key
|
|
31
|
+
const googleProvider = createGoogleGenerativeAI({ apiKey });
|
|
32
|
+
|
|
33
|
+
// Stream text generation
|
|
34
|
+
const result = await streamText({
|
|
35
|
+
model: googleProvider(model),
|
|
36
|
+
messages,
|
|
37
|
+
temperature,
|
|
38
|
+
maxTokens,
|
|
39
|
+
onFinish,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
@@ -0,0 +1,200 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createOpenAI } from '@ai-sdk/openai';
|
|
2
|
+
import { type CoreMessage, streamText } from 'ai';
|
|
3
|
+
|
|
4
|
+
export interface OpenAIStreamOptions {
|
|
5
|
+
model?: string;
|
|
6
|
+
temperature?: number;
|
|
7
|
+
maxTokens?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Stream chat completion from OpenAI using Vercel AI SDK
|
|
12
|
+
*/
|
|
13
|
+
export async function streamOpenAIChat(
|
|
14
|
+
messages: CoreMessage[],
|
|
15
|
+
options: OpenAIStreamOptions = {},
|
|
16
|
+
onFinish?: (result: any) => Promise<void>,
|
|
17
|
+
) {
|
|
18
|
+
const {
|
|
19
|
+
model = 'gpt-4.1-nano',
|
|
20
|
+
temperature = 0.7,
|
|
21
|
+
maxTokens = 1000,
|
|
22
|
+
} = options;
|
|
23
|
+
|
|
24
|
+
// Get API key from environment variables
|
|
25
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
26
|
+
if (!apiKey) {
|
|
27
|
+
throw new Error('OPENAI_API_KEY environment variable is required');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Create OpenAI provider with API key
|
|
31
|
+
const openaiProvider = createOpenAI({ apiKey });
|
|
32
|
+
|
|
33
|
+
// Stream text generation
|
|
34
|
+
const result = await streamText({
|
|
35
|
+
model: openaiProvider(model),
|
|
36
|
+
messages,
|
|
37
|
+
temperature,
|
|
38
|
+
maxTokens,
|
|
39
|
+
onFinish,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Schema for individual trait analysis
|
|
5
|
+
*/
|
|
6
|
+
export const TraitAnalysisSchema = z.object({
|
|
7
|
+
score: z.number().min(0).max(100).describe('Score from 0-100 for this trait'),
|
|
8
|
+
feedback: z.string().describe('Specific feedback about this trait'),
|
|
9
|
+
strengths: z.array(z.string()).describe('Key strengths for this trait'),
|
|
10
|
+
improvements: z
|
|
11
|
+
.array(z.string())
|
|
12
|
+
.describe('Suggested improvements for this trait'),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Schema for comprehensive facial analysis results
|
|
17
|
+
*/
|
|
18
|
+
export const FacialAnalysisSchema = z.object({
|
|
19
|
+
// Overall analysis
|
|
20
|
+
overallScore: z
|
|
21
|
+
.number()
|
|
22
|
+
.min(0)
|
|
23
|
+
.max(100)
|
|
24
|
+
.describe('Overall facial analysis score'),
|
|
25
|
+
overallMessage: z.string().describe('Comprehensive analysis summary'),
|
|
26
|
+
confidence: z
|
|
27
|
+
.number()
|
|
28
|
+
.min(0)
|
|
29
|
+
.max(1)
|
|
30
|
+
.describe('AI confidence in the analysis'),
|
|
31
|
+
|
|
32
|
+
// Individual trait scores
|
|
33
|
+
traitScores: z.object({
|
|
34
|
+
jawline: TraitAnalysisSchema.describe('Jawline definition and structure'),
|
|
35
|
+
skinHealth: TraitAnalysisSchema.describe(
|
|
36
|
+
'Skin clarity, texture, and health',
|
|
37
|
+
),
|
|
38
|
+
facialSymmetry: TraitAnalysisSchema.describe(
|
|
39
|
+
'Facial symmetry and proportions',
|
|
40
|
+
),
|
|
41
|
+
eyeArea: TraitAnalysisSchema.describe(
|
|
42
|
+
'Eye shape, clarity, and expressiveness',
|
|
43
|
+
),
|
|
44
|
+
noseStructure: TraitAnalysisSchema.describe(
|
|
45
|
+
'Nose proportions and structure',
|
|
46
|
+
),
|
|
47
|
+
lipFullness: TraitAnalysisSchema.describe('Lip shape and fullness'),
|
|
48
|
+
}),
|
|
49
|
+
|
|
50
|
+
// Recommendations
|
|
51
|
+
recommendations: z
|
|
52
|
+
.array(z.string())
|
|
53
|
+
.describe('Actionable recommendations for improvement'),
|
|
54
|
+
|
|
55
|
+
// Analysis metadata
|
|
56
|
+
analysisType: z.string().describe('Type of analysis performed'),
|
|
57
|
+
processingTime: z
|
|
58
|
+
.number()
|
|
59
|
+
.describe('Time taken for analysis in milliseconds'),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Type definitions derived from schemas
|
|
64
|
+
*/
|
|
65
|
+
export type TraitAnalysis = z.infer<typeof TraitAnalysisSchema>;
|
|
66
|
+
export type FacialAnalysisResult = z.infer<typeof FacialAnalysisSchema>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Schema for the AI prompt context
|
|
70
|
+
*/
|
|
71
|
+
export const AnalysisPromptSchema = z.object({
|
|
72
|
+
goal: z.string().describe('Analysis goal (e.g., facial_beauty, skin_health)'),
|
|
73
|
+
feedbackStyle: z
|
|
74
|
+
.string()
|
|
75
|
+
.describe('Feedback style (e.g., constructive, detailed)'),
|
|
76
|
+
imageCount: z.number().describe('Number of images being analyzed'),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export type AnalysisPrompt = z.infer<typeof AnalysisPromptSchema>;
|