diff --git a/backend/api/podcast/handlers/research.py b/backend/api/podcast/handlers/research.py index 3155702e..143364a0 100644 --- a/backend/api/podcast/handlers/research.py +++ b/backend/api/podcast/handlers/research.py @@ -218,6 +218,9 @@ Listener CTA: {request.analysis.get('listener_cta', 'N/A')} summary = "" key_insights = [] + expert_quotes = [] + listener_cta_suggestions = [] + mapped_angles = [] if raw_content and sources: logger.warning(f"[Podcast Research] Extracting insights from {len(sources)} sources for user {user_id}") @@ -337,13 +340,22 @@ QUALITY STANDARDS: try: summary = data.get("summary", "") key_insights = [PodcastResearchInsight(**insight) for insight in data.get("key_insights", [])] + expert_quotes = data.get("expert_quotes", []) + listener_cta_suggestions = data.get("listener_cta_suggestions", []) + mapped_angles = data.get("mapped_angles", []) except Exception as insight_err: logger.warning(f"[Podcast Research] Failed to parse insights: {insight_err}. Data keys: {list(data.keys()) if isinstance(data, dict) else 'not a dict'}") summary = data.get("summary", "") if isinstance(data, dict) else "" key_insights = [] + expert_quotes = data.get("expert_quotes", []) if isinstance(data, dict) else [] + listener_cta_suggestions = data.get("listener_cta_suggestions", []) if isinstance(data, dict) else [] + mapped_angles = data.get("mapped_angles", []) if isinstance(data, dict) else [] else: summary = "" key_insights = [] + expert_quotes = [] + listener_cta_suggestions = [] + mapped_angles = [] except HTTPException: raise except Exception as exc: @@ -423,5 +435,8 @@ QUALITY STANDARDS: search_type=result.get("search_type") if isinstance(result, dict) else None, provider=result.get("provider", "exa") if isinstance(result, dict) else "exa", content=raw_content, + mapped_angles=mapped_angles, + expert_quotes=expert_quotes, + listener_cta_suggestions=listener_cta_suggestions, estimate=estimate, ) diff --git a/frontend/src/components/PodcastMaker/PodcastDashboard/ResearchSummary.tsx b/frontend/src/components/PodcastMaker/PodcastDashboard/ResearchSummary.tsx index 8b25ccd6..5881268c 100644 --- a/frontend/src/components/PodcastMaker/PodcastDashboard/ResearchSummary.tsx +++ b/frontend/src/components/PodcastMaker/PodcastDashboard/ResearchSummary.tsx @@ -285,6 +285,78 @@ export const ResearchSummary: React.FC = ({ ) )} + {/* Expert Quotes */} + + + Expert Quotes + + {research.expertQuotes && research.expertQuotes.length > 0 ? ( + + {research.expertQuotes.slice(0, 4).map((quote, idx) => ( + + + “{quote.quote}” + + + Source S{quote.source_index} + + + ))} + + ) : ( + + No expert quotes extracted yet. + + )} + + + {/* Listener CTAs */} + + + Listener CTAs + + {research.listenerCta && research.listenerCta.length > 0 ? ( + + {research.listenerCta.slice(0, 4).map((cta, idx) => ( + + + {cta} + + + ))} + + ) : ( + + No listener CTAs suggested yet. + + )} + + + {/* Mapped Angles */} + + + Mapped Angles + + {research.mappedAngles && research.mappedAngles.length > 0 ? ( + + {research.mappedAngles.slice(0, 4).map((angle, idx) => ( + + + {angle.title || `Angle ${idx + 1}`} + + + {angle.why || "No rationale provided."} + + + ))} + + ) : ( + + No mapped angles available yet. + + )} + + {/* Search Queries Used */} {research.searchQueries && research.searchQueries.length > 0 && ( diff --git a/frontend/src/services/podcastApi.ts b/frontend/src/services/podcastApi.ts index 2978e96e..a86b1b28 100644 --- a/frontend/src/services/podcastApi.ts +++ b/frontend/src/services/podcastApi.ts @@ -198,6 +198,8 @@ const mapExaResearchResponse = (response: any): Research => { source_indices: insight.source_indices || [] })); + // Backend keys must match PodcastExaResearchResponse exactly: + // expert_quotes, listener_cta_suggestions, mapped_angles const expertQuotes = (response.expert_quotes || []).map((eq: any) => ({ quote: eq.quote || eq.text || "", source_index: eq.source_index ?? 0