Fix production issues: add matplotlib dep, fix get_db calls, resolve ESLint
- Add matplotlib>=3.7.0 to requirements-podcast.txt (B-roll requires it) - Fix research.py and exa_provider.py using get_session_for_user() instead of broken Depends(get_db) - Fix BrollInfoPanel.tsx: call useScriptEditor hook unconditionally - Add debug logging to avatar endpoint for troubleshooting
This commit is contained in:
@@ -86,6 +86,8 @@ async def get_latest_avatar(
|
|||||||
try:
|
try:
|
||||||
user_id = _extract_user_id(current_user)
|
user_id = _extract_user_id(current_user)
|
||||||
|
|
||||||
|
logger.info(f"[latest-avatar] Looking for avatar for user_id: {user_id}")
|
||||||
|
|
||||||
# Search for assets that are either:
|
# Search for assets that are either:
|
||||||
# 1. Saved with source_module=BRAND_AVATAR_GENERATOR (new)
|
# 1. Saved with source_module=BRAND_AVATAR_GENERATOR (new)
|
||||||
# 2. Saved with source_module=STORY_WRITER but have metadata category='brand_avatar' (legacy)
|
# 2. Saved with source_module=STORY_WRITER but have metadata category='brand_avatar' (legacy)
|
||||||
@@ -100,6 +102,8 @@ async def get_latest_avatar(
|
|||||||
])
|
])
|
||||||
).order_by(desc(ContentAsset.created_at)).limit(50).all()
|
).order_by(desc(ContentAsset.created_at)).limit(50).all()
|
||||||
|
|
||||||
|
logger.info(f"[latest-avatar] Found {len(candidates)} candidate(s)")
|
||||||
|
|
||||||
asset = None
|
asset = None
|
||||||
for candidate in candidates:
|
for candidate in candidates:
|
||||||
# Check for direct match (new assets)
|
# Check for direct match (new assets)
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ def _build_research_cost_estimate(
|
|||||||
raw_content: str,
|
raw_content: str,
|
||||||
sources_count: int,
|
sources_count: int,
|
||||||
provider_result: Dict[str, Any],
|
provider_result: Dict[str, Any],
|
||||||
|
user_id: str = "default",
|
||||||
) -> PodcastCostEst:
|
) -> PodcastCostEst:
|
||||||
# Fallback defaults mirror current catalog defaults.
|
# Fallback defaults mirror current catalog defaults.
|
||||||
exa_per_request = 0.005
|
exa_per_request = 0.005
|
||||||
@@ -70,7 +71,9 @@ def _build_research_cost_estimate(
|
|||||||
gemini_out_token = 0.0000006
|
gemini_out_token = 0.0000006
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db = next(get_db())
|
from services.database import get_session_for_user
|
||||||
|
db = get_session_for_user(user_id)
|
||||||
|
if db:
|
||||||
try:
|
try:
|
||||||
pricing_service = PricingService(db)
|
pricing_service = PricingService(db)
|
||||||
exa_per_request = _get_price_from_catalog(
|
exa_per_request = _get_price_from_catalog(
|
||||||
@@ -431,6 +434,7 @@ QUALITY STANDARDS:
|
|||||||
raw_content=raw_content,
|
raw_content=raw_content,
|
||||||
sources_count=len(sources_payload),
|
sources_count=len(sources_payload),
|
||||||
provider_result=result if isinstance(result, dict) else {},
|
provider_result=result if isinstance(result, dict) else {},
|
||||||
|
user_id=user_id,
|
||||||
),
|
),
|
||||||
search_type=result.get("search_type") if isinstance(result, dict) else None,
|
search_type=result.get("search_type") if isinstance(result, dict) else None,
|
||||||
provider=result.get("provider", "exa") if isinstance(result, dict) else "exa",
|
provider=result.get("provider", "exa") if isinstance(result, dict) else "exa",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ pandas>=2.0.0
|
|||||||
|
|
||||||
# Image/media for podcast
|
# Image/media for podcast
|
||||||
Pillow>=10.0.0
|
Pillow>=10.0.0
|
||||||
|
matplotlib>=3.7.0
|
||||||
huggingface_hub>=1.1.4
|
huggingface_hub>=1.1.4
|
||||||
|
|
||||||
# TTS for podcast
|
# TTS for podcast
|
||||||
|
|||||||
@@ -314,11 +314,14 @@ class ExaResearchProvider(BaseProvider):
|
|||||||
|
|
||||||
def track_exa_usage(self, user_id: str, cost: float):
|
def track_exa_usage(self, user_id: str, cost: float):
|
||||||
"""Track Exa API usage after successful call."""
|
"""Track Exa API usage after successful call."""
|
||||||
from services.database import get_db
|
from services.database import get_session_for_user
|
||||||
from services.subscription import PricingService
|
from services.subscription import PricingService
|
||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
|
|
||||||
db = next(get_db())
|
db = get_session_for_user(user_id)
|
||||||
|
if not db:
|
||||||
|
logger.warning(f"[track_exa_usage] Could not get DB session for user {user_id}")
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
pricing_service = PricingService(db)
|
pricing_service = PricingService(db)
|
||||||
current_period = pricing_service.get_current_billing_period(user_id)
|
current_period = pricing_service.get_current_billing_period(user_id)
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import numpy as np
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
import matplotlib
|
import matplotlib
|
||||||
matplotlib.use("Agg")
|
matplotlib.use("Agg")
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.patches as mpatches
|
import matplotlib.patches as mpatches
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
|
||||||
from moviepy import (
|
from moviepy import (
|
||||||
VideoFileClip, ImageClip, CompositeVideoClip,
|
VideoFileClip, ImageClip, CompositeVideoClip,
|
||||||
concatenate_videoclips,
|
concatenate_videoclips,
|
||||||
|
|||||||
@@ -14,27 +14,22 @@ interface BrollInfoPanelProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const BrollInfoPanel: React.FC<BrollInfoPanelProps> = (props) => {
|
export const BrollInfoPanel: React.FC<BrollInfoPanelProps> = (props) => {
|
||||||
let contextValue: ReturnType<typeof useScriptEditor> | null = null;
|
const ctx = useScriptEditor();
|
||||||
try {
|
|
||||||
contextValue = useScriptEditor();
|
|
||||||
} catch {
|
|
||||||
contextValue = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
activeScript,
|
activeScript: ctxActiveScript,
|
||||||
generatingChartId,
|
generatingChartId: ctxGeneratingChartId,
|
||||||
generateChartPreviews,
|
generateChartPreviews: ctxGenerateChartPreviews,
|
||||||
regenerateChart,
|
regenerateChart: ctxRegenerateChart,
|
||||||
removeChart,
|
removeChart: ctxRemoveChart,
|
||||||
scenesWithCharts
|
scenesWithCharts: ctxScenesWithCharts
|
||||||
} = contextValue ?? {};
|
} = ctx;
|
||||||
|
|
||||||
const resolvedActiveScript = props.activeScript ?? activeScript;
|
const resolvedActiveScript = props.activeScript ?? ctxActiveScript;
|
||||||
const resolvedGeneratingChartId = props.generatingChartId ?? generatingChartId;
|
const resolvedGeneratingChartId = props.generatingChartId ?? ctxGeneratingChartId;
|
||||||
const resolvedGenerateChartPreviews = props.generateChartPreviews ?? generateChartPreviews;
|
const resolvedGenerateChartPreviews = props.generateChartPreviews ?? ctxGenerateChartPreviews;
|
||||||
const resolvedRegenerateChart = props.regenerateChart ?? regenerateChart;
|
const resolvedRegenerateChart = props.regenerateChart ?? ctxRegenerateChart;
|
||||||
const resolvedRemoveChart = props.removeChart ?? removeChart;
|
const resolvedRemoveChart = props.removeChart ?? ctxRemoveChart;
|
||||||
|
|
||||||
if (!resolvedActiveScript || resolvedActiveScript.scenes.length === 0) {
|
if (!resolvedActiveScript || resolvedActiveScript.scenes.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -42,7 +37,7 @@ export const BrollInfoPanel: React.FC<BrollInfoPanelProps> = (props) => {
|
|||||||
|
|
||||||
const scenesWithData = resolvedActiveScript.scenes.filter(s => s.chart_data && Object.keys(s.chart_data).length > 0);
|
const scenesWithData = resolvedActiveScript.scenes.filter(s => s.chart_data && Object.keys(s.chart_data).length > 0);
|
||||||
const hasChartData = scenesWithData.length > 0;
|
const hasChartData = scenesWithData.length > 0;
|
||||||
const resolvedScenesWithCharts = props.scenesWithCharts ?? scenesWithCharts ?? scenesWithData.length;
|
const resolvedScenesWithCharts = props.scenesWithCharts ?? ctxScenesWithCharts ?? scenesWithData.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
|
|||||||
Reference in New Issue
Block a user