This commit is contained in:
Flatlogic Bot 2026-03-02 04:55:34 +00:00
parent 4220a7a231
commit 6c4fe526f8
5 changed files with 58 additions and 50 deletions

View File

@ -154,7 +154,10 @@ async function awaitResponse(aiRequestId, options = {}) {
const interval = Math.max(Number(options.interval ?? 5), 1); const interval = Math.max(Number(options.interval ?? 5), 1);
const deadline = Date.now() + Math.max(timeout, interval) * 1000; const deadline = Date.now() + Math.max(timeout, interval) * 1000;
while (true) { let isComplete = false;
let finalResponse = null;
while (!isComplete && Date.now() < deadline) {
const statusResp = await fetchStatus(aiRequestId, { const statusResp = await fetchStatus(aiRequestId, {
headers: options.headers, headers: options.headers,
timeout: options.timeout_per_call, timeout: options.timeout_per_call,
@ -165,14 +168,15 @@ async function awaitResponse(aiRequestId, options = {}) {
const data = statusResp.data || {}; const data = statusResp.data || {};
if (data && typeof data === "object") { if (data && typeof data === "object") {
if (data.status === "success") { if (data.status === "success") {
return { isComplete = true;
finalResponse = {
success: true, success: true,
status: 200, status: 200,
data: data.response || data, data: data.response || data,
}; };
} } else if (data.status === "failed") {
if (data.status === "failed") { isComplete = true;
return { finalResponse = {
success: false, success: false,
status: 500, status: 500,
error: String(data.error || "AI request failed"), error: String(data.error || "AI request failed"),
@ -181,19 +185,24 @@ async function awaitResponse(aiRequestId, options = {}) {
} }
} }
} else { } else {
return statusResp; isComplete = true;
finalResponse = statusResp;
} }
if (Date.now() >= deadline) { if (!isComplete) {
return { await sleep(interval * 1000);
success: false,
error: "timeout",
message: "Timed out waiting for AI response.",
};
} }
await sleep(interval * 1000);
} }
if (!finalResponse) {
return {
success: false,
error: "timeout",
message: "Timed out waiting for AI response.",
};
}
return finalResponse;
} }
function extractText(response) { function extractText(response) {
@ -306,7 +315,7 @@ function buildUrl(pathValue, baseUrl) {
} }
function resolveStatusPath(aiRequestId, cfg) { function resolveStatusPath(aiRequestId, cfg) {
const basePath = (cfg.responsesPath || "").replace(/\/+$/, ""); const basePath = (cfg.responsesPath || "").replace(///+$/, "");
if (!basePath) { if (!basePath) {
return `/ai-request/${encodeURIComponent(String(aiRequestId))}/status`; return `/ai-request/${encodeURIComponent(String(aiRequestId))}/status`;
} }

View File

@ -4,7 +4,7 @@ import { MenuAsideItem } from './interfaces'
const menuAside: MenuAsideItem[] = [ const menuAside: MenuAsideItem[] = [
{ {
href: '/studio', href: '/studio',
label: 'Music Studio', label: 'AI Music Generator Creator',
icon: icon.mdiMusicNotePlus, icon: icon.mdiMusicNotePlus,
}, },
{ {

View File

@ -106,7 +106,7 @@ const Dashboard = () => {
main> main>
<BaseButton <BaseButton
href="/studio" href="/studio"
label="Open Music Studio" label="Open AI Music Generator"
icon={icon.mdiMusicNotePlus} icon={icon.mdiMusicNotePlus}
color="info" color="info"
/> />

View File

@ -10,12 +10,12 @@ import { mdiMusic, mdiAccountKey, mdiPlayCircle, mdiCloudDownload, mdiAutoFix }
import BaseIcon from '../components/BaseIcon'; import BaseIcon from '../components/BaseIcon';
export default function Home() { export default function Home() {
const title = 'AI Music Studio Pro'; const title = 'AI Music Generator Creator Pro';
return ( return (
<div className="bg-slate-950 text-white min-h-screen font-sans selection:bg-emerald-500/30"> <div className="bg-slate-950 text-white min-h-screen font-sans selection:bg-emerald-500/30">
<Head> <Head>
<title>{getPageTitle('Professional AI Music Generator')}</title> <title>{getPageTitle('AI Music Generator Creator')}</title>
</Head> </Head>
{/* Hero Section */} {/* Hero Section */}
@ -35,7 +35,7 @@ export default function Home() {
</div> </div>
<h1 className="text-5xl md:text-7xl font-extrabold tracking-tight mb-6 bg-clip-text text-transparent bg-gradient-to-b from-white to-slate-400"> <h1 className="text-5xl md:text-7xl font-extrabold tracking-tight mb-6 bg-clip-text text-transparent bg-gradient-to-b from-white to-slate-400">
Professional AI <br /> Music Creator Professional AI <br /> Music Generator
</h1> </h1>
<p className="max-w-2xl text-lg md:text-xl text-slate-400 mb-10 leading-relaxed"> <p className="max-w-2xl text-lg md:text-xl text-slate-400 mb-10 leading-relaxed">

View File

@ -17,7 +17,6 @@ import { SelectField } from '../../components/SelectField';
import BaseIcon from '../../components/BaseIcon'; import BaseIcon from '../../components/BaseIcon';
import FormField from '../../components/FormField'; import FormField from '../../components/FormField';
import NotificationBar from '../../components/NotificationBar'; import NotificationBar from '../../components/NotificationBar';
import axios from 'axios';
const StudioPage = () => { const StudioPage = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -36,26 +35,26 @@ const StudioPage = () => {
const initialValues = { const initialValues = {
song_title: '', song_title: '',
generation_mode: 'manual_lyrics', generation_mode: 'auto_lyrics',
lyrics_text: '', lyrics_text: '',
languageId: '', language: '',
styleId: '', style: '',
eraId: '', era: '',
voiceId: '', voice: '',
}; };
const validate = (values: any) => { const validate = (values: any) => {
const errors: any = {}; const errors: any = {};
if (!values.song_title) errors.song_title = 'Required'; if (!values.song_title) errors.song_title = 'Required';
if (values.generation_mode === 'manual_lyrics' && !values.lyrics_text) errors.lyrics_text = 'Required'; if (values.generation_mode === 'manual_lyrics' && !values.lyrics_text) errors.lyrics_text = 'Required';
if (!values.languageId) errors.languageId = 'Required'; if (!values.language) errors.language = 'Required';
if (!values.styleId) errors.styleId = 'Required'; if (!values.style) errors.style = 'Required';
if (!values.eraId) errors.eraId = 'Required'; if (!values.era) errors.era = 'Required';
return errors; return errors;
}; };
const handleGenerateLyrics = async (values: any, setFieldValue: any) => { const handleGenerateLyrics = async (values: any, setFieldValue: any) => {
if (!values.song_title || !values.styleId || !values.eraId) { if (!values.song_title || !values.style || !values.era) {
alert('Please provide a title, style, and era first.'); alert('Please provide a title, style, and era first.');
return; return;
} }
@ -81,9 +80,9 @@ const StudioPage = () => {
song_title: values.song_title, song_title: values.song_title,
generation_mode: values.generation_mode, generation_mode: values.generation_mode,
lyrics_text: values.lyrics_text, lyrics_text: values.lyrics_text,
languageId: values.languageId, language: values.language,
styleId: values.styleId, style: values.style,
eraId: values.eraId, era: values.era,
status: 'queued', status: 'queued',
requested_at: new Date().toISOString(), requested_at: new Date().toISOString(),
})).unwrap(); })).unwrap();
@ -91,7 +90,7 @@ const StudioPage = () => {
const songId = songResult.id || songResult.data?.id; const songId = songResult.id || songResult.data?.id;
await dispatch(createJob({ await dispatch(createJob({
songId: songId, song: songId,
job_type: 'music_composition', job_type: 'music_composition',
status: 'queued', status: 'queued',
progress_percent: 0, progress_percent: 0,
@ -103,7 +102,7 @@ const StudioPage = () => {
setTimeout(() => setGenerationSuccess(false), 5000); setTimeout(() => setGenerationSuccess(false), 5000);
} catch (error) { } catch (error) {
console.error('Failed to generate song:', error); console.error('Failed to generate song:', error);
alert('Failed to start generation. Please check the logs.'); alert('Failed to start generation. Please check the permissions and logs.');
} finally { } finally {
setIsGenerating(false); setIsGenerating(false);
} }
@ -150,7 +149,7 @@ const StudioPage = () => {
return ( return (
<> <>
<HeadInstance> <HeadInstance>
<title>{getPageTitle('AI Music Studio')}</title> <title>{getPageTitle('AI Music Generator Creator')}</title>
</HeadInstance> </HeadInstance>
<audio <audio
@ -160,7 +159,7 @@ const StudioPage = () => {
/> />
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiMusic} title="AI Music Generation Studio" main> <SectionTitleLineWithButton icon={mdiMusic} title="AI Music Generator Creator" main>
<BaseButton <BaseButton
href="/songs/songs-list" href="/songs/songs-list"
label="Library" label="Library"
@ -201,41 +200,41 @@ const StudioPage = () => {
name="generation_mode" name="generation_mode"
className="w-full bg-slate-800 border-slate-700 text-white rounded-lg p-3 focus:ring-emerald-500 border focus:border-emerald-500 outline-none transition-all" className="w-full bg-slate-800 border-slate-700 text-white rounded-lg p-3 focus:ring-emerald-500 border focus:border-emerald-500 outline-none transition-all"
> >
<option value="manual_lyrics">Manual Lyrics</option>
<option value="auto_lyrics">AI Auto-Lyrics (Full Song)</option> <option value="auto_lyrics">AI Auto-Lyrics (Full Song)</option>
<option value="manual_lyrics">Manual Lyrics</option>
<option value="remix_reference">Remix Reference</option> <option value="remix_reference">Remix Reference</option>
</Field> </Field>
</FormField> </FormField>
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
<FormField label="Language" error={errors.languageId && touched.languageId}> <FormField label="Language" error={errors.language && touched.language}>
<SelectField <SelectField
itemRef="languages" itemRef="languages"
showField="language_name" showField="language_name"
field={{ name: 'languageId', value: values.languageId }} field={{ name: 'language', value: values.language }}
form={{ setFieldValue }} form={{ setFieldValue }}
options={{ id: 'languageId' }} options={{ id: 'language' }}
/> />
</FormField> </FormField>
<FormField label="Era" error={errors.eraId && touched.eraId}> <FormField label="Era" error={errors.era && touched.era}>
<SelectField <SelectField
itemRef="eras" itemRef="eras"
showField="era_name" showField="era_name"
field={{ name: 'eraId', value: values.eraId }} field={{ name: 'era', value: values.era }}
form={{ setFieldValue }} form={{ setFieldValue }}
options={{ id: 'eraId' }} options={{ id: 'era' }}
/> />
</FormField> </FormField>
<FormField label="Style" error={errors.styleId && touched.styleId}> <FormField label="Style" error={errors.style && touched.style}>
<SelectField <SelectField
itemRef="music_styles" itemRef="music_styles"
showField="style_name" showField="style_name"
field={{ name: 'styleId', value: values.styleId }} field={{ name: 'style', value: values.style }}
form={{ setFieldValue }} form={{ setFieldValue }}
options={{ id: 'styleId' }} options={{ id: 'style' }}
/> />
</FormField> </FormField>
</div> </div>
@ -244,9 +243,9 @@ const StudioPage = () => {
<SelectField <SelectField
itemRef="ai_voices" itemRef="ai_voices"
showField="voice_name" showField="voice_name"
field={{ name: 'voiceId', value: values.voiceId }} field={{ name: 'voice', value: values.voice }}
form={{ setFieldValue }} form={{ setFieldValue }}
options={{ id: 'voiceId' }} options={{ id: 'voice' }}
/> />
</FormField> </FormField>