Files
ALwrity/frontend/src/components/PodcastMaker/PodcastDashboard/utils.ts
ajaysi 63bb937796 feat: podcast demo mode with ALWRITY_ENABLED_FEATURES support
- Add ALWRITY_ENABLED_FEATURES env var for feature gating
- Podcast-only mode: skip LLM bootstrap, scheduler, persona services
- Enhance video generation prompt with scene context, analysis, narration
- Add voice cloning support via custom_voice_id in WaveSpeed
- Add text-to-speech for research results (browser speechSynthesis)
- Fix render queue to sync images from script phase
- Add WaveSpeed LLM pricing (gpt-oss-120b)
- Fix podcast bible generation error handling
- Refactor RouterManager for feature-based router loading
2026-04-03 06:59:59 +05:30

101 lines
3.0 KiB
TypeScript

import { ResearchConfig, DateRange } from "../../../services/blogWriterApi";
import { CreateProjectPayload, Knobs } from "../types";
export const DEFAULT_KNOBS: Knobs = {
voice_emotion: "neutral",
voice_speed: 1,
voice_id: "Wise_Woman",
custom_voice_id: undefined,
resolution: "720p",
scene_length_target: 45,
sample_rate: 24000,
bitrate: "standard",
};
export const allowedDateRanges: DateRange[] = [
"last_week",
"last_month",
"last_3_months",
"last_6_months",
"last_year",
"all_time",
];
export const sanitizeExaConfig = (
exa?: CreateProjectPayload["knobs"] & any & { exa_suggested_config?: any } | any
): ResearchConfig | undefined => {
if (!exa) return undefined;
const cfg = exa as {
exa_search_type?: "auto" | "keyword" | "neural";
exa_category?: string;
exa_include_domains?: string[];
exa_exclude_domains?: string[];
max_sources?: number;
include_statistics?: boolean;
date_range?: string;
};
const searchType: ResearchConfig["exa_search_type"] =
cfg.exa_search_type && ["auto", "keyword", "neural"].includes(cfg.exa_search_type)
? cfg.exa_search_type
: undefined;
const dateRange: DateRange | undefined = cfg.date_range && allowedDateRanges.includes(cfg.date_range as DateRange)
? (cfg.date_range as DateRange)
: undefined;
return {
provider: "exa",
exa_search_type: searchType,
exa_category: cfg.exa_category,
exa_include_domains: cfg.exa_include_domains,
exa_exclude_domains: cfg.exa_exclude_domains,
max_sources: cfg.max_sources,
include_statistics: cfg.include_statistics,
date_range: dateRange,
};
};
export const announceError = (
setAnnouncement: (msg: string) => void,
setAnnouncementSeverity?: (severity: "info" | "error" | "success") => void,
error?: unknown
) => {
let message = "Unexpected error occurred. Please try again.";
if (error instanceof Error) {
message = error.message;
// Simplify common error messages
if (message.includes("RESOURCE_EXHAUSTED") || message.includes("quota")) {
message = "API quota exceeded. Please check your API keys or try again later.";
} else if (message.includes("All LLM providers failed")) {
message = "AI service temporarily unavailable. Please try again later.";
} else if (message.includes("No LLM API keys configured")) {
message = "API keys not configured. Please contact support.";
} else if (message.includes("RESOURCE_EXHAUSTED")) {
message = "API quota exceeded. Please check your subscription or try again later.";
} else if (message.length > 100) {
message = "An error occurred during analysis. Please try again.";
}
}
setAnnouncement(message);
if (setAnnouncementSeverity) {
setAnnouncementSeverity("error");
}
};
export const getStepLabel = (step: string | null): string => {
switch (step) {
case "analysis":
return "Analysis";
case "research":
return "Research";
case "script":
return "Script Editing";
case "render":
return "Rendering";
default:
return "Unknown";
}
};