Commit Graph

1045 Commits

Author SHA1 Message Date
ي
23489fdc12 Add flat-context synthesis and mnemonic prompt injection 2026-05-18 16:00:56 +05:30
ajaysi
928c2f20aa fix: WYSIWYG editor, content generation, and writing assistant bug fixes
- Fix text selection menu not showing: wire contentRef via inputRef on multiline TextField
- Fix blog title not truncating: add min-w-0 for flex item overflow
- Fix outline generation 500: escape curly braces in f-string prompt template
- Fix content generation 'NoneType not callable': replace SessionLocal() with get_session_for_user(), add db param to MediumBlogGenerator, fix signature mismatch in database_task_manager
- Fix writing assistant suggest 500: add auth + user_id to API endpoint and service, replace sync requests with httpx.AsyncClient
- Fix hallucination detector 404: explicitly include router in main.py and app.py
- Fix missing error_data in task failure responses
- Hide CopilotKit web inspector button
- Remove hardcoded fallback suggestions from SmartTypingAssist
- Fix stale closure refs in SmartTypingAssist handleTypingChange
- Add two-column editor layout, stats bar, section hover menu
- Various subscription, billing, and research module improvements
2026-05-14 09:11:51 +05:30
ajaysi
7385100017 fix(product-marketing): route image generation through unified subscription validation
Backend:
- product_image_service.py: Replaced direct wavespeed_client.generate_image()
  with generate_image() from main_image_generation (unified entry point)
- This ensures subscription pre-flight validation (_validate_image_operation)
  and usage tracking (_track_image_operation_usage) are enforced
- Removed _generate_image_with_retry method and WaveSpeedClient dependency
- Animation/video/avatar services already route through ImageStudioManager - no changes needed

Frontend:
- useProductMarketing.ts: Added formatError() helper for 402/429 detection
  across all 8 API operations
- useCampaignCreator.ts: Added formatError() helper for 402/429 detection
  across all 13 API operations
- All error messages now surface subscription limits with upgrade prompts
2026-05-14 09:11:51 +05:30
ajaysi
93a1985d9f fix(image-studio): add asset library saving + 402 subscription error handling
Backend:
- New POST /api/image-studio/save-to-library endpoint
  Saves generated base64 images to workspace disk and creates ContentAsset
  record for the unified asset library. Returns asset_id, file_url, filename.

Frontend:
- Added saveImageToLibrary() to useImageStudio hook
- CreateStudio auto-saves generated images to asset library after creation
- All 8 API operations now use _formatErrorMessage() helper
  for 402/429 subscription limit errors with upgrade prompts
  instead of generic error messages
2026-05-14 09:11:51 +05:30
ajaysi
4fdc7d3ea0 refactor(phase3-session-b4): remove legacy router, __init__.py creates router directly
- Deleted empty routers/image_studio_router.py (legacy file)
- __init__.py now creates APIRouter directly instead of re-exporting from legacy
- Same prefix, tags, and all 33 routes preserved
- app.py imports unchanged: from routers.image_studio import router as image_studio_router

Final package structure:
routers/image_studio/
  ├── __init__.py  ← creates router, includes 10 sub-routers
  ├── models.py    ← 40 Pydantic models
  ├── deps.py      ← shared dependencies
  ├── create.py edit.py face_swap.py upscale.py  ← endpoint groups
  ├── control.py social.py transform.py
  ├── compress.py convert.py health.py
2026-05-14 09:11:51 +05:30
ajaysi
85d6cc1d20 refactor(phase3-session-b3): extract create, transform, compress, convert into sub-routers
Extracted remaining 4 endpoint groups:
- create.py: 7 endpoints (create, 3xtemplates, providers, estimate-cost, platform-specs)
- transform.py: 4 endpoints (image-to-video, talking-avatar, estimate-cost, video serving)
- compress.py: 5 endpoints (compress, batch, estimate, formats, presets)
- convert.py: 4 endpoints (convert-format, batch, supported, recommendations)

Legacy router is now empty (only imports + empty router definition).
All 33 routes preserved. Package is fully modular.
2026-05-14 09:11:51 +05:30
ajaysi
0d20dcb801 refactor(phase3-session-b2): extract edit and face_swap into sub-routers
Extracted 2 endpoint groups into separate sub-router modules:
- edit.py: 4 endpoints (POST /edit/process, GET /edit/operations, GET /edit/models, POST /edit/recommend)
- face_swap.py: 3 endpoints (POST /face-swap/process, GET /face-swap/models, POST /face-swap/recommend)

