Fix review issues: lyrics polling, validation, undici fetch, retry, timeout, throttle, payload helper
This commit is contained in:
Vendored
+97
-127
@@ -37,6 +37,8 @@ exports.ToolHandlers = void 0;
|
||||
const schemas = __importStar(require("./schemas"));
|
||||
const ASYNC_POLLING_PATHS = {
|
||||
'suno_generate_music': '/generate/record-info?taskId=',
|
||||
'suno_generate_lyrics': '/lyrics/record-info?taskId=',
|
||||
'suno_generate_sounds': '/generate/record-info?taskId=',
|
||||
'suno_extend_music': '/generate/record-info?taskId=',
|
||||
'suno_replace_section': '/generate/record-info?taskId=',
|
||||
'suno_upload_and_cover': '/generate/record-info?taskId=',
|
||||
@@ -49,9 +51,46 @@ const ASYNC_POLLING_PATHS = {
|
||||
'suno_create_video': '/generate/video-info?taskId=',
|
||||
'suno_create_cover': '/generate/cover-info?taskId=',
|
||||
'suno_convert_to_wav': '/generate/wav-info?taskId=',
|
||||
'suno_generate_sounds': '/generate/record-info?taskId=',
|
||||
};
|
||||
function copyDefined(source, target, keys) {
|
||||
for (const key of keys) {
|
||||
const value = source[key];
|
||||
if (value !== undefined) {
|
||||
target[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
function isLyricsData(data) {
|
||||
return data.type === 'LYRICS';
|
||||
}
|
||||
function formatLyricsResult(data) {
|
||||
const status = data.status;
|
||||
if (status !== 'SUCCESS') {
|
||||
return JSON.stringify({
|
||||
taskId: data.taskId,
|
||||
status,
|
||||
errorCode: data.errorCode,
|
||||
errorMessage: data.errorMessage,
|
||||
}, null, 2);
|
||||
}
|
||||
const variants = data.response?.data ?? [];
|
||||
return JSON.stringify({
|
||||
taskId: data.taskId,
|
||||
status,
|
||||
type: data.type,
|
||||
variants: variants.map((v, index) => ({
|
||||
index: index + 1,
|
||||
title: v.title,
|
||||
text: v.text,
|
||||
status: v.status,
|
||||
errorMessage: v.errorMessage,
|
||||
})),
|
||||
}, null, 2);
|
||||
}
|
||||
function formatTaskResult(data) {
|
||||
if (isLyricsData(data)) {
|
||||
return formatLyricsResult(data);
|
||||
}
|
||||
const status = data.status;
|
||||
if (status !== 'SUCCESS') {
|
||||
return JSON.stringify({
|
||||
@@ -62,7 +101,7 @@ function formatTaskResult(data) {
|
||||
}, null, 2);
|
||||
}
|
||||
const response = data.response;
|
||||
const tracks = response?.data ?? response?.sunoData ?? [];
|
||||
const tracks = (response?.data ?? response?.sunoData ?? []);
|
||||
return JSON.stringify({
|
||||
taskId: data.taskId,
|
||||
status,
|
||||
@@ -102,40 +141,32 @@ class ToolHandlers {
|
||||
case 'suno_generate_music': {
|
||||
const input = schemas.GenerateMusicSchema.parse(args);
|
||||
const payload = {
|
||||
prompt: input.prompt,
|
||||
customMode: input.customMode,
|
||||
instrumental: input.instrumental,
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
if (input.negativeTags !== undefined)
|
||||
payload.negativeTags = input.negativeTags;
|
||||
if (input.vocalGender !== undefined)
|
||||
payload.vocalGender = input.vocalGender;
|
||||
if (input.styleWeight !== undefined)
|
||||
payload.styleWeight = input.styleWeight;
|
||||
if (input.weirdnessConstraint !== undefined)
|
||||
payload.weirdnessConstraint = input.weirdnessConstraint;
|
||||
if (input.audioWeight !== undefined)
|
||||
payload.audioWeight = input.audioWeight;
|
||||
if (input.personaId !== undefined)
|
||||
payload.personaId = input.personaId;
|
||||
if (input.personaModel !== undefined)
|
||||
payload.personaModel = input.personaModel;
|
||||
copyDefined(input, payload, [
|
||||
'prompt',
|
||||
'style',
|
||||
'title',
|
||||
'negativeTags',
|
||||
'vocalGender',
|
||||
'styleWeight',
|
||||
'weirdnessConstraint',
|
||||
'audioWeight',
|
||||
'personaId',
|
||||
'personaModel',
|
||||
]);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate', payload);
|
||||
break;
|
||||
}
|
||||
case 'suno_generate_lyrics': {
|
||||
const input = schemas.GenerateLyricsSchema.parse(args);
|
||||
const result = await this.client.post('/lyrics', {
|
||||
resultText = await runAsyncTask(this.client, name, '/lyrics', {
|
||||
prompt: input.prompt,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
});
|
||||
resultText = JSON.stringify({ taskId: result.data.taskId, status: 'PENDING' }, null, 2);
|
||||
break;
|
||||
}
|
||||
case 'suno_generate_sounds': {
|
||||
@@ -145,14 +176,7 @@ class ToolHandlers {
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.soundLoop !== undefined)
|
||||
payload.soundLoop = input.soundLoop;
|
||||
if (input.soundTempo !== undefined)
|
||||
payload.soundTempo = input.soundTempo;
|
||||
if (input.soundKey !== undefined)
|
||||
payload.soundKey = input.soundKey;
|
||||
if (input.grabLyrics !== undefined)
|
||||
payload.grabLyrics = input.grabLyrics;
|
||||
copyDefined(input, payload, ['soundLoop', 'soundTempo', 'soundKey', 'grabLyrics']);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/sounds', payload);
|
||||
break;
|
||||
}
|
||||
@@ -164,28 +188,19 @@ class ToolHandlers {
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.prompt !== undefined)
|
||||
payload.prompt = input.prompt;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
if (input.continueAt !== undefined)
|
||||
payload.continueAt = input.continueAt;
|
||||
if (input.negativeTags !== undefined)
|
||||
payload.negativeTags = input.negativeTags;
|
||||
if (input.vocalGender !== undefined)
|
||||
payload.vocalGender = input.vocalGender;
|
||||
if (input.styleWeight !== undefined)
|
||||
payload.styleWeight = input.styleWeight;
|
||||
if (input.weirdnessConstraint !== undefined)
|
||||
payload.weirdnessConstraint = input.weirdnessConstraint;
|
||||
if (input.audioWeight !== undefined)
|
||||
payload.audioWeight = input.audioWeight;
|
||||
if (input.personaId !== undefined)
|
||||
payload.personaId = input.personaId;
|
||||
if (input.personaModel !== undefined)
|
||||
payload.personaModel = input.personaModel;
|
||||
copyDefined(input, payload, [
|
||||
'prompt',
|
||||
'style',
|
||||
'title',
|
||||
'continueAt',
|
||||
'negativeTags',
|
||||
'vocalGender',
|
||||
'styleWeight',
|
||||
'weirdnessConstraint',
|
||||
'audioWeight',
|
||||
'personaId',
|
||||
'personaModel',
|
||||
]);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/extend', payload);
|
||||
break;
|
||||
}
|
||||
@@ -199,16 +214,7 @@ class ToolHandlers {
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.replaceAudioUrl !== undefined)
|
||||
payload.replaceAudioUrl = input.replaceAudioUrl;
|
||||
if (input.customMode !== undefined)
|
||||
payload.customMode = input.customMode;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
if (input.instrumental !== undefined)
|
||||
payload.instrumental = input.instrumental;
|
||||
copyDefined(input, payload, ['replaceAudioUrl', 'customMode', 'style', 'title', 'instrumental']);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/replace-section', payload);
|
||||
break;
|
||||
}
|
||||
@@ -216,16 +222,10 @@ class ToolHandlers {
|
||||
const input = schemas.AddVocalsSchema.parse(args);
|
||||
const payload = {
|
||||
audioId: input.audioId,
|
||||
prompt: input.prompt,
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.customMode !== undefined)
|
||||
payload.customMode = input.customMode;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
copyDefined(input, payload, ['prompt', 'customMode', 'style', 'title']);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/add-vocals', payload);
|
||||
break;
|
||||
}
|
||||
@@ -233,16 +233,10 @@ class ToolHandlers {
|
||||
const input = schemas.AddInstrumentalSchema.parse(args);
|
||||
const payload = {
|
||||
audioId: input.audioId,
|
||||
prompt: input.prompt,
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.customMode !== undefined)
|
||||
payload.customMode = input.customMode;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
copyDefined(input, payload, ['prompt', 'customMode', 'style', 'title']);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/add-instrumental', payload);
|
||||
break;
|
||||
}
|
||||
@@ -255,26 +249,18 @@ class ToolHandlers {
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.prompt !== undefined)
|
||||
payload.prompt = input.prompt;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
if (input.negativeTags !== undefined)
|
||||
payload.negativeTags = input.negativeTags;
|
||||
if (input.vocalGender !== undefined)
|
||||
payload.vocalGender = input.vocalGender;
|
||||
if (input.styleWeight !== undefined)
|
||||
payload.styleWeight = input.styleWeight;
|
||||
if (input.weirdnessConstraint !== undefined)
|
||||
payload.weirdnessConstraint = input.weirdnessConstraint;
|
||||
if (input.audioWeight !== undefined)
|
||||
payload.audioWeight = input.audioWeight;
|
||||
if (input.personaId !== undefined)
|
||||
payload.personaId = input.personaId;
|
||||
if (input.personaModel !== undefined)
|
||||
payload.personaModel = input.personaModel;
|
||||
copyDefined(input, payload, [
|
||||
'prompt',
|
||||
'style',
|
||||
'title',
|
||||
'negativeTags',
|
||||
'vocalGender',
|
||||
'styleWeight',
|
||||
'weirdnessConstraint',
|
||||
'audioWeight',
|
||||
'personaId',
|
||||
'personaModel',
|
||||
]);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/upload-cover', payload);
|
||||
break;
|
||||
}
|
||||
@@ -286,14 +272,7 @@ class ToolHandlers {
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.prompt !== undefined)
|
||||
payload.prompt = input.prompt;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
if (input.continueAt !== undefined)
|
||||
payload.continueAt = input.continueAt;
|
||||
copyDefined(input, payload, ['prompt', 'style', 'title', 'continueAt']);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/upload-extend', payload);
|
||||
break;
|
||||
}
|
||||
@@ -306,22 +285,16 @@ class ToolHandlers {
|
||||
model: input.model,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.instrumental !== undefined)
|
||||
payload.instrumental = input.instrumental;
|
||||
if (input.style !== undefined)
|
||||
payload.style = input.style;
|
||||
if (input.title !== undefined)
|
||||
payload.title = input.title;
|
||||
if (input.negativeTags !== undefined)
|
||||
payload.negativeTags = input.negativeTags;
|
||||
if (input.vocalGender !== undefined)
|
||||
payload.vocalGender = input.vocalGender;
|
||||
if (input.styleWeight !== undefined)
|
||||
payload.styleWeight = input.styleWeight;
|
||||
if (input.weirdnessConstraint !== undefined)
|
||||
payload.weirdnessConstraint = input.weirdnessConstraint;
|
||||
if (input.audioWeight !== undefined)
|
||||
payload.audioWeight = input.audioWeight;
|
||||
copyDefined(input, payload, [
|
||||
'instrumental',
|
||||
'style',
|
||||
'title',
|
||||
'negativeTags',
|
||||
'vocalGender',
|
||||
'styleWeight',
|
||||
'weirdnessConstraint',
|
||||
'audioWeight',
|
||||
]);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/mashup', payload);
|
||||
break;
|
||||
}
|
||||
@@ -351,10 +324,7 @@ class ToolHandlers {
|
||||
audioId: input.audioId,
|
||||
callBackUrl: input.callBackUrl ?? '',
|
||||
};
|
||||
if (input.author !== undefined)
|
||||
payload.author = input.author;
|
||||
if (input.domainName !== undefined)
|
||||
payload.domainName = input.domainName;
|
||||
copyDefined(input, payload, ['author', 'domainName']);
|
||||
resultText = await runAsyncTask(this.client, name, '/generate/video', payload);
|
||||
break;
|
||||
}
|
||||
@@ -407,8 +377,8 @@ class ToolHandlers {
|
||||
}
|
||||
case 'suno_get_lyrics_details': {
|
||||
const input = schemas.GetLyricsDetailsSchema.parse(args);
|
||||
const result = await this.client.get(`/generate/lyrics-info?taskId=${encodeURIComponent(input.taskId)}`);
|
||||
resultText = JSON.stringify(result.data, null, 2);
|
||||
const result = await this.client.get(`/lyrics/record-info?taskId=${encodeURIComponent(input.taskId)}`);
|
||||
resultText = formatLyricsResult(result.data);
|
||||
break;
|
||||
}
|
||||
case 'suno_get_wav_details': {
|
||||
|
||||
Reference in New Issue
Block a user