447 lines
21 KiB
JavaScript
447 lines
21 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || (function () {
|
|
var ownKeys = function(o) {
|
|
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
var ar = [];
|
|
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
return ar;
|
|
};
|
|
return ownKeys(o);
|
|
};
|
|
return function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
})();
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.ToolHandlers = void 0;
|
|
const schemas = __importStar(require("./schemas"));
|
|
const ASYNC_POLLING_PATHS = {
|
|
'suno_generate_music': '/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=',
|
|
'suno_upload_and_extend': '/generate/record-info?taskId=',
|
|
'suno_add_vocals': '/generate/record-info?taskId=',
|
|
'suno_add_instrumental': '/generate/record-info?taskId=',
|
|
'suno_generate_mashup': '/generate/record-info?taskId=',
|
|
'suno_separate_vocals': '/vocal-removal/record-info?taskId=',
|
|
'suno_separate_stems': '/vocal-removal/record-info?taskId=',
|
|
'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 formatTaskResult(data) {
|
|
const status = data.status;
|
|
if (status !== 'SUCCESS') {
|
|
return JSON.stringify({
|
|
taskId: data.taskId,
|
|
status,
|
|
errorCode: data.errorCode,
|
|
errorMessage: data.errorMessage,
|
|
}, null, 2);
|
|
}
|
|
const response = data.response;
|
|
const tracks = response?.data ?? response?.sunoData ?? [];
|
|
return JSON.stringify({
|
|
taskId: data.taskId,
|
|
status,
|
|
operationType: data.operationType,
|
|
tracks: tracks.map((t) => ({
|
|
id: t.id,
|
|
title: t.title,
|
|
tags: t.tags,
|
|
duration: t.duration,
|
|
prompt: t.prompt,
|
|
audio_url: t.audio_url ?? t.audioUrl,
|
|
stream_audio_url: t.stream_audio_url ?? t.streamAudioUrl,
|
|
image_url: t.image_url ?? t.imageUrl,
|
|
})),
|
|
}, null, 2);
|
|
}
|
|
async function runAsyncTask(client, taskName, createPath, payload) {
|
|
const createResult = await client.post(createPath, payload);
|
|
const taskId = createResult.data.taskId;
|
|
const statusPathTemplate = ASYNC_POLLING_PATHS[taskName];
|
|
if (!statusPathTemplate) {
|
|
return JSON.stringify({ taskId, status: 'PENDING', note: 'Use suno_get_task_status to poll.' }, null, 2);
|
|
}
|
|
const statusData = await client.pollTaskStatus(taskId, {
|
|
statusPath: `${statusPathTemplate}${encodeURIComponent(taskId)}`,
|
|
});
|
|
return formatTaskResult(statusData);
|
|
}
|
|
class ToolHandlers {
|
|
client;
|
|
constructor(client) {
|
|
this.client = client;
|
|
}
|
|
async handle(name, args) {
|
|
let resultText;
|
|
switch (name) {
|
|
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;
|
|
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', {
|
|
prompt: input.prompt,
|
|
callBackUrl: input.callBackUrl ?? '',
|
|
});
|
|
resultText = JSON.stringify({ taskId: result.data.taskId, status: 'PENDING' }, null, 2);
|
|
break;
|
|
}
|
|
case 'suno_generate_sounds': {
|
|
const input = schemas.GenerateSoundsSchema.parse(args);
|
|
const payload = {
|
|
prompt: input.prompt,
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/sounds', payload);
|
|
break;
|
|
}
|
|
case 'suno_extend_music': {
|
|
const input = schemas.ExtendMusicSchema.parse(args);
|
|
const payload = {
|
|
audioId: input.audioId,
|
|
defaultParamFlag: input.defaultParamFlag,
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/extend', payload);
|
|
break;
|
|
}
|
|
case 'suno_replace_section': {
|
|
const input = schemas.ReplaceSectionSchema.parse(args);
|
|
const payload = {
|
|
audioId: input.audioId,
|
|
prompt: input.prompt,
|
|
start: input.start,
|
|
end: input.end,
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/replace-section', payload);
|
|
break;
|
|
}
|
|
case 'suno_add_vocals': {
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/add-vocals', payload);
|
|
break;
|
|
}
|
|
case 'suno_add_instrumental': {
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/add-instrumental', payload);
|
|
break;
|
|
}
|
|
case 'suno_upload_and_cover': {
|
|
const input = schemas.UploadAndCoverSchema.parse(args);
|
|
const payload = {
|
|
uploadUrl: input.uploadUrl,
|
|
customMode: input.customMode,
|
|
instrumental: input.instrumental,
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/upload-cover', payload);
|
|
break;
|
|
}
|
|
case 'suno_upload_and_extend': {
|
|
const input = schemas.UploadAndExtendSchema.parse(args);
|
|
const payload = {
|
|
uploadUrl: input.uploadUrl,
|
|
defaultParamFlag: input.defaultParamFlag,
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/upload-extend', payload);
|
|
break;
|
|
}
|
|
case 'suno_generate_mashup': {
|
|
const input = schemas.GenerateMashupSchema.parse(args);
|
|
const payload = {
|
|
uploadUrlList: input.uploadUrlList,
|
|
customMode: input.customMode,
|
|
prompt: input.prompt,
|
|
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;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/mashup', payload);
|
|
break;
|
|
}
|
|
case 'suno_separate_vocals': {
|
|
const input = schemas.SeparateVocalsSchema.parse(args);
|
|
resultText = await runAsyncTask(this.client, name, '/vocal-removal/generate', {
|
|
taskId: input.taskId,
|
|
audioId: input.audioId,
|
|
callBackUrl: input.callBackUrl ?? '',
|
|
});
|
|
break;
|
|
}
|
|
case 'suno_separate_stems': {
|
|
const input = schemas.SeparateStemsSchema.parse(args);
|
|
resultText = await runAsyncTask(this.client, name, '/vocal-removal/generate', {
|
|
taskId: input.taskId,
|
|
audioId: input.audioId,
|
|
type: 'split_stem',
|
|
callBackUrl: input.callBackUrl ?? '',
|
|
});
|
|
break;
|
|
}
|
|
case 'suno_create_video': {
|
|
const input = schemas.CreateVideoSchema.parse(args);
|
|
const payload = {
|
|
taskId: input.taskId,
|
|
audioId: input.audioId,
|
|
callBackUrl: input.callBackUrl ?? '',
|
|
};
|
|
if (input.author !== undefined)
|
|
payload.author = input.author;
|
|
if (input.domainName !== undefined)
|
|
payload.domainName = input.domainName;
|
|
resultText = await runAsyncTask(this.client, name, '/generate/video', payload);
|
|
break;
|
|
}
|
|
case 'suno_create_cover': {
|
|
const input = schemas.CreateCoverSchema.parse(args);
|
|
resultText = await runAsyncTask(this.client, name, '/generate/cover', {
|
|
taskId: input.taskId,
|
|
audioId: input.audioId,
|
|
callBackUrl: input.callBackUrl ?? '',
|
|
});
|
|
break;
|
|
}
|
|
case 'suno_convert_to_wav': {
|
|
const input = schemas.ConvertToWavSchema.parse(args);
|
|
resultText = await runAsyncTask(this.client, name, '/generate/wav', {
|
|
taskId: input.taskId,
|
|
audioId: input.audioId,
|
|
callBackUrl: input.callBackUrl ?? '',
|
|
});
|
|
break;
|
|
}
|
|
case 'suno_boost_style': {
|
|
const input = schemas.BoostStyleSchema.parse(args);
|
|
const result = await this.client.post('/style/generate', {
|
|
content: input.content,
|
|
});
|
|
resultText = result.data.result;
|
|
break;
|
|
}
|
|
case 'suno_generate_persona': {
|
|
const input = schemas.GeneratePersonaSchema.parse(args);
|
|
const payload = { taskId: input.taskId };
|
|
if (input.audioId !== undefined)
|
|
payload.audioId = input.audioId;
|
|
const result = await this.client.post('/generate/persona', payload);
|
|
resultText = JSON.stringify(result.data, null, 2);
|
|
break;
|
|
}
|
|
case 'suno_get_task_status': {
|
|
const input = schemas.GetTaskStatusSchema.parse(args);
|
|
const data = await this.client.get(`/generate/record-info?taskId=${encodeURIComponent(input.taskId)}`);
|
|
resultText = formatTaskResult(data.data);
|
|
break;
|
|
}
|
|
case 'suno_get_timestamped_lyrics': {
|
|
const input = schemas.GetTimestampedLyricsSchema.parse(args);
|
|
const result = await this.client.get(`/generate/timestamped-lyrics?taskId=${encodeURIComponent(input.taskId)}&audioId=${encodeURIComponent(input.audioId)}`);
|
|
resultText = JSON.stringify(result.data, null, 2);
|
|
break;
|
|
}
|
|
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);
|
|
break;
|
|
}
|
|
case 'suno_get_wav_details': {
|
|
const input = schemas.GetWavDetailsSchema.parse(args);
|
|
const result = await this.client.get(`/generate/wav-info?taskId=${encodeURIComponent(input.taskId)}`);
|
|
resultText = JSON.stringify(result.data, null, 2);
|
|
break;
|
|
}
|
|
case 'suno_get_vocal_separation_details': {
|
|
const input = schemas.GetVocalSeparationDetailsSchema.parse(args);
|
|
const result = await this.client.get(`/vocal-removal/record-info?taskId=${encodeURIComponent(input.taskId)}`);
|
|
resultText = JSON.stringify(result.data, null, 2);
|
|
break;
|
|
}
|
|
case 'suno_get_video_details': {
|
|
const input = schemas.GetVideoDetailsSchema.parse(args);
|
|
const result = await this.client.get(`/generate/video-info?taskId=${encodeURIComponent(input.taskId)}`);
|
|
resultText = JSON.stringify(result.data, null, 2);
|
|
break;
|
|
}
|
|
case 'suno_get_credits': {
|
|
schemas.GetCreditsSchema.parse(args);
|
|
const result = await this.client.get('/generate/credit');
|
|
resultText = JSON.stringify({ credits: result.data }, null, 2);
|
|
break;
|
|
}
|
|
default:
|
|
throw new Error(`Unknown tool: ${name}`);
|
|
}
|
|
return {
|
|
content: [{ type: 'text', text: resultText }],
|
|
};
|
|
}
|
|
}
|
|
exports.ToolHandlers = ToolHandlers;
|
|
//# sourceMappingURL=handlers.js.map
|