All 33 routes preserved (10 extracted in B1, 7 extracted in B2, 16 remaining in legacy).
2026-05-14 09:11:51 +05:30
ajaysi
463cfdc5cf refactor(phase3-session-b1): extract upscale, control, social, health into sub-routers
Extracted 4 endpoint groups into separate sub-router modules:
- health.py: 1 endpoint (GET /health)
- upscale.py: 1 endpoint (POST /upscale)
- control.py: 2 endpoints (POST /control/process, GET /control/operations)
- social.py: 2 endpoints (POST /social/optimize, GET /social/platforms/{platform}/formats)

__init__.py now composes these sub-routers into the legacy router.
All 33 routes preserved. No functional changes.
2026-05-14 09:11:51 +05:30
ajaysi
19a5af9682 refactor(phase3-session-a): extract Image Studio models and deps into separate modules
- Created routers/image_studio/models.py with all 40 Pydantic models
- Created routers/image_studio/deps.py with get_studio_manager() and _require_user_id()
- Renamed old monolithic image_studio.py -> image_studio_router.py
- Updated __init__.py to re-export the router for backward compatibility
- Old file now imports models and deps from new modules (no inline definitions)

Backward compatibility: from routers.image_studio import router still works.
Route count unchanged: 33 routes, prefix /api/image-studio.
2026-05-14 09:11:51 +05:30
ajaysi
ca725b77e7 refactor(phase2): add provider-aware tracking and fill missing subscription usage tracking
Changes:
1. helpers.py (_track_image_operation_usage): Map provider name to DB columns
   dynamically (stability→stability_calls, wavespeed→wavespeed_calls, etc.)
   instead of hardcoding stability_calls/stability_cost.

2. upscale_service.py: Added _track_image_operation_usage() call after
   successful Stability upscale completion.

3. control_service.py: Added _track_image_operation_usage() call after
   successful Stability control operation completion.

4. edit_service.py: Added _track_image_operation_usage() call after
   successful Stability edit operation (remove_background, inpaint,
   outpaint, search_replace, search_recolor, relight).

Previously only Create Studio and Face Swap tracked usage. Now all five
studios correctly decrement subscription limits.
2026-05-14 09:11:51 +05:30
ajaysi
bc311cfdf6 refactor(phase1): extract image generation helpers, edit, face_swap into separate modules + fix subscription bugs
Extracted from main_image_generation.py (1002->591 lines):
- image_generation/helpers.py: _validate_image_operation, _track_image_operation_usage
- image_generation/edit.py: generate_image_edit (with _get_edit_provider)
- image_generation/face_swap.py: generate_face_swap (with _get_face_swap_provider)

Main image_generation.py now imports and re-exports from these modules.
All existing imports (api/images.py, step4_asset_routes.py, studio services) continue to work unchanged.

Bug fixes included:
1. generate_image_edit: Added missing 'return result' (was returning None!)
2. generate_image_edit: Added missing _track_image_operation_usage call
3. generate_face_swap: Removed duplicate dead tracking code after return statement
2026-05-14 09:11:51 +05:30
ajaysi
6c740ee63f docs(01-code-splitting): complete Phase 1 - MUI icon optimization and roadmap update
- Phase 1 complete: all 3 plans executed
- MUI icon barrel imports eliminated (111 files)
- ROADMAP.md updated: Phase 1 marked complete, consolidated Phase 3 & 4
- STATE.md updated: reflects actual progress and decisions
2026-05-14 09:11:51 +05:30
ajaysi
05e84d6089 fix(01-code-splitting): convert StoryWriter, YouTubeCreator MUI icons
- Converted barrel imports to individual imports across 22 files
- StoryWriter (3), YouTubeCreator (19)
2026-05-14 09:11:51 +05:30
ajaysi
f46465cd97 fix(01-code-splitting): convert PodcastMaker, ProductMarketing, Research, Scheduler, SEO, shared MUI icons
- Converted barrel imports to individual imports across 44 files
- Covers CreateStep, ScriptEditor, RenderQueue, ProductMarketing, Scheduler, SEO, shared components
2026-05-14 09:11:51 +05:30
ajaysi
ebdd1edfa0 fix(01-code-splitting): convert PodcastMaker AnalysisPanel MUI icons
- Converted barrel imports to individual imports across 18 AnalysisPanel files
- AnalysisPanel.tsx (12 icons), AnalysisTabNav.tsx (9 icons)
2026-05-14 09:11:51 +05:30
ajaysi
45bd1eada9 fix(01-code-splitting): convert ImageStudio, Landing, LinkedIn, MainDashboard, OnboardingWizard MUI icons
- Converted barrel imports to individual imports across 14 files
- Most complex: VoiceAvatarPlaceholder (22 icons), FeatureShowcase (8), TestPersonaModal (9)
2026-05-14 09:11:51 +05:30
ajaysi
ef7b3d2b49 fix(01-code-splitting): convert billing, blog, content-planning, error-boundary, pricing, alerts MUI icons
- Converted barrel imports to individual imports across 8 files
- Affected files: billing (2), BlogWriter (1), ContentPlanningDashboard (2), ErrorBoundary (1), Pricing (1), AlertsBadge (1)
2026-05-14 09:11:50 +05:30
ajaysi
98cfb03cf7 fix(01-code-splitting): convert BillingPage MUI icons to individual imports
- Converted 1 barrel import (Refresh) to per-file default import
2026-05-14 09:11:50 +05:30
ajaysi
993000a540 fix(01-code-splitting): convert SchedulerDashboard MUI icons to individual imports
- Converted 7 barrel imports (Refresh, Schedule, CheckCircle, PlayArrow, Pause, TrendingUp, AccessTime) to per-file default imports
2026-05-14 09:11:50 +05:30
ajaysi
b3e2f4382c fix(01-code-splitting): convert SubscriptionExpiredModal MUI icons to individual imports
- Converted 3 barrel imports (CreditCard, Warning, ArrowForward) to per-file default imports
2026-05-14 09:11:50 +05:30
ajaysi
638e785ad4 fix(01-code-splitting): convert SubscriptionGuard MUI icons to individual imports
- Converted 2 barrel imports (Lock, Upgrade) to per-file default imports
2026-05-14 09:11:50 +05:30
ajaysi
98a1cc91a2 fix(01-code-splitting): convert ErrorBoundary MUI icons to individual imports
- Converted 5 barrel imports (ErrorOutline, Refresh, Home, ExpandMore, BugReport) to per-file default imports
- No JSX changes needed (aliases already matched variable names)
2026-05-14 09:11:50 +05:30
ajaysi
ab827e9ab9 feat(01-code-splitting): add feature gating with ALWRITY_ENABLED_FEATURES
- Create FeatureRoute.tsx wrapper component for route-level feature gating
- Add FEATURE_KEYS constant map to demoMode.ts for type-safe feature references
- Wrap 47 feature-specific routes with <FeatureRoute> in App.tsx
- Core routes (dashboard, billing, pricing, auth callbacks) remain ungated
- Disabled features redirect to /dashboard and never load their lazy chunks
- Main bundle: +259 bytes (FeatureRoute is a lightweight component)

Closes Phase 1 Plan 01-02
2026-05-14 09:11:50 +05:30
ajaysi
8ee042bd2c feat(01-code-splitting): convert 31+ route components to React.lazy
- Replace all 31+ static route component imports in App.tsx with React.lazy() dynamic imports
- Add LazyLoadingFallback.tsx shared component for Suspense fallback
- Wrap <Routes> with <Suspense> for chunk loading states
- Handle named exports (ImageStudio, VideoStudio, ProductMarketing, StoryProjectList) with .then() wrapper
- Main bundle reduced from 8.42MB to 2.50MB (70% reduction)
- 190+ chunk files created for on-demand loading per route

Closes Phase 1 Plan 01-01
2026-05-14 09:11:50 +05:30
Diksha
4df1adfbe2 fix(backend): add missing matplotlib dependency for podcast composer
The podcast B-roll composer imports matplotlib for chart rendering, so adding it to backend requirements prevents import failures in fresh setups.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 22:28:19 +05:30
ajaysi
3f984e8d0c feat(podcast): add pre-estimate endpoint, enhance cost estimator with multi-model support, cleanup alpha pricing seeding
- Add POST /podcast/pre-estimate endpoint for cost estimation before analysis
- Enhance cost_estimator.py with multi-model support (gemini, audio, voice clone, image, video)
- Add detailed cost breakdown (llm, audio, media costs + per-phase breakdown)
- Remove redundant pricing seeding from init_alpha_subscription_tiers.py
- Add SSOT pricing via PricingService.initialize_default_pricing()
- Update TopicUrlInput tooltip to show estimate details
- Add debug logging for pricing seeding and pre-estimate
- Clean up verbose podcast mode debug logs in app.py
2026-05-06 15:29:12 +05:30
ajaysi
a7d2ef1c09 feat(podcast): add Get Trending Topics modal to podcast topic input
Frontend Changes:
- Added TrendingTopicsModal with tabs (Interest Chart, Regions, Related Topics, Related Queries)
- Reuses existing TrendsChart component from Research module
- Clickable chips for related topics/queries that populate the topic input
- Added 'Get Trending Topics' green button next to 'Enhance Topic With AI'
- Responsive layout: buttons stack on mobile, side-by-side on desktop
- Wired up modal state in CreateModal
- Backend endpoint and podcastApi method committed in prior push
2026-04-24 20:52:23 +05:30
ajaysi
fc47445181 fix(voice-clone): persist clone info in localStorage, auto-merge into project knobs, fix clone ID detection in CreateModal
- Move voice clone cache from module-level memory to localStorage
  so it survives page refresh and works across browser tabs
- VoiceAvatarPlaceholder now syncs clone result to localStorage
  immediately after creation (both design and clone paths)
- usePodcastProjectState auto-merges voice clone cache into project
  knobs when loading a project (fills gap for projects created
  before voice clone or when voice clone was created after)
- CreateModal now detects voice clone IDs by prefix (vc_*) not
  just by VOICE_CLONE_ID constant, fixing the mismatch where
  VoiceSelector passes the actual clone ID but CreateModal
  expected the placeholder ID
- AudioRegenerateModal is intentionally per-scene override and
  does not write back to knobs (by design)
- trends.py handler added for podcast topic trend analysis
2026-04-24 20:36:35 +05:30
ajaysi
d518365c87 fix: add missing budget_cap argument to create_project in update_project handler 2026-04-24 15:47:42 +05:30
ajaysi
ba94ee30bc feat(phase-4): UI/UX improvements for Podcast Maker Write phase
Frontend Changes:
- Add scene numbering badge (1/N) next to scene titles
- Add inline status chips (Complete, Audio, Image, Voice, Why Script)
- Professional AI-like gradient styling for all chips with shadows
- Remove Script Editor header and 'Why This Script Format?' collapsible
- Move Voice and Why Script info to per-scene chips
- Make scene section mobile-responsive (responsive layout, button sizing)
- Rename 'B-Roll Charts' to 'Podcast Charts' with accordion (collapsed by default)
- Add sceneIndex prop to SceneEditor for scene numbering
- Enhanced accessibility with keyboard navigation and focus states

Backend Changes:
- Audio handler improvements
- B-roll handler enhancements
- Script handler updates
- B-roll composer and service improvements
- Removed temporary broll_temp files

Technical:
- Full mobile responsiveness for scene cards
- Gradient chip styling: vibrant colors with white text and shadows
- Non-breaking approval/generation flow preserved
- TypeScript compatibility maintained
2026-04-24 15:44:09 +05:30
ajaysi
8b79099b15 Fix preflight NameError, clean up debug logs, remove redundant voice button, fix Tooltip warning 2026-04-22 16:10:27 +05:30
ajaysi
fbbfe81ed7 Fix voice clone: use absolute API URL for audio (not relative) so requests hit Render backend instead of Vercel SPA 2026-04-22 15:00:54 +05:30
ajaysi
d7319c981e Add debug logging to WaveSpeed speech generator for qwen3 voice clone 2026-04-22 13:19:32 +05:30
ajaysi
3c4965462a Add debug logging to asset serving to see file content 2026-04-22 12:56:48 +05:30
ajaysi
26ccb2f609 Add debug logging for voice clone preview audio bytes 2026-04-22 12:41:11 +05:30
ajaysi
cbd68fa43f Fix voice clone NotSupportedError and improve subscription services 2026-04-22 12:27:51 +05:30
ajaysi
641143a7d6 fix: use aiApiClient for voice clone/design (180s timeout instead of 60s) 2026-04-22 11:38:15 +05:30
ajaysi
dd7f8515a4 debug: add logging for asset path resolution 2026-04-22 11:23:24 +05:30
ajaysi
5e205d52cd fix: add comprehensive logging for voice clone debugging
- Backend: change logger.info to logger.warning for production logs
- Frontend: add console logs in brandAssets.ts createVoiceClone
- Frontend: add token auth and audio error logs in VoiceAvatarPlaceholder
- Log token fetching, authenticated URL, audio duration
2026-04-22 09:58:20 +05:30
ajaysi
b9f2123ce9 debug: add more logging for voice clone audio format detection 2026-04-22 09:34:44 +05:30
ajaysi
00f46ecbed fix: add preload=auto and key to Generated AI Voice Preview audio element 2026-04-22 09:06:00 +05:30
ajaysi
973dd501fe fix: PrimaryButton ref warning + research modal close race condition 2026-04-22 08:48:35 +05:30
ajaysi
efff72f4bd fix: create avatars subdirectory before saving avatar upload 2026-04-22 08:29:37 +05:30
ajaysi
913e59a0a8 fix: voice clone preview audio authentication + MIME type fixes
- Restore auth on assets_serving.py using get_current_user_with_query_token
  (supports ?token= query param for <audio> elements)
- Add proper MIME type detection on asset serving (fixes NotSupportedError)
- Use storage_paths for path resolution in assets_serving.py
- VoiceSelector: append auth token to preview URLs for /api/ endpoints
- VoiceAvatarPlaceholder: add authenticatedAudioUrl state with async token
  resolution so <audio> elements get ?token= query param
- TestPersonaModal: same auth token pattern for voice preview audio
2026-04-22 08:04:55 +05:30
ajaysi
02d13716f3 fix: voice clone preview audio not playing + avatar upload 500 + asset serving
- Fix voice clone preview saved as .wav regardless of actual format (MP3/WebM
  content from WaveSpeed was saved with .wav extension causing NotSupportedError)
- Add detect_audio_format() and ensure_audio_extension() to media_utils
- Fix assets_serving.py: use storage_paths for root resolution, add proper
  MIME types to FileResponse, add auth via query token for <audio> elements
- Fix assets_serving.py: add path traversal security check
- Fix step4_asset_routes.py: use get_user_workspace() instead of WORKSPACE_DIR,
  detect actual audio format before saving preview
- Fix get_db() in database.py: raise HTTPException(401) instead of raw Exception,
  catch engine creation failures with HTTPException(503)
- Fix avatar.py: add auth error handling, diagnostic logging for path resolution,
  graceful DB save degradation
2026-04-22 07:24:28 +05:30
ajaysi
c5d625945f fix: centralize ROOT_DIR resolution, fix workspace path on Render.com, cleanup legacy paths
- Upgrade utils/storage_paths.py with robust find_repo_root() (env var override + validation + fallback)
- Remove broken _find_root() from podcast/constants.py, import from storage_paths instead
- Fix ROOT_DIR resolving to backend/ instead of project root (caused avatar upload 500s on Render.com)
- Fix video_combination_service.py default output dir (was writing to data/media instead of workspace)
- Add deprecation comments to global data/media constants in media_utils.py
- Pass user_id through resolve_media_path for tenant-scoped podcast resolution
- Add ALWRITY_ROOT_DIR env var support for explicit production overrides
- Log warning when get_podcast_media_dir called without user_id
- Use OperationButton with cost display for scene action buttons
2026-04-22 06:28:45 +05:30
ajaysi
6e9c11744c fix: WebM/Opus audio duration shows zero - add durationchange listener and preload=auto 2026-04-22 06:10:15 +05:30
ajaysi
b1ca29f7f7 fix: workspace-aware media resolution + production-ready logging
- load_podcast_image_bytes now accepts user_id for workspace-aware resolution
- Video and avatar handlers pass user_id to image loading
- Strip JWT tokens from console logs (dev-only verbose logging)
- Guard debug logs behind NODE_ENV===development in SceneCard, useRenderQueue, SubscriptionContext, mediaCache
- Add devLogger utility
2026-04-21 21:19:40 +05:30
ajaysi
91b2f996fd feat: voice clone audio generation + podcast workspace architecture
- Voice clone integration: When user selects voice clone in Write phase,
  backend uses their uploaded voice sample + scene script text to generate
  audio via qwen3/minimax/cosyvoice voice clone APIs
- Multi-tenant workspace storage: All podcast assets (audio, video, images,
  charts) now use workspace-specific directories per user
- Chart preview improvements: Card-based B-Roll charts UI with thumbnails,
  takeaway text, and action buttons; public endpoint for image serving
- Voice clone caching: In-memory LRU cache for voice samples (avoids
  re-downloading per scene); frontend caches voice clone metadata
- Thread pool for voice clone: Audio generation uses ThreadPoolExecutor to
  avoid blocking the FastAPI event loop
- Auto-detect voice clone IDs (vc_*, MY_VOICE_CLONE) to route correctly
- DB fallback for voice sample URL: Fetches from ContentAsset if not passed
- Fixed API URL resolution for chart previews
- Fixed GlassyCard DOM warnings for motion props
- Fixed ScriptGenerationProgressView syntax error
- Fixed usePodcastWorkflow scriptData reference
2026-04-21 19:38:50 +05:30
ajaysi
7637babd7d Add detailed logging for project update debugging 2026-04-20 16:01:13 +05:30