@elizaos/plugin-suno 1.0.6-alpha.4 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
1
  // src/providers/suno.ts
2
+ import {
3
+ recordLlmCall
4
+ } from "@elizaos/core";
2
5
  var SunoProvider = class _SunoProvider {
3
6
  apiKey;
4
7
  baseUrl;
5
8
  static async get(runtime, _message, _state) {
6
9
  const apiKey = runtime.getSetting("SUNO_API_KEY");
7
- if (!apiKey) {
10
+ if (typeof apiKey !== "string" || !apiKey) {
8
11
  throw new Error("SUNO_API_KEY is required");
9
12
  }
10
13
  return new _SunoProvider({ apiKey });
@@ -16,491 +19,293 @@ var SunoProvider = class _SunoProvider {
16
19
  async get(_runtime, _message, _state) {
17
20
  return { status: "ready" };
18
21
  }
19
- async request(endpoint, options = {}) {
22
+ async request(runtime, endpoint, options = {}) {
20
23
  const url = `${this.baseUrl}${endpoint}`;
21
24
  const headers = {
22
- "Authorization": `Bearer ${this.apiKey}`,
25
+ Authorization: `Bearer ${this.apiKey}`,
23
26
  "Content-Type": "application/json",
24
27
  ...options.headers
25
28
  };
26
- const response = await fetch(url, {
27
- ...options,
28
- headers
29
+ const body = typeof options.body === "string" ? options.body : "";
30
+ const details = {
31
+ model: "suno",
32
+ modelVersion: "api-v1",
33
+ systemPrompt: "Suno music generation API request",
34
+ userPrompt: body,
35
+ temperature: readTemperature(body),
36
+ maxTokens: 0,
37
+ purpose: "action",
38
+ actionType: `suno.fetch${endpoint}`
39
+ };
40
+ return recordLlmCall(runtime, details, async () => {
41
+ const response = await fetch(url, {
42
+ ...options,
43
+ headers
44
+ });
45
+ if (!response.ok) {
46
+ throw new Error(`Suno API error: ${response.statusText}`);
47
+ }
48
+ const data = await response.json();
49
+ details.response = JSON.stringify({ suno_response: data });
50
+ return data;
29
51
  });
30
- if (!response.ok) {
31
- throw new Error(`Suno API error: ${response.statusText}`);
32
- }
33
- return response.json();
52
+ }
53
+ };
54
+ function readTemperature(body) {
55
+ if (!body) return 0;
56
+ try {
57
+ const parsed = JSON.parse(body);
58
+ return typeof parsed.temperature === "number" ? parsed.temperature : 0;
59
+ } catch {
60
+ return 0;
61
+ }
62
+ }
63
+ var sunoStatusProvider = {
64
+ name: "SUNO_STATUS",
65
+ description: "Suno music generation status",
66
+ descriptionCompressed: "Suno generation availability.",
67
+ contexts: ["media"],
68
+ contextGate: { anyOf: ["media"] },
69
+ cacheStable: false,
70
+ cacheScope: "turn",
71
+ get: async (runtime) => {
72
+ const configured = Boolean(runtime.getSetting("SUNO_API_KEY"));
73
+ return {
74
+ text: JSON.stringify(
75
+ {
76
+ suno: {
77
+ configured,
78
+ status: configured ? "ready" : "missing_api_key",
79
+ action: "MUSIC_GENERATION",
80
+ subactions: ["generate", "custom", "extend"]
81
+ }
82
+ },
83
+ null,
84
+ 2
85
+ ),
86
+ data: { configured },
87
+ values: { sunoConfigured: configured }
88
+ };
34
89
  }
35
90
  };
36
91
 
37
- // src/actions/generate.ts
38
- var generateMusic = {
39
- name: "generate-music",
40
- description: "Generate music using Suno AI",
92
+ // src/actions/musicGeneration.ts
93
+ var SUNO_ACTION_TIMEOUT_MS = 3e4;
94
+ var MAX_SUNO_RESPONSE_BYTES = 4e3;
95
+ function paramsFromMessageAndOptions(message, options) {
96
+ const content = message.content && typeof message.content === "object" ? message.content : {};
97
+ const parameters = (options == null ? void 0 : options.parameters) && typeof options.parameters === "object" ? options.parameters : {};
98
+ return { ...content, ...options, ...parameters };
99
+ }
100
+ function normalizeSubaction(value) {
101
+ const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
102
+ if (normalized === "generate" || normalized === "custom" || normalized === "extend") {
103
+ return normalized;
104
+ }
105
+ if (normalized === "custom_generate" || normalized === "custom-generate") return "custom";
106
+ if (normalized === "extend_audio" || normalized === "extend-audio") return "extend";
107
+ return null;
108
+ }
109
+ function inferSubaction(message, params) {
110
+ var _a;
111
+ const explicit = normalizeSubaction(params.action ?? params.subaction ?? params.operation);
112
+ if (explicit) return explicit;
113
+ const text = (((_a = message.content) == null ? void 0 : _a.text) ?? "").toLowerCase();
114
+ if (params.audio_id || /\b(extend|lengthen|longer|add \d+.*seconds?)\b/.test(text)) {
115
+ return "extend";
116
+ }
117
+ if (params.reference_audio || params.style || params.bpm || params.key || params.mode || /\b(custom|style|bpm|key|mode|reference)\b/.test(text)) {
118
+ return "custom";
119
+ }
120
+ return "generate";
121
+ }
122
+ function promptFromParams(message, params) {
123
+ var _a;
124
+ const prompt = typeof params.prompt === "string" ? params.prompt.trim() : "";
125
+ if (prompt) return prompt;
126
+ return (((_a = message.content) == null ? void 0 : _a.text) ?? "").trim();
127
+ }
128
+ function numberOrDefault(value, fallback) {
129
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
130
+ }
131
+ function generationBody(params, prompt) {
132
+ return {
133
+ prompt,
134
+ duration: numberOrDefault(params.duration, 30),
135
+ temperature: numberOrDefault(params.temperature, 1),
136
+ top_k: numberOrDefault(params.topK, 250),
137
+ top_p: numberOrDefault(params.topP, 0.95),
138
+ classifier_free_guidance: numberOrDefault(params.classifier_free_guidance, 3)
139
+ };
140
+ }
141
+ var musicGeneration = {
142
+ name: "MUSIC_GENERATION",
143
+ contexts: ["media"],
144
+ contextGate: { anyOf: ["media"] },
145
+ roleGate: { minRole: "USER" },
146
+ description: "Generate music through Suno. Use action generate for a simple prompt, custom for style/BPM/key/reference parameters, or extend for an existing audio_id and duration.",
147
+ descriptionCompressed: "Suno music generation router action: generate, custom, extend.",
41
148
  similes: [
149
+ "GENERATE_MUSIC",
42
150
  "CREATE_MUSIC",
43
151
  "MAKE_MUSIC",
44
152
  "COMPOSE_MUSIC",
45
- "GENERATE_AUDIO",
46
- "CREATE_SONG",
47
- "MAKE_SONG"
153
+ "CUSTOM_GENERATE_MUSIC",
154
+ "EXTEND_AUDIO"
48
155
  ],
49
- validate: async (runtime, message, state, options) => {
50
- var _a, _b;
51
- const __avTextRaw = typeof ((_a = message == null ? void 0 : message.content) == null ? void 0 : _a.text) === "string" ? message.content.text : "";
52
- const __avText = __avTextRaw.toLowerCase();
53
- const __avKeywords = ["generate", "music"];
54
- const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((word) => word.length > 0 && __avText.includes(word));
55
- const __avRegex = new RegExp("\\b(?:generate|music)\\b", "i");
56
- const __avRegexOk = __avRegex.test(__avText);
57
- const __avSource = String(((_b = message == null ? void 0 : message.content) == null ? void 0 : _b.source) ?? (message == null ? void 0 : message.source) ?? "");
58
- const __avExpectedSource = "";
59
- const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || (runtime == null ? void 0 : runtime.agentId) || (runtime == null ? void 0 : runtime.getService) || (runtime == null ? void 0 : runtime.getSetting));
60
- const __avOptions = options && typeof options === "object" ? options : {};
61
- const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean((message == null ? void 0 : message.content) && typeof message.content === "object");
62
- if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
63
- return false;
64
- }
65
- const __avLegacyValidate = async (runtime2, _message) => {
66
- return !!runtime2.getSetting("SUNO_API_KEY");
67
- };
68
- try {
69
- return Boolean(await __avLegacyValidate(runtime, message, state, options));
70
- } catch {
71
- return false;
72
- }
73
- },
74
- handler: async (runtime, message, state, _options, callback) => {
75
- try {
76
- const provider = await SunoProvider.get(runtime, message, state);
77
- const content = message.content;
78
- if (!content.prompt) {
79
- throw new Error("Missing required parameter: prompt");
80
- }
81
- const response = await provider.request("/generate", {
82
- method: "POST",
83
- body: JSON.stringify({
84
- prompt: content.prompt,
85
- duration: content.duration || 30,
86
- temperature: content.temperature || 1,
87
- top_k: content.topK || 250,
88
- top_p: content.topP || 0.95,
89
- classifier_free_guidance: content.classifier_free_guidance || 3
90
- })
91
- });
92
- if (callback) {
93
- callback({
94
- text: "Successfully generated music based on your prompt",
95
- content: response
96
- });
97
- }
98
- return true;
99
- } catch (error) {
100
- if (callback) {
101
- callback({
102
- text: `Failed to extend audio: ${error.message}`,
103
- error
104
- });
105
- }
106
- return false;
156
+ parameters: [
157
+ {
158
+ name: "action",
159
+ description: "Suno operation: generate, custom, or extend.",
160
+ required: false,
161
+ schema: { type: "string", enum: ["generate", "custom", "extend"] }
162
+ },
163
+ {
164
+ name: "subaction",
165
+ description: "Legacy alias for action.",
166
+ required: false,
167
+ schema: { type: "string" }
168
+ },
169
+ {
170
+ name: "prompt",
171
+ description: "Music prompt for generate/custom.",
172
+ required: false,
173
+ schema: { type: "string" }
174
+ },
175
+ {
176
+ name: "audio_id",
177
+ description: "Existing Suno audio id for extend.",
178
+ required: false,
179
+ schema: { type: "string" }
180
+ },
181
+ {
182
+ name: "duration",
183
+ description: "Generation duration or extension seconds.",
184
+ required: false,
185
+ schema: { type: "number", default: 30 }
107
186
  }
108
- },
109
- examples: [
110
- [
111
- {
112
- user: "{{user1}}",
113
- content: {
114
- text: "Create a happy and energetic song",
115
- prompt: "A cheerful and energetic melody with upbeat rhythm",
116
- duration: 30,
117
- temperature: 1
118
- }
119
- },
120
- {
121
- user: "{{agent}}",
122
- content: {
123
- text: "I'll generate a happy and energetic song for you.",
124
- action: "generate-music"
125
- }
126
- },
127
- {
128
- user: "{{agent}}",
129
- content: {
130
- text: "Successfully generated your upbeat and energetic song."
131
- }
132
- }
133
- ],
134
- [
135
- {
136
- user: "{{user1}}",
137
- content: {
138
- text: "Generate a relaxing ambient track",
139
- prompt: "A peaceful ambient soundscape with gentle waves and soft pads",
140
- duration: 45,
141
- temperature: 0.8,
142
- classifier_free_guidance: 4
143
- }
144
- },
145
- {
146
- user: "{{agent}}",
147
- content: {
148
- text: "I'll create a calming ambient piece for you.",
149
- action: "generate-music"
150
- }
151
- },
152
- {
153
- user: "{{agent}}",
154
- content: {
155
- text: "Successfully generated your relaxing ambient soundscape."
156
- }
157
- }
158
- ],
159
- [
160
- {
161
- user: "{{user1}}",
162
- content: {
163
- text: "Make a short jingle for my podcast",
164
- prompt: "A catchy and professional podcast intro jingle",
165
- duration: 15,
166
- temperature: 1.2,
167
- top_k: 300
168
- }
169
- },
170
- {
171
- user: "{{agent}}",
172
- content: {
173
- text: "I'll generate a podcast jingle for you.",
174
- action: "generate-music"
175
- }
176
- },
177
- {
178
- user: "{{agent}}",
179
- content: {
180
- text: "Successfully generated your podcast jingle."
181
- }
182
- }
183
- ]
184
- ]
185
- };
186
- var generate_default = generateMusic;
187
-
188
- // src/actions/customGenerate.ts
189
- var customGenerateMusic = {
190
- name: "custom-generate-music",
191
- description: "Generate music with custom parameters using Suno AI",
192
- similes: [
193
- "CREATE_CUSTOM_MUSIC",
194
- "GENERATE_CUSTOM_AUDIO",
195
- "MAKE_CUSTOM_MUSIC",
196
- "COMPOSE_CUSTOM_MUSIC",
197
- "COMPOSE_MUSIC",
198
- "CREATE_MUSIC",
199
- "GENERATE_MUSIC"
200
187
  ],
201
- validate: async (runtime, message, state, options) => {
202
- var _a, _b;
203
- const __avTextRaw = typeof ((_a = message == null ? void 0 : message.content) == null ? void 0 : _a.text) === "string" ? message.content.text : "";
204
- const __avText = __avTextRaw.toLowerCase();
205
- const __avKeywords = ["custom", "generate", "music"];
206
- const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((word) => word.length > 0 && __avText.includes(word));
207
- const __avRegex = new RegExp("\\b(?:custom|generate|music)\\b", "i");
208
- const __avRegexOk = __avRegex.test(__avText);
209
- const __avSource = String(((_b = message == null ? void 0 : message.content) == null ? void 0 : _b.source) ?? (message == null ? void 0 : message.source) ?? "");
210
- const __avExpectedSource = "";
211
- const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || (runtime == null ? void 0 : runtime.agentId) || (runtime == null ? void 0 : runtime.getService) || (runtime == null ? void 0 : runtime.getSetting));
212
- const __avOptions = options && typeof options === "object" ? options : {};
213
- const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean((message == null ? void 0 : message.content) && typeof message.content === "object");
214
- if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
215
- return false;
216
- }
217
- const __avLegacyValidate = async (runtime2, _message) => {
218
- return !!runtime2.getSetting("SUNO_API_KEY");
219
- };
220
- try {
221
- return Boolean(await __avLegacyValidate(runtime, message, state, options));
222
- } catch {
223
- return false;
224
- }
188
+ validate: async (runtime, message) => {
189
+ var _a;
190
+ if (!runtime.getSetting("SUNO_API_KEY")) return false;
191
+ const text = (((_a = message.content) == null ? void 0 : _a.text) ?? "").toLowerCase();
192
+ return /\b(generate|create|make|compose|extend|music|song|audio|track)\b/.test(text);
225
193
  },
226
- handler: async (runtime, message, state, _options, callback) => {
194
+ handler: async (runtime, message, state, options, callback) => {
227
195
  try {
196
+ const params = paramsFromMessageAndOptions(message, options);
197
+ const subaction = inferSubaction(message, params);
228
198
  const provider = await SunoProvider.get(runtime, message, state);
229
- const content = message.content;
230
- if (!content.prompt) {
231
- throw new Error("Missing required parameter: prompt");
232
- }
233
- const response = await provider.request("/custom-generate", {
234
- method: "POST",
235
- body: JSON.stringify({
236
- prompt: content.prompt,
237
- duration: content.duration || 30,
238
- temperature: content.temperature || 1,
239
- top_k: content.topK || 250,
240
- top_p: content.topP || 0.95,
241
- classifier_free_guidance: content.classifier_free_guidance || 3,
242
- reference_audio: content.reference_audio,
243
- style: content.style,
244
- bpm: content.bpm,
245
- key: content.key,
246
- mode: content.mode
247
- })
248
- });
249
- if (callback) {
250
- callback({
251
- text: "Successfully generated custom music",
252
- content: response
253
- });
254
- }
255
- return true;
256
- } catch (error) {
257
- if (callback) {
258
- callback({
259
- text: `Failed to generate custom music: ${error.message}`,
260
- error
261
- });
262
- }
263
- return false;
264
- }
265
- },
266
- examples: [
267
- [
268
- {
269
- user: "{{user1}}",
270
- content: {
271
- text: "Create an upbeat electronic dance track with heavy bass",
272
- prompt: "An upbeat electronic dance track with heavy bass and energetic synths",
273
- duration: 60,
274
- style: "electronic",
275
- bpm: 128
276
- }
277
- },
278
- {
279
- user: "{{agent}}",
280
- content: {
281
- text: "I'll generate an energetic EDM track for you.",
282
- action: "custom-generate-music"
283
- }
284
- },
285
- {
286
- user: "{{agent}}",
287
- content: {
288
- text: "Successfully generated your EDM track with heavy bass and synths."
199
+ let endpoint = "/generate";
200
+ let body;
201
+ if (subaction === "extend") {
202
+ if (!params.audio_id || !params.duration) {
203
+ throw new Error("Missing required parameters: audio_id and duration");
289
204
  }
290
- }
291
- ],
292
- [
293
- {
294
- user: "{{user1}}",
295
- content: {
296
- text: "Generate a calm piano melody in C major",
297
- prompt: "A gentle, flowing piano melody with soft dynamics",
298
- duration: 45,
299
- style: "classical",
300
- key: "C",
301
- mode: "major",
302
- temperature: 0.8
205
+ endpoint = "/extend";
206
+ body = {
207
+ audio_id: params.audio_id,
208
+ duration: params.duration
209
+ };
210
+ } else {
211
+ const prompt = promptFromParams(message, params);
212
+ if (!prompt) {
213
+ throw new Error("Missing required parameter: prompt");
303
214
  }
304
- },
305
- {
306
- user: "{{agent}}",
307
- content: {
308
- text: "I'll create a calming piano piece in C major for you.",
309
- action: "custom-generate-music"
310
- }
311
- },
312
- {
313
- user: "{{agent}}",
314
- content: {
315
- text: "Successfully generated your peaceful piano melody in C major."
215
+ body = generationBody(params, prompt);
216
+ if (subaction === "custom") {
217
+ endpoint = "/custom-generate";
218
+ body = {
219
+ ...body,
220
+ reference_audio: params.reference_audio,
221
+ style: params.style,
222
+ bpm: params.bpm,
223
+ key: params.key,
224
+ mode: params.mode
225
+ };
316
226
  }
317
227
  }
318
- ],
319
- [
320
- {
321
- user: "{{user1}}",
322
- content: {
323
- text: "Make a rock song with guitar solos",
324
- prompt: "A rock song with powerful electric guitar solos and driving drums",
325
- duration: 90,
326
- style: "rock",
327
- bpm: 120,
328
- classifier_free_guidance: 4
329
- }
330
- },
331
- {
332
- user: "{{agent}}",
333
- content: {
334
- text: "I'll generate a rock track with guitar solos for you.",
335
- action: "custom-generate-music"
336
- }
337
- },
338
- {
339
- user: "{{agent}}",
340
- content: {
341
- text: "Successfully generated your rock song with guitar solos."
342
- }
343
- }
344
- ]
345
- ]
346
- };
347
- var customGenerate_default = customGenerateMusic;
348
-
349
- // src/actions/extend.ts
350
- var extendAudio = {
351
- name: "extend-audio",
352
- description: "Extend the duration of an existing audio generation",
353
- similes: [
354
- "LENGTHEN_AUDIO",
355
- "PROLONG_AUDIO",
356
- "INCREASE_DURATION",
357
- "MAKE_AUDIO_LONGER"
358
- ],
359
- validate: async (runtime, message, state, options) => {
360
- var _a, _b;
361
- const __avTextRaw = typeof ((_a = message == null ? void 0 : message.content) == null ? void 0 : _a.text) === "string" ? message.content.text : "";
362
- const __avText = __avTextRaw.toLowerCase();
363
- const __avKeywords = ["extend", "audio"];
364
- const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((word) => word.length > 0 && __avText.includes(word));
365
- const __avRegex = new RegExp("\\b(?:extend|audio)\\b", "i");
366
- const __avRegexOk = __avRegex.test(__avText);
367
- const __avSource = String(((_b = message == null ? void 0 : message.content) == null ? void 0 : _b.source) ?? (message == null ? void 0 : message.source) ?? "");
368
- const __avExpectedSource = "";
369
- const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || (runtime == null ? void 0 : runtime.agentId) || (runtime == null ? void 0 : runtime.getService) || (runtime == null ? void 0 : runtime.getSetting));
370
- const __avOptions = options && typeof options === "object" ? options : {};
371
- const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean((message == null ? void 0 : message.content) && typeof message.content === "object");
372
- if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
373
- return false;
374
- }
375
- const __avLegacyValidate = async (runtime2, _message) => {
376
- return !!runtime2.getSetting("SUNO_API_KEY");
377
- };
378
- try {
379
- return Boolean(await __avLegacyValidate(runtime, message, state, options));
380
- } catch {
381
- return false;
382
- }
383
- },
384
- handler: async (runtime, message, state, _options, callback) => {
385
- try {
386
- const provider = await SunoProvider.get(runtime, message, state);
387
- const content = message.content;
388
- if (!content.audio_id || !content.duration) {
389
- throw new Error("Missing required parameters: audio_id and duration");
390
- }
391
- const response = await provider.request("/extend", {
228
+ const controller = new AbortController();
229
+ const timeout = setTimeout(() => controller.abort(), SUNO_ACTION_TIMEOUT_MS);
230
+ const response = await provider.request(runtime, endpoint, {
392
231
  method: "POST",
393
- body: JSON.stringify({
394
- audio_id: content.audio_id,
395
- duration: content.duration
396
- })
397
- });
398
- if (callback) {
399
- callback({
400
- text: `Successfully extended audio ${content.audio_id}`,
401
- content: response
402
- });
403
- }
404
- return true;
232
+ body: JSON.stringify(body),
233
+ signal: controller.signal
234
+ }).finally(() => clearTimeout(timeout));
235
+ const cappedResponse = JSON.stringify(response).length > MAX_SUNO_RESPONSE_BYTES ? {
236
+ truncated: true,
237
+ preview: JSON.stringify(response).slice(0, MAX_SUNO_RESPONSE_BYTES)
238
+ } : response;
239
+ await (callback == null ? void 0 : callback({
240
+ text: subaction === "extend" ? `Successfully extended audio ${params.audio_id}` : `Successfully submitted ${subaction} music generation`,
241
+ content: cappedResponse
242
+ }));
243
+ return {
244
+ success: true,
245
+ text: subaction === "extend" ? `Successfully extended audio ${params.audio_id}` : `Successfully submitted ${subaction} music generation`,
246
+ data: { subaction, response: cappedResponse }
247
+ };
405
248
  } catch (error) {
406
- if (callback) {
407
- callback({
408
- text: `Failed to extend audio: ${error.message}`,
409
- error
410
- });
411
- }
412
- return false;
249
+ const errorMessage = error instanceof Error ? error.message : String(error);
250
+ const text = `Music generation failed: ${errorMessage}`;
251
+ await (callback == null ? void 0 : callback({
252
+ text,
253
+ error
254
+ }));
255
+ return { success: false, text, error: errorMessage };
413
256
  }
414
257
  },
415
258
  examples: [
416
259
  [
417
260
  {
418
- user: "{{user1}}",
419
- content: {
420
- text: "Make this song longer by 30 seconds",
421
- audio_id: "abc123",
422
- duration: 30
423
- }
424
- },
425
- {
426
- user: "{{agent}}",
427
- content: {
428
- text: "I'll extend your song by 30 seconds.",
429
- action: "extend-audio"
430
- }
431
- },
432
- {
433
- user: "{{agent}}",
434
- content: {
435
- text: "Successfully extended your song by 30 seconds."
436
- }
437
- }
438
- ],
439
- [
440
- {
441
- user: "{{user1}}",
261
+ name: "{{user1}}",
442
262
  content: {
443
- text: "Double the length of this track",
444
- audio_id: "xyz789",
445
- duration: 60
446
- }
447
- },
448
- {
449
- user: "{{agent}}",
450
- content: {
451
- text: "I'll double the duration of your track.",
452
- action: "extend-audio"
453
- }
454
- },
455
- {
456
- user: "{{agent}}",
457
- content: {
458
- text: "Successfully doubled the length of your track to 60 seconds."
459
- }
460
- }
461
- ],
462
- [
463
- {
464
- user: "{{user1}}",
465
- content: {
466
- text: "Add 15 more seconds to this melody",
467
- audio_id: "def456",
468
- duration: 15
469
- }
470
- },
471
- {
472
- user: "{{agent}}",
473
- content: {
474
- text: "I'll add 15 seconds to your melody.",
475
- action: "extend-audio"
263
+ text: "Generate a relaxing ambient track",
264
+ prompt: "A peaceful ambient soundscape with gentle waves and soft pads",
265
+ duration: 45
476
266
  }
477
267
  },
478
268
  {
479
- user: "{{agent}}",
269
+ name: "{{agent}}",
480
270
  content: {
481
- text: "Successfully added 15 seconds to your melody."
271
+ text: "I'll generate a calming ambient piece.",
272
+ action: "MUSIC_GENERATION"
482
273
  }
483
274
  }
484
275
  ]
485
276
  ]
486
277
  };
487
- var extend_default = extendAudio;
278
+ var musicGeneration_default = musicGeneration;
488
279
 
489
280
  // src/index.ts
490
281
  var sunoPlugin = {
491
282
  name: "suno",
492
283
  description: "Suno AI Music Generation Plugin for Eliza",
493
- actions: [generate_default, customGenerate_default, extend_default],
494
- evaluators: [],
495
- providers: [SunoProvider]
284
+ actions: [musicGeneration_default],
285
+ providers: [sunoStatusProvider],
286
+ // Self-declared auto-enable: activate when SUNO_API_KEY is set OR when
287
+ // media.audio is configured to use the suno provider with own-key mode.
288
+ autoEnable: {
289
+ shouldEnable: (env, config) => {
290
+ const key = env.SUNO_API_KEY;
291
+ if (typeof key === "string" && key.trim() !== "") return true;
292
+ const media = config == null ? void 0 : config.media;
293
+ const audio = media == null ? void 0 : media.audio;
294
+ return Boolean(
295
+ audio && audio.enabled !== false && audio.mode === "own-key" && audio.provider === "suno"
296
+ );
297
+ }
298
+ }
496
299
  };
497
300
  var index_default = sunoPlugin;
498
301
  export {
499
- customGenerate_default as CustomGenerateMusic,
500
- extend_default as ExtendAudio,
501
- generate_default as GenerateMusic,
302
+ musicGeneration_default as CustomGenerateMusic,
303
+ musicGeneration_default as ExtendAudio,
304
+ musicGeneration_default as GenerateMusic,
305
+ musicGeneration_default as MusicGeneration,
502
306
  SunoProvider,
503
307
  index_default as default,
504
- sunoPlugin
308
+ sunoPlugin,
309
+ sunoStatusProvider
505
310
  };
506
311
  //# sourceMappingURL=index.js.map