@elizaos/plugin-suno 2.0.0-beta.1 → 2.0.3-beta.3
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/LICENSE +21 -0
- package/README.md +81 -207
- package/auto-enable.ts +5 -5
- package/package.json +23 -8
- package/dist/index.d.ts +0 -23
- package/dist/index.js +0 -311
- package/dist/index.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shaw Walters and elizaOS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,207 +1,81 @@
|
|
|
1
|
-
@elizaos/plugin-suno
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
- Lengthening existing music pieces
|
|
83
|
-
- Creating seamless loops
|
|
84
|
-
- Generating variations of existing tracks
|
|
85
|
-
|
|
86
|
-
await eliza.execute('suno.extend-audio', {
|
|
87
|
-
audio_id: "your-audio-id",
|
|
88
|
-
duration: 60
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
Generation Parameters Explained:
|
|
92
|
-
|
|
93
|
-
- temperature: Controls randomness in generation (0.0-1.0+)
|
|
94
|
-
* Lower values (0.1-0.5): More conservative, consistent output
|
|
95
|
-
* Higher values (1.0+): More creative, varied output
|
|
96
|
-
|
|
97
|
-
- classifier_free_guidance: Controls how closely the output follows the prompt (1.0-20.0)
|
|
98
|
-
* Lower values: More creative interpretation
|
|
99
|
-
* Higher values: Stricter adherence to prompt
|
|
100
|
-
|
|
101
|
-
- topK/topP: Control the diversity of the generation
|
|
102
|
-
* topK: Limits the number of tokens considered
|
|
103
|
-
* topP: Controls the cumulative probability threshold
|
|
104
|
-
|
|
105
|
-
API REFERENCE
|
|
106
|
-
|
|
107
|
-
SunoProvider Configuration
|
|
108
|
-
The Suno provider accepts the following configuration options:
|
|
109
|
-
|
|
110
|
-
interface SunoConfig {
|
|
111
|
-
apiKey: string;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
Action Parameters:
|
|
115
|
-
|
|
116
|
-
1. Generate Music (suno.generate-music)
|
|
117
|
-
interface GenerateParams {
|
|
118
|
-
prompt: string;
|
|
119
|
-
duration?: number; // Duration in seconds
|
|
120
|
-
temperature?: number; // Controls randomness
|
|
121
|
-
topK?: number; // Top K sampling
|
|
122
|
-
topP?: number; // Top P sampling
|
|
123
|
-
classifier_free_guidance?: number; // Guidance scale
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
2. Custom Generate Music (suno.custom-generate-music)
|
|
127
|
-
interface CustomGenerateParams {
|
|
128
|
-
prompt: string;
|
|
129
|
-
duration?: number;
|
|
130
|
-
temperature?: number;
|
|
131
|
-
topK?: number;
|
|
132
|
-
topP?: number;
|
|
133
|
-
classifier_free_guidance?: number;
|
|
134
|
-
reference_audio?: string; // Path to reference audio file
|
|
135
|
-
style?: string; // Musical style
|
|
136
|
-
bpm?: number; // Beats per minute
|
|
137
|
-
key?: string; // Musical key
|
|
138
|
-
mode?: string; // Musical mode (e.g., "major", "minor")
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
3. Extend Audio (suno.extend-audio)
|
|
142
|
-
interface ExtendParams {
|
|
143
|
-
audio_id: string; // ID of the audio to extend
|
|
144
|
-
duration: number; // Additional duration in seconds
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
Response Type:
|
|
148
|
-
interface GenerationResponse {
|
|
149
|
-
id: string; // Generated audio ID
|
|
150
|
-
status: string; // Status of the generation
|
|
151
|
-
url?: string; // URL to download the generated audio
|
|
152
|
-
error?: string; // Error message if generation failed
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
ERROR HANDLING
|
|
156
|
-
|
|
157
|
-
The plugin includes built-in error handling for common scenarios:
|
|
158
|
-
|
|
159
|
-
try {
|
|
160
|
-
await eliza.execute('suno.generate', params);
|
|
161
|
-
} catch (error) {
|
|
162
|
-
if (error.code === 'SUNO_API_ERROR') {
|
|
163
|
-
// Handle API-specific errors
|
|
164
|
-
}
|
|
165
|
-
// Handle other errors
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
EXAMPLES
|
|
169
|
-
|
|
170
|
-
Creating a Pop Song:
|
|
171
|
-
|
|
172
|
-
const result = await eliza.execute('suno.generate-music', {
|
|
173
|
-
prompt: "Create a pop song with vocals, drums, and guitar",
|
|
174
|
-
duration: 180,
|
|
175
|
-
temperature: 1.0,
|
|
176
|
-
classifier_free_guidance: 3.5
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
Creating a Custom Classical Piece:
|
|
180
|
-
|
|
181
|
-
const result = await eliza.execute('suno.custom-generate-music', {
|
|
182
|
-
prompt: "A classical piano sonata in the style of Mozart",
|
|
183
|
-
duration: 120,
|
|
184
|
-
temperature: 0.8,
|
|
185
|
-
style: "classical",
|
|
186
|
-
bpm: 120,
|
|
187
|
-
key: "C",
|
|
188
|
-
mode: "major"
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
Extending an Existing Track:
|
|
192
|
-
|
|
193
|
-
const extended = await eliza.execute('suno.extend-audio', {
|
|
194
|
-
audio_id: "existing-track-id",
|
|
195
|
-
duration: 60
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
LICENSE
|
|
199
|
-
|
|
200
|
-
MIT
|
|
201
|
-
|
|
202
|
-
SUPPORT
|
|
203
|
-
|
|
204
|
-
For issues and feature requests, please open an issue on our GitHub repository.
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
Built with ❤️ for ElizaOS
|
|
1
|
+
# @elizaos/plugin-suno
|
|
2
|
+
|
|
3
|
+
Suno AI music generation plugin for elizaOS. Enables Eliza agents to generate, custom-generate, and extend audio tracks via the Suno API.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
This plugin contributes a Suno HTTP client and a status provider (`SUNO_STATUS`) to the elizaOS agent runtime. Music generation is dispatched through the `MUSIC` umbrella action (provided by `@elizaos/plugin-music`); this plugin supplies the Suno-specific handler (`sunoGenerateMusicHandler`) that `plugin-music` mounts.
|
|
8
|
+
|
|
9
|
+
Three subactions are supported:
|
|
10
|
+
|
|
11
|
+
| Subaction | Endpoint | Required params |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `generate` | `POST /generate` | `prompt` |
|
|
14
|
+
| `custom_generate` | `POST /custom-generate` | `prompt`; optional: `style`, `bpm`, `key`, `mode`, `reference_audio` |
|
|
15
|
+
| `extend` | `POST /extend` | `audio_id`, `duration` |
|
|
16
|
+
|
|
17
|
+
The subaction is inferred from message text and params when not specified explicitly.
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
- A Suno API key (obtain at [suno.ai](https://suno.ai)).
|
|
22
|
+
- `@elizaos/plugin-music` loaded alongside this plugin to expose the `MUSIC` action to agents.
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
Set the API key as an environment variable or in the agent character config:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
SUNO_API_KEY=your-suno-api-key
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The plugin auto-enables when `SUNO_API_KEY` is present, or when agent config sets:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"media": {
|
|
37
|
+
"audio": {
|
|
38
|
+
"provider": "suno",
|
|
39
|
+
"mode": "own-key"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Generation parameters
|
|
46
|
+
|
|
47
|
+
### `generate` and `custom_generate`
|
|
48
|
+
|
|
49
|
+
| Param | Type | Default | Description |
|
|
50
|
+
|---|---|---|---|
|
|
51
|
+
| `prompt` | string | (required) | Text description of the music to generate |
|
|
52
|
+
| `duration` | number | 30 | Duration in seconds |
|
|
53
|
+
| `temperature` | number | 1.0 | Randomness (higher = more creative) |
|
|
54
|
+
| `topK` | number | 250 | Top-K sampling |
|
|
55
|
+
| `topP` | number | 0.95 | Top-P sampling |
|
|
56
|
+
| `classifier_free_guidance` | number | 3.0 | Prompt adherence strength |
|
|
57
|
+
| `style` | string | — | Musical style (custom_generate only) |
|
|
58
|
+
| `bpm` | number | — | Beats per minute (custom_generate only) |
|
|
59
|
+
| `key` | string | — | Musical key, e.g. `"C"` (custom_generate only) |
|
|
60
|
+
| `mode` | string | — | `"major"` or `"minor"` (custom_generate only) |
|
|
61
|
+
| `reference_audio` | string | — | Reference audio path (custom_generate only) |
|
|
62
|
+
|
|
63
|
+
### `extend`
|
|
64
|
+
|
|
65
|
+
| Param | Type | Required | Description |
|
|
66
|
+
|---|---|---|---|
|
|
67
|
+
| `audio_id` | string | Yes | ID of the existing track to extend |
|
|
68
|
+
| `duration` | number | Yes | Additional seconds to add |
|
|
69
|
+
|
|
70
|
+
## Response shape
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
interface GenerationResponse {
|
|
74
|
+
id: string;
|
|
75
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
76
|
+
audio_url?: string;
|
|
77
|
+
error?: string;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Responses larger than 4000 bytes are truncated before being returned to the agent context.
|
package/auto-enable.ts
CHANGED
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
// `elizaos.plugin.autoEnableModule`. Keep this module light: env reads only,
|
|
5
5
|
// no service init, no transitive imports of the full plugin runtime. The
|
|
6
6
|
// auto-enable engine loads dozens of these per boot.
|
|
7
|
-
import type { PluginAutoEnableContext } from
|
|
7
|
+
import type { PluginAutoEnableContext } from '@elizaos/core';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Enable when a Suno API key is in the environment, or when the user has
|
|
11
11
|
* explicitly selected Suno as the audio provider in own-key mode.
|
|
12
12
|
*/
|
|
13
13
|
export function shouldEnable(ctx: PluginAutoEnableContext): boolean {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const apiKey = ctx.env.SUNO_API_KEY;
|
|
15
|
+
if (apiKey && apiKey.trim() !== '') return true;
|
|
16
|
+
const audio = ctx.config?.media?.audio;
|
|
17
|
+
return audio?.provider === 'suno' && audio?.mode === 'own-key';
|
|
18
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/plugin-suno",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3-beta.3",
|
|
4
4
|
"description": "Suno AI Music Generation Plugin for Eliza",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,8 +9,24 @@
|
|
|
9
9
|
"./package.json": "./package.json",
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
|
+
"eliza-source": {
|
|
13
|
+
"types": "./src/index.ts",
|
|
14
|
+
"import": "./src/index.ts",
|
|
15
|
+
"default": "./src/index.ts"
|
|
16
|
+
},
|
|
12
17
|
"import": "./dist/index.js",
|
|
13
18
|
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./*.css": "./dist/*.css",
|
|
21
|
+
"./*": {
|
|
22
|
+
"types": "./dist/*.d.ts",
|
|
23
|
+
"eliza-source": {
|
|
24
|
+
"types": "./src/*.ts",
|
|
25
|
+
"import": "./src/*.ts",
|
|
26
|
+
"default": "./src/*.ts"
|
|
27
|
+
},
|
|
28
|
+
"import": "./dist/*.js",
|
|
29
|
+
"default": "./dist/*.js"
|
|
14
30
|
}
|
|
15
31
|
},
|
|
16
32
|
"files": [
|
|
@@ -28,19 +44,17 @@
|
|
|
28
44
|
"scripts": {
|
|
29
45
|
"build": "tsup --format esm",
|
|
30
46
|
"dev": "tsup --format esm --watch",
|
|
31
|
-
"lint": "
|
|
47
|
+
"lint": "bunx @biomejs/biome check .",
|
|
32
48
|
"lint:check": "bun run lint",
|
|
33
49
|
"lint:fix": "bunx @biomejs/biome check --write ./src",
|
|
34
50
|
"format": "bunx @biomejs/biome format --write ./src",
|
|
35
51
|
"format:check": "bunx @biomejs/biome format ./src",
|
|
36
|
-
"test": "vitest run --config vitest.config.ts
|
|
37
|
-
"typecheck": "
|
|
52
|
+
"test": "vitest run --config vitest.config.ts",
|
|
53
|
+
"typecheck": "tsgo --noEmit -p tsconfig.json"
|
|
38
54
|
},
|
|
39
55
|
"devDependencies": {
|
|
40
56
|
"@biomejs/biome": "^2.4.14",
|
|
41
|
-
"@types/jest": "^30.0.0",
|
|
42
57
|
"@types/node": "^22.19.17",
|
|
43
|
-
"jest": "^30.0.0",
|
|
44
58
|
"tsup": "^8.5.1",
|
|
45
59
|
"typescript": "^6.0.3",
|
|
46
60
|
"vitest": "^4.0.0"
|
|
@@ -60,6 +74,7 @@
|
|
|
60
74
|
"access": "public"
|
|
61
75
|
},
|
|
62
76
|
"dependencies": {
|
|
63
|
-
"@elizaos/core": "2.0.
|
|
64
|
-
}
|
|
77
|
+
"@elizaos/core": "2.0.3-beta.3"
|
|
78
|
+
},
|
|
79
|
+
"gitHead": "f54b0f4eaed317d59fa7dbcdce20f4cdb0734420"
|
|
65
80
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Action, IAgentRuntime, Memory, State, Provider, Plugin } from '@elizaos/core';
|
|
2
|
-
|
|
3
|
-
declare const musicGeneration: Action;
|
|
4
|
-
|
|
5
|
-
interface SunoConfig {
|
|
6
|
-
apiKey: string;
|
|
7
|
-
baseUrl?: string;
|
|
8
|
-
}
|
|
9
|
-
declare class SunoProvider {
|
|
10
|
-
private apiKey;
|
|
11
|
-
private baseUrl;
|
|
12
|
-
static get(runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<SunoProvider>;
|
|
13
|
-
constructor(config: SunoConfig);
|
|
14
|
-
get(_runtime: IAgentRuntime, _message: Memory, _state?: State): Promise<{
|
|
15
|
-
status: string;
|
|
16
|
-
}>;
|
|
17
|
-
request(runtime: IAgentRuntime, endpoint: string, options?: RequestInit): Promise<any>;
|
|
18
|
-
}
|
|
19
|
-
declare const sunoStatusProvider: Provider;
|
|
20
|
-
|
|
21
|
-
declare const sunoPlugin: Plugin;
|
|
22
|
-
|
|
23
|
-
export { musicGeneration as CustomGenerateMusic, musicGeneration as ExtendAudio, musicGeneration as GenerateMusic, musicGeneration as MusicGeneration, SunoProvider, sunoPlugin as default, sunoPlugin, sunoStatusProvider };
|
package/dist/index.js
DELETED
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
// src/providers/suno.ts
|
|
2
|
-
import {
|
|
3
|
-
recordLlmCall
|
|
4
|
-
} from "@elizaos/core";
|
|
5
|
-
var SunoProvider = class _SunoProvider {
|
|
6
|
-
apiKey;
|
|
7
|
-
baseUrl;
|
|
8
|
-
static async get(runtime, _message, _state) {
|
|
9
|
-
const apiKey = runtime.getSetting("SUNO_API_KEY");
|
|
10
|
-
if (typeof apiKey !== "string" || !apiKey) {
|
|
11
|
-
throw new Error("SUNO_API_KEY is required");
|
|
12
|
-
}
|
|
13
|
-
return new _SunoProvider({ apiKey });
|
|
14
|
-
}
|
|
15
|
-
constructor(config) {
|
|
16
|
-
this.apiKey = config.apiKey;
|
|
17
|
-
this.baseUrl = config.baseUrl || "https://api.suno.ai/v1";
|
|
18
|
-
}
|
|
19
|
-
async get(_runtime, _message, _state) {
|
|
20
|
-
return { status: "ready" };
|
|
21
|
-
}
|
|
22
|
-
async request(runtime, endpoint, options = {}) {
|
|
23
|
-
const url = `${this.baseUrl}${endpoint}`;
|
|
24
|
-
const headers = {
|
|
25
|
-
Authorization: `Bearer ${this.apiKey}`,
|
|
26
|
-
"Content-Type": "application/json",
|
|
27
|
-
...options.headers
|
|
28
|
-
};
|
|
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;
|
|
51
|
-
});
|
|
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
|
-
};
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
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.",
|
|
148
|
-
similes: [
|
|
149
|
-
"GENERATE_MUSIC",
|
|
150
|
-
"CREATE_MUSIC",
|
|
151
|
-
"MAKE_MUSIC",
|
|
152
|
-
"COMPOSE_MUSIC",
|
|
153
|
-
"CUSTOM_GENERATE_MUSIC",
|
|
154
|
-
"EXTEND_AUDIO"
|
|
155
|
-
],
|
|
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 }
|
|
186
|
-
}
|
|
187
|
-
],
|
|
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);
|
|
193
|
-
},
|
|
194
|
-
handler: async (runtime, message, state, options, callback) => {
|
|
195
|
-
try {
|
|
196
|
-
const params = paramsFromMessageAndOptions(message, options);
|
|
197
|
-
const subaction = inferSubaction(message, params);
|
|
198
|
-
const provider = await SunoProvider.get(runtime, message, state);
|
|
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");
|
|
204
|
-
}
|
|
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");
|
|
214
|
-
}
|
|
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
|
-
};
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
const controller = new AbortController();
|
|
229
|
-
const timeout = setTimeout(() => controller.abort(), SUNO_ACTION_TIMEOUT_MS);
|
|
230
|
-
const response = await provider.request(runtime, endpoint, {
|
|
231
|
-
method: "POST",
|
|
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
|
-
};
|
|
248
|
-
} catch (error) {
|
|
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 };
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
examples: [
|
|
259
|
-
[
|
|
260
|
-
{
|
|
261
|
-
name: "{{user1}}",
|
|
262
|
-
content: {
|
|
263
|
-
text: "Generate a relaxing ambient track",
|
|
264
|
-
prompt: "A peaceful ambient soundscape with gentle waves and soft pads",
|
|
265
|
-
duration: 45
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
{
|
|
269
|
-
name: "{{agent}}",
|
|
270
|
-
content: {
|
|
271
|
-
text: "I'll generate a calming ambient piece.",
|
|
272
|
-
action: "MUSIC_GENERATION"
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
]
|
|
276
|
-
]
|
|
277
|
-
};
|
|
278
|
-
var musicGeneration_default = musicGeneration;
|
|
279
|
-
|
|
280
|
-
// src/index.ts
|
|
281
|
-
var sunoPlugin = {
|
|
282
|
-
name: "suno",
|
|
283
|
-
description: "Suno AI Music Generation Plugin for Eliza",
|
|
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
|
-
}
|
|
299
|
-
};
|
|
300
|
-
var index_default = sunoPlugin;
|
|
301
|
-
export {
|
|
302
|
-
musicGeneration_default as CustomGenerateMusic,
|
|
303
|
-
musicGeneration_default as ExtendAudio,
|
|
304
|
-
musicGeneration_default as GenerateMusic,
|
|
305
|
-
musicGeneration_default as MusicGeneration,
|
|
306
|
-
SunoProvider,
|
|
307
|
-
index_default as default,
|
|
308
|
-
sunoPlugin,
|
|
309
|
-
sunoStatusProvider
|
|
310
|
-
};
|
|
311
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers/suno.ts","../src/actions/musicGeneration.ts","../src/index.ts"],"sourcesContent":["import {\n type IAgentRuntime,\n type Memory,\n type Provider,\n type RecordLlmCallDetails,\n recordLlmCall,\n type State,\n} from '@elizaos/core';\n\nexport interface SunoConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class SunoProvider {\n private apiKey: string;\n private baseUrl: string;\n\n static async get(\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State\n ): Promise<SunoProvider> {\n const apiKey = runtime.getSetting('SUNO_API_KEY');\n if (typeof apiKey !== 'string' || !apiKey) {\n throw new Error('SUNO_API_KEY is required');\n }\n return new SunoProvider({ apiKey });\n }\n\n constructor(config: SunoConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || 'https://api.suno.ai/v1';\n }\n\n async get(\n _runtime: IAgentRuntime,\n _message: Memory,\n _state?: State\n ): Promise<{ status: string }> {\n return { status: 'ready' };\n }\n\n async request(runtime: IAgentRuntime, endpoint: string, options: RequestInit = {}) {\n const url = `${this.baseUrl}${endpoint}`;\n const headers = {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n ...options.headers,\n };\n\n const body = typeof options.body === 'string' ? options.body : '';\n const details: RecordLlmCallDetails = {\n model: 'suno',\n modelVersion: 'api-v1',\n systemPrompt: 'Suno music generation API request',\n userPrompt: body,\n temperature: readTemperature(body),\n maxTokens: 0,\n purpose: 'action',\n actionType: `suno.fetch${endpoint}`,\n };\n\n return recordLlmCall(runtime, details, async () => {\n const response = await fetch(url, {\n ...options,\n headers,\n });\n\n if (!response.ok) {\n throw new Error(`Suno API error: ${response.statusText}`);\n }\n\n const data = await response.json();\n details.response = JSON.stringify({ suno_response: data });\n return data;\n });\n }\n}\n\nfunction readTemperature(body: string): number {\n if (!body) return 0;\n try {\n const parsed = JSON.parse(body) as { temperature?: unknown };\n return typeof parsed.temperature === 'number' ? parsed.temperature : 0;\n } catch {\n return 0;\n }\n}\n\nexport const sunoStatusProvider: Provider = {\n name: 'SUNO_STATUS',\n description: 'Suno music generation status',\n descriptionCompressed: 'Suno generation availability.',\n contexts: ['media'],\n contextGate: { anyOf: ['media'] },\n cacheStable: false,\n cacheScope: 'turn',\n get: async (runtime: IAgentRuntime) => {\n const configured = Boolean(runtime.getSetting('SUNO_API_KEY'));\n return {\n text: JSON.stringify(\n {\n suno: {\n configured,\n status: configured ? 'ready' : 'missing_api_key',\n action: 'MUSIC_GENERATION',\n subactions: ['generate', 'custom', 'extend'],\n },\n },\n null,\n 2\n ),\n data: { configured },\n values: { sunoConfigured: configured },\n };\n },\n};\n\nexport interface GenerateParams {\n prompt: string;\n duration?: number;\n temperature?: number;\n topK?: number;\n topP?: number;\n classifier_free_guidance?: number;\n}\n\nexport interface CustomGenerateParams extends GenerateParams {\n reference_audio?: string;\n style?: string;\n bpm?: number;\n key?: string;\n mode?: string;\n}\n\nexport interface ExtendParams {\n audio_id: string;\n duration: number;\n}\n\nexport interface GenerationResponse {\n id: string;\n status: 'pending' | 'processing' | 'completed' | 'failed';\n audio_url?: string;\n error?: string;\n}\n","import type {\n Action,\n ActionResult,\n HandlerCallback,\n IAgentRuntime,\n Memory,\n State,\n} from '@elizaos/core';\nimport { SunoProvider } from '../providers/suno';\n\ntype MusicGenerationSubaction = 'generate' | 'custom' | 'extend';\n\ntype MusicGenerationParams = {\n action?: MusicGenerationSubaction | string;\n subaction?: MusicGenerationSubaction | string;\n operation?: MusicGenerationSubaction | string;\n prompt?: string;\n duration?: number;\n temperature?: number;\n topK?: number;\n topP?: number;\n classifier_free_guidance?: number;\n reference_audio?: string;\n style?: string;\n bpm?: number;\n key?: string;\n mode?: string;\n audio_id?: string;\n};\n\nconst SUNO_ACTION_TIMEOUT_MS = 30_000;\nconst MAX_SUNO_RESPONSE_BYTES = 4000;\n\nfunction paramsFromMessageAndOptions(\n message: Memory,\n options?: Record<string, unknown>\n): MusicGenerationParams {\n const content =\n message.content && typeof message.content === 'object'\n ? (message.content as Record<string, unknown>)\n : {};\n const parameters =\n options?.parameters && typeof options.parameters === 'object'\n ? (options.parameters as Record<string, unknown>)\n : {};\n return { ...content, ...options, ...parameters } as MusicGenerationParams;\n}\n\nfunction normalizeSubaction(value: unknown): MusicGenerationSubaction | null {\n const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';\n if (normalized === 'generate' || normalized === 'custom' || normalized === 'extend') {\n return normalized;\n }\n if (normalized === 'custom_generate' || normalized === 'custom-generate') return 'custom';\n if (normalized === 'extend_audio' || normalized === 'extend-audio') return 'extend';\n return null;\n}\n\nfunction inferSubaction(message: Memory, params: MusicGenerationParams): MusicGenerationSubaction {\n const explicit = normalizeSubaction(params.action ?? params.subaction ?? params.operation);\n if (explicit) return explicit;\n const text = (message.content?.text ?? '').toLowerCase();\n if (params.audio_id || /\\b(extend|lengthen|longer|add \\d+.*seconds?)\\b/.test(text)) {\n return 'extend';\n }\n if (\n params.reference_audio ||\n params.style ||\n params.bpm ||\n params.key ||\n params.mode ||\n /\\b(custom|style|bpm|key|mode|reference)\\b/.test(text)\n ) {\n return 'custom';\n }\n return 'generate';\n}\n\nfunction promptFromParams(message: Memory, params: MusicGenerationParams): string {\n const prompt = typeof params.prompt === 'string' ? params.prompt.trim() : '';\n if (prompt) return prompt;\n return (message.content?.text ?? '').trim();\n}\n\nfunction numberOrDefault(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\nfunction generationBody(params: MusicGenerationParams, prompt: string): Record<string, unknown> {\n return {\n prompt,\n duration: numberOrDefault(params.duration, 30),\n temperature: numberOrDefault(params.temperature, 1.0),\n top_k: numberOrDefault(params.topK, 250),\n top_p: numberOrDefault(params.topP, 0.95),\n classifier_free_guidance: numberOrDefault(params.classifier_free_guidance, 3.0),\n };\n}\n\nexport const musicGeneration: Action = {\n name: 'MUSIC_GENERATION',\n contexts: ['media'],\n contextGate: { anyOf: ['media'] },\n roleGate: { minRole: 'USER' },\n description:\n '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.',\n descriptionCompressed: 'Suno music generation router action: generate, custom, extend.',\n similes: [\n 'GENERATE_MUSIC',\n 'CREATE_MUSIC',\n 'MAKE_MUSIC',\n 'COMPOSE_MUSIC',\n 'CUSTOM_GENERATE_MUSIC',\n 'EXTEND_AUDIO',\n ],\n parameters: [\n {\n name: 'action',\n description: 'Suno operation: generate, custom, or extend.',\n required: false,\n schema: { type: 'string', enum: ['generate', 'custom', 'extend'] },\n },\n {\n name: 'subaction',\n description: 'Legacy alias for action.',\n required: false,\n schema: { type: 'string' },\n },\n {\n name: 'prompt',\n description: 'Music prompt for generate/custom.',\n required: false,\n schema: { type: 'string' },\n },\n {\n name: 'audio_id',\n description: 'Existing Suno audio id for extend.',\n required: false,\n schema: { type: 'string' },\n },\n {\n name: 'duration',\n description: 'Generation duration or extension seconds.',\n required: false,\n schema: { type: 'number', default: 30 },\n },\n ],\n validate: async (runtime: IAgentRuntime, message: Memory): Promise<boolean> => {\n if (!runtime.getSetting('SUNO_API_KEY')) return false;\n const text = (message.content?.text ?? '').toLowerCase();\n return /\\b(generate|create|make|compose|extend|music|song|audio|track)\\b/.test(text);\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state: State,\n options: Record<string, unknown> | undefined,\n callback?: HandlerCallback\n ): Promise<ActionResult> => {\n try {\n const params = paramsFromMessageAndOptions(message, options);\n const subaction = inferSubaction(message, params);\n const provider = await SunoProvider.get(runtime, message, state);\n\n let endpoint = '/generate';\n let body: Record<string, unknown>;\n\n if (subaction === 'extend') {\n if (!params.audio_id || !params.duration) {\n throw new Error('Missing required parameters: audio_id and duration');\n }\n endpoint = '/extend';\n body = {\n audio_id: params.audio_id,\n duration: params.duration,\n };\n } else {\n const prompt = promptFromParams(message, params);\n if (!prompt) {\n throw new Error('Missing required parameter: prompt');\n }\n body = generationBody(params, prompt);\n if (subaction === 'custom') {\n endpoint = '/custom-generate';\n body = {\n ...body,\n reference_audio: params.reference_audio,\n style: params.style,\n bpm: params.bpm,\n key: params.key,\n mode: params.mode,\n };\n }\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), SUNO_ACTION_TIMEOUT_MS);\n const response = await provider\n .request(runtime, endpoint, {\n method: 'POST',\n body: JSON.stringify(body),\n signal: controller.signal,\n })\n .finally(() => clearTimeout(timeout));\n const cappedResponse =\n JSON.stringify(response).length > MAX_SUNO_RESPONSE_BYTES\n ? {\n truncated: true,\n preview: JSON.stringify(response).slice(0, MAX_SUNO_RESPONSE_BYTES),\n }\n : response;\n\n await callback?.({\n text:\n subaction === 'extend'\n ? `Successfully extended audio ${params.audio_id}`\n : `Successfully submitted ${subaction} music generation`,\n content: cappedResponse,\n });\n\n return {\n success: true,\n text:\n subaction === 'extend'\n ? `Successfully extended audio ${params.audio_id}`\n : `Successfully submitted ${subaction} music generation`,\n data: { subaction, response: cappedResponse },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n const text = `Music generation failed: ${errorMessage}`;\n await callback?.({\n text,\n error,\n });\n return { success: false, text, error: errorMessage };\n }\n },\n examples: [\n [\n {\n name: '{{user1}}',\n content: {\n text: 'Generate a relaxing ambient track',\n prompt: 'A peaceful ambient soundscape with gentle waves and soft pads',\n duration: 45,\n },\n },\n {\n name: '{{agent}}',\n content: {\n text: \"I'll generate a calming ambient piece.\",\n action: 'MUSIC_GENERATION',\n },\n },\n ],\n ],\n};\n\nexport default musicGeneration;\n","import type { Plugin } from '@elizaos/core';\nimport musicGeneration from './actions/musicGeneration';\nimport { SunoProvider, sunoStatusProvider } from './providers/suno';\n\nexport {\n SunoProvider,\n musicGeneration as MusicGeneration,\n musicGeneration as GenerateMusic,\n musicGeneration as CustomGenerateMusic,\n musicGeneration as ExtendAudio,\n sunoStatusProvider,\n};\n\nexport const sunoPlugin: Plugin = {\n name: 'suno',\n description: 'Suno AI Music Generation Plugin for Eliza',\n actions: [musicGeneration],\n providers: [sunoStatusProvider],\n // Self-declared auto-enable: activate when SUNO_API_KEY is set OR when\n // media.audio is configured to use the suno provider with own-key mode.\n autoEnable: {\n shouldEnable: (env, config) => {\n const key = env.SUNO_API_KEY;\n if (typeof key === 'string' && key.trim() !== '') return true;\n const media = config?.media as Record<string, unknown> | undefined;\n const audio = media?.audio as\n | { enabled?: unknown; mode?: unknown; provider?: unknown }\n | undefined;\n return Boolean(\n audio &&\n audio.enabled !== false &&\n audio.mode === 'own-key' &&\n audio.provider === 'suno'\n );\n },\n },\n};\n\nexport default sunoPlugin;\n"],"mappings":"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","names":[]}
|