@j-o-r/hello-dave 0.1.1 → 0.1.5

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.
Files changed (173) hide show
  1. package/CHANGELOG.md +42 -25
  2. package/README.md +81 -221
  3. package/TODO.md +173 -35
  4. package/agents/agent_creator.js +105 -0
  5. package/agents/agent_creator.prompt.md +371 -0
  6. package/agents/ask_agent.js +64 -127
  7. package/agents/claude_agent.js +68 -0
  8. package/agents/code_agent.js +55 -135
  9. package/agents/code_agent.prompt.md +50 -0
  10. package/agents/echo_agent.js +76 -0
  11. package/agents/financial_expert.js +75 -0
  12. package/agents/gpt_agent.js +52 -103
  13. package/agents/gpt_code.js +81 -0
  14. package/agents/grok_agent.js +58 -114
  15. package/agents/minimax_agent.js +92 -0
  16. package/agents/mureka_agent.js +77 -0
  17. package/agents/planner_agent.js +172 -0
  18. package/agents/stability_agent.js +87 -0
  19. package/agents/test_agent.js +75 -157
  20. package/agents/weather_agent.js +73 -0
  21. package/agents/workflow_agent.js +189 -0
  22. package/bin/dave.js +436 -184
  23. package/docs/bin-dave.md +85 -35
  24. package/docs/cdn-ssh.md +100 -0
  25. package/docs/creating-agents.md +301 -0
  26. package/docs/creating-toolsets.md +336 -0
  27. package/docs/docs-organization.md +48 -0
  28. package/docs/project-overview.md +86 -51
  29. package/lib/API/elevenlabs.io/music.compose.md +441 -0
  30. package/lib/API/elevenlabs.io/music.create-composition-plan.md +370 -0
  31. package/lib/API/elevenlabs.io/music.stream.md +425 -0
  32. package/lib/API/lalal.ai/lalal.js +445 -0
  33. package/lib/API/lalal.ai/openapi.json +2614 -0
  34. package/lib/API/minimax/ImageToolset.js +82 -37
  35. package/lib/API/minimax/MusicToolset.js +125 -79
  36. package/lib/API/minimax/VideoToolset.js +170 -167
  37. package/lib/API/minimax/image.js +5 -1
  38. package/lib/API/minimax/music.js +210 -23
  39. package/lib/API/minimax/video.js +242 -53
  40. package/lib/API/mureka/MusicToolset.js +646 -0
  41. package/lib/API/mureka/README.md +41 -0
  42. package/lib/API/mureka/index.js +7 -0
  43. package/lib/API/mureka/music.js +658 -0
  44. package/lib/API/openai.com/index.js +7 -0
  45. package/lib/API/openai.com/{reponses/text.js → responses.js} +64 -18
  46. package/lib/API/openai.com/video.create.character.md +40 -0
  47. package/lib/API/openai.com/video.create.md +219 -0
  48. package/lib/API/openai.com/video.delete.md +44 -0
  49. package/lib/API/openai.com/video.download.md +31 -0
  50. package/lib/API/openai.com/video.edit.md +155 -0
  51. package/lib/API/openai.com/video.extend.md +166 -0
  52. package/lib/API/openai.com/video.fetch.character.md +43 -0
  53. package/lib/API/openai.com/video.js +784 -0
  54. package/lib/API/openai.com/video.list.md +201 -0
  55. package/lib/API/openai.com/video.remix.md +175 -0
  56. package/lib/API/openai.com/video.retrieve.md +139 -0
  57. package/lib/API/openai.com/videoToolset.js +616 -0
  58. package/lib/API/stability.ai/ImageToolset.js +131 -40
  59. package/lib/API/stability.ai/MusicToolset.js +79 -47
  60. package/lib/API/stability.ai/audio.js +63 -131
  61. package/lib/API/x.ai/chat.responses.md +1040 -0
  62. package/lib/API/x.ai/image.js +229 -59
  63. package/lib/API/x.ai/imageToolset.js +376 -0
  64. package/lib/API/x.ai/index.js +1 -1
  65. package/lib/API/x.ai/responses.js +9 -18
  66. package/lib/Agent.js +271 -0
  67. package/lib/Agent.js.old +284 -0
  68. package/lib/AgentLauncher.js +593 -0
  69. package/lib/Cli.js +87 -13
  70. package/lib/Prompt.js +23 -1
  71. package/lib/Session.js +5 -4
  72. package/lib/ToolSet.js +102 -6
  73. package/lib/agentLoader.js +369 -0
  74. package/lib/cdn.js +67 -231
  75. package/lib/{CdnToolset.js → cdnToolset.js} +47 -64
  76. package/lib/defaultToolsets.js +43 -0
  77. package/lib/fafs.js +1 -1
  78. package/lib/genericToolset.js +442 -119
  79. package/lib/handOffToolset.js +179 -0
  80. package/lib/index.js +34 -27
  81. package/lib/toolsetLoader.js +248 -0
  82. package/package.json +10 -4
  83. package/types/API/lalal.ai/lalal.d.ts +116 -0
  84. package/types/API/minimax/image.d.ts +2 -1
  85. package/types/API/minimax/music.d.ts +189 -26
  86. package/types/API/minimax/video.d.ts +100 -31
  87. package/types/API/mureka/index.d.ts +7 -0
  88. package/types/API/mureka/music.d.ts +472 -0
  89. package/types/API/openai.com/index.d.ts +7 -0
  90. package/types/API/openai.com/{reponses/text.d.ts → responses.d.ts} +11 -11
  91. package/types/API/openai.com/video.d.ts +409 -0
  92. package/types/API/openai.com/videoToolset.d.ts +24 -0
  93. package/types/API/stability.ai/audio.d.ts +14 -103
  94. package/types/API/stability.ai/image.d.ts +2 -2
  95. package/types/API/x.ai/image.d.ts +138 -26
  96. package/types/API/x.ai/imageToolset.d.ts +3 -0
  97. package/types/API/x.ai/index.d.ts +1 -1
  98. package/types/API/x.ai/responses.d.ts +4 -4
  99. package/types/Agent.d.ts +123 -0
  100. package/types/AgentLauncher.d.ts +250 -0
  101. package/types/Cli.d.ts +28 -8
  102. package/types/Prompt.d.ts +23 -5
  103. package/types/Session.d.ts +1 -1
  104. package/types/ToolSet.d.ts +10 -0
  105. package/types/agentLoader.d.ts +78 -0
  106. package/types/cdn.d.ts +15 -90
  107. package/types/defaultToolsets.d.ts +9 -0
  108. package/types/fafs.d.ts +1 -1
  109. package/types/genericToolset.d.ts +1 -1
  110. package/types/handOffToolset.d.ts +28 -0
  111. package/types/index.d.ts +19 -17
  112. package/types/toolsetLoader.d.ts +114 -0
  113. package/utils/format_log.js +101 -23
  114. package/utils/launch_agent.js +18 -0
  115. package/utils/list_sessions.sh +13 -5
  116. package/utils/search_sessions.sh +65 -29
  117. package/utils/toolsets.js +33 -0
  118. package/README.md.bak.1779452127 +0 -240
  119. package/agents/codeserver.sh +0 -47
  120. package/agents/daisy_agent.js +0 -173
  121. package/agents/docs_agent.js +0 -148
  122. package/agents/memory_agent.js +0 -263
  123. package/agents/minimax.js +0 -173
  124. package/agents/npm_agent.js +0 -202
  125. package/agents/prompt_agent.js +0 -133
  126. package/agents/readme_agent.js +0 -148
  127. package/agents/spawn_agent.js +0 -160
  128. package/agents/stability.js +0 -173
  129. package/agents/todo_agent.js +0 -175
  130. package/bin/codeDave +0 -58
  131. package/docs/agent-dave-websocket-protocol.md +0 -180
  132. package/docs/agent-manager.md +0 -244
  133. package/docs/codeserver-pattern.md +0 -191
  134. package/docs/generic-toolset.md +0 -326
  135. package/docs/howtos/agent-networking.md +0 -253
  136. package/docs/howtos/spawn-agents.md.bak +0 -200
  137. package/docs/howtos/spawn-agents.md.bak_new +0 -200
  138. package/docs/multi-agent-clusters.md +0 -265
  139. package/docs/music-toolsets.md +0 -137
  140. package/docs/path-resolution-best-practices.md +0 -104
  141. package/docs/plans/minimax-music-generation.md +0 -80
  142. package/docs/plans/unified-agent-architecture.md +0 -146
  143. package/docs/plans/websocket-streaming-plan.md.bak +0 -317
  144. package/docs/prompt/spawn_agent.md +0 -175
  145. package/docs/prompt/spawn_agent.md.bak +0 -201
  146. package/docs/prompt/task_clarification_and_documentation.md +0 -35
  147. package/docs/prompt-class.md +0 -141
  148. package/docs/todo-archive-infra-2026-04-21.md +0 -15
  149. package/docs/todo-archive-v0.0.8.md +0 -1
  150. package/docs/todo-archive-v0.1.0.md +0 -32
  151. package/docs/todo-archive.md +0 -44
  152. package/docs/tools-syntax-validation.md +0 -121
  153. package/docs/toolset.md +0 -164
  154. package/docs/xai-responses.md +0 -111
  155. package/docs/xai_collections.md +0 -106
  156. package/lib/API/x.ai/ImageToolset.js +0 -165
  157. package/lib/API/x.ai/text.js +0 -415
  158. package/lib/AgentClient.js +0 -248
  159. package/lib/AgentManager.js +0 -245
  160. package/lib/AgentServer.js +0 -404
  161. package/lib/wsCli.js +0 -287
  162. package/lib/wsIO.js +0 -90
  163. package/types/API/x.ai/text.d.ts +0 -286
  164. package/types/AgentClient.d.ts +0 -109
  165. package/types/AgentManager.d.ts +0 -100
  166. package/types/AgentServer.d.ts +0 -89
  167. package/types/wsCli.d.ts +0 -17
  168. package/types/wsIO.d.ts +0 -30
  169. package/utils/test.sh +0 -46
  170. /package/docs/{suggestions.md → _notes/token-counts.md} +0 -0
  171. /package/lib/API/openai.com/{reponses/MESSAGES.md → MESSAGES.md} +0 -0
  172. /package/types/API/{x.ai/ImageToolset.d.ts → mureka/MusicToolset.d.ts} +0 -0
  173. /package/types/{CdnToolset.d.ts → cdnToolset.d.ts} +0 -0
@@ -3,16 +3,15 @@
3
3
  * @module minimax/ImageToolset
4
4
  * @description Comprehensive ToolSet for the Minimax Image Generation API.
5
5
  *
6
- * This ToolSet exposes the full Minimax Image API with every available option
7
- * and detailed return values, following the same pattern as lib/genericToolset.js
8
- * and MusicToolset.js.
9
- *
10
- * It is designed to be used directly by AI agents or merged into larger toolsets.
6
+ * This ToolSet exposes the Minimax Image API with descriptive function-call
7
+ * schemas and compact, self-describing function responses. Tool responses
8
+ * preserve durable references such as local paths, temporary image URLs, seeds,
9
+ * trace IDs, and source image references so the assistant can repeat those
10
+ * values in a normal assistant message before old raw tool I/O is pruned.
11
11
  *
12
12
  * @example
13
13
  * import imageToolset from './lib/API/minimax/ImageToolset.js';
14
14
  *
15
- * // Use in an agent:
16
15
  * const toolset = agent.getToolset();
17
16
  * toolset.merge(imageToolset);
18
17
  */
@@ -22,6 +21,54 @@ import * as minimax from './image.js';
22
21
 
23
22
  const tools = new ToolSet('auto');
24
23
 
24
+ /**
25
+ * Serialize a tool response as pretty JSON.
26
+ *
27
+ * @param {Record<string, unknown>} value Response payload to serialize.
28
+ * @returns {string} Pretty JSON response for function-calling output.
29
+ */
30
+ function json(value) {
31
+ return JSON.stringify(value, null, 2);
32
+ }
33
+
34
+ /**
35
+ * Build a compact, self-describing Minimax image tool response.
36
+ *
37
+ * @param {string} tool Tool/function name that produced the response.
38
+ * @param {Record<string, unknown>} params Original tool parameters.
39
+ * @param {Record<string, unknown>} result Wrapper result object.
40
+ * @returns {string} JSON response containing durable references and assistant instructions.
41
+ */
42
+ function imageToolResponse(tool, params, result) {
43
+ const imageUrls = Array.isArray(result.image_urls) ? result.image_urls : [];
44
+ const imageBase64 = Array.isArray(result.image_base64) ? result.image_base64 : [];
45
+ const localPaths = Array.isArray(result.local_paths) ? result.local_paths : [];
46
+
47
+ return json({
48
+ tool,
49
+ success: true,
50
+ trace_id: result.id,
51
+ prompt: params.prompt,
52
+ model: params.model || 'image-01',
53
+ aspect_ratio: params.aspect_ratio || '1:1',
54
+ response_format: params.response_format || 'url',
55
+ seed: params.seed,
56
+ image_urls: imageUrls,
57
+ image_url: imageUrls[0],
58
+ image_url_count: imageUrls.length,
59
+ has_base64_output: imageBase64.length > 0,
60
+ image_base64_count: imageBase64.length,
61
+ local_paths: localPaths,
62
+ local_path: localPaths[0],
63
+ metadata: result.metadata,
64
+ duration_ms: result.duration,
65
+ source_subject_reference: params.subject_reference,
66
+ note:
67
+ 'Assistant: tell the user the exact local_path/local_paths and, when present, image_url/image_urls, trace_id, and seed in your normal response. ' +
68
+ 'Use local_path as the durable local reference for follow-up file/CDN operations. Minimax image URLs are temporary and may expire.'
69
+ });
70
+ }
71
+
25
72
  /* ============================================================
26
73
  CORE IMAGE GENERATION (Text-to-Image + Image-to-Image)
27
74
  ============================================================ */
@@ -29,22 +76,23 @@ const tools = new ToolSet('auto');
29
76
  tools.add(
30
77
  'generate_image',
31
78
  'Generate images using the Minimax Image Generation API. ' +
32
- 'Supports both Text-to-Image and Image-to-Image (via subject_reference). ' +
33
- 'All generated images are automatically saved locally in .cache/minimax/.',
79
+ 'Supports both Text-to-Image and Image-to-Image via subject_reference. ' +
80
+ 'All generated images are automatically saved locally in .cache/minimax/. ' +
81
+ 'After success, include the exact local_path/local_paths in your assistant response. ' +
82
+ 'If image_url/image_urls are returned, include them too, but mention they are temporary. ' +
83
+ 'Also preserve trace_id and seed when present for reproducibility or debugging.',
34
84
  {
35
85
  type: 'object',
36
86
  properties: {
37
87
  prompt: {
38
88
  type: 'string',
39
- description: 'Text description of the image, max 1500 characters. ' +
40
- 'Example: "A serene mountain landscape at sunset, photorealistic, cinematic lighting"'
89
+ description: 'Text description of the image, max 1500 characters. Example: "A serene mountain landscape at sunset, photorealistic, cinematic lighting".'
41
90
  },
42
91
  model: {
43
92
  type: 'string',
44
93
  enum: ['image-01', 'image-01-live'],
45
94
  default: 'image-01',
46
- description: 'Model to use. "image-01" = standard (text-to-image and img2img). ' +
47
- '"image-01-live" = optimized for image-to-image.'
95
+ description: 'Model to use. "image-01" = standard text-to-image and image-to-image. "image-01-live" = optimized for image-to-image.'
48
96
  },
49
97
  aspect_ratio: {
50
98
  type: 'string',
@@ -54,8 +102,7 @@ tools.add(
54
102
  },
55
103
  width: {
56
104
  type: 'integer',
57
- description: 'Image width in pixels (512-2048, must be divisible by 8). ' +
58
- 'Only effective for model "image-01". aspect_ratio takes priority if both are provided.'
105
+ description: 'Image width in pixels (512-2048, divisible by 8). Only effective for model "image-01". aspect_ratio takes priority if both are provided.'
59
106
  },
60
107
  height: {
61
108
  type: 'integer',
@@ -65,8 +112,7 @@ tools.add(
65
112
  type: 'string',
66
113
  enum: ['url', 'base64'],
67
114
  default: 'url',
68
- description: 'Output format. "url" returns temporary signed links (expire after 24h). ' +
69
- '"base64" returns raw base64 data. Default is "url" (user preference).'
115
+ description: 'Output format. Prefer "url" where possible. URL links are temporary and expire after about 24 hours. Generated output is also saved to local_path.'
70
116
  },
71
117
  seed: {
72
118
  type: 'integer',
@@ -89,16 +135,19 @@ tools.add(
89
135
  items: {
90
136
  type: 'object',
91
137
  properties: {
92
- type: { type: 'string', enum: ['character'], description: 'Subject type. Currently only "character" supported.' },
138
+ type: {
139
+ type: 'string',
140
+ enum: ['character'],
141
+ description: 'Subject type. Currently only "character" supported.'
142
+ },
93
143
  image_file: {
94
144
  type: 'string',
95
- description: 'Reference image URL or Base64 data URL (data:image/jpeg;base64,...). ' +
96
- 'Best results with front-facing portrait photos (JPG/PNG < 10MB).'
145
+ description: 'Reference image URL or Base64 data URL (data:image/jpeg;base64,...). Prefer image_url/public URL where possible. Best results with front-facing portrait photos (JPG/PNG < 10MB).'
97
146
  }
98
147
  },
99
148
  required: ['type', 'image_file']
100
149
  },
101
- description: 'For Image-to-Image generation. Array of subject references (currently supports character portraits).'
150
+ description: 'For Image-to-Image generation. Array of subject references. Preserve the exact source image_file in the final assistant response when it matters for follow-up.'
102
151
  },
103
152
  extra: {
104
153
  type: 'object',
@@ -109,18 +158,7 @@ tools.add(
109
158
  },
110
159
  async (params) => {
111
160
  const result = await minimax.requestImage(params.prompt, params);
112
-
113
- return JSON.stringify({
114
- image_urls: result.image_urls,
115
- image_base64: result.image_base64,
116
- local_paths: result.local_paths,
117
- metadata: result.metadata,
118
- trace_id: result.id,
119
- duration_ms: result.duration,
120
- raw_response: result.raw,
121
- note: 'Images have been automatically saved to local_paths. ' +
122
- 'Use response_format="base64" if you need the raw data instead of URLs.'
123
- }, null, 2);
161
+ return imageToolResponse('generate_image', params, result);
124
162
  }
125
163
  );
126
164
 
@@ -131,13 +169,14 @@ tools.add(
131
169
  tools.add(
132
170
  'save_image_to_local',
133
171
  'Save image data (URL or base64) to a local file in .cache/minimax/. ' +
134
- 'Useful when you already have image data from another source or previous generation.',
172
+ 'Useful when you already have image data from another source or previous generation. ' +
173
+ 'After success, include the exact local_path in your assistant response so it remains available after function-call history is pruned.',
135
174
  {
136
175
  type: 'object',
137
176
  properties: {
138
177
  image_data: {
139
178
  type: 'string',
140
- description: 'Either a URL or a base64-encoded image string (with or without data: prefix).'
179
+ description: 'Either an image URL or a base64-encoded image string (with or without data: prefix). Prefer URL/image_url where possible.'
141
180
  },
142
181
  filename_prefix: {
143
182
  type: 'string',
@@ -159,11 +198,17 @@ tools.add(
159
198
  params.index ?? 0
160
199
  );
161
200
 
162
- return JSON.stringify({
201
+ return json({
202
+ tool: 'save_image_to_local',
203
+ success: true,
163
204
  local_path: localPath,
164
- note: 'File saved successfully.'
205
+ localPath,
206
+ filename_prefix: params.filename_prefix || 'minimax-image',
207
+ index: params.index ?? 0,
208
+ source_image_data_type: typeof params.image_data === 'string' && params.image_data.startsWith('http') ? 'url' : 'base64',
209
+ note: 'Assistant: tell the user the exact local_path in your normal response. Use local_path as the durable reference for follow-up file/CDN operations.'
165
210
  });
166
211
  }
167
212
  );
168
213
 
169
- export default tools;
214
+ export default tools;
@@ -5,8 +5,8 @@
5
5
  *
6
6
  * Exposes four clear workflows matching the underlying music.js design:
7
7
  * - create_music → text-to-music (music-2.6 / music-2.6-free)
8
- * - change_music → cover generation (music-cover) with strict reference rules
9
- * - analyze_music → preprocess reference audio for two-step covers
8
+ * - change_music → cover generation (music-cover) model fixed to 'music-cover'
9
+ * - analyze_music → preprocess reference audio for two-step covers (model fixed to 'music-cover')
10
10
  * - lyrics → generate, edit or continue song lyrics
11
11
  *
12
12
  * Designed for direct use by AI agents.
@@ -14,6 +14,10 @@
14
14
  * Important notes:
15
15
  * - Lyrics are optional for both instrumental and non-instrumental music generation.
16
16
  * - Streaming is not supported; the `stream` parameter is always false and not exposed as an option.
17
+ * - For change_music and analyze_music: model is fixed to 'music-cover' (recommended paid model).
18
+ * - For change_music (music-cover models): prompt is strictly limited to 300 characters.
19
+ * - audio_setting is fixed internally (44100 Hz / 256 kbps / mp3) — not exposed to users.
20
+ * - **Critical for two-step covers**: When using `cover_feature_id` + non-instrumental (`is_instrumental: false`), the `lyrics` parameter is **mandatory**.
17
21
  */
18
22
 
19
23
  import ToolSet from '../../ToolSet.js';
@@ -21,6 +25,49 @@ import * as minimax from './music.js';
21
25
 
22
26
  const tools = new ToolSet('auto');
23
27
 
28
+ /**
29
+ * Serialize a tool response as pretty JSON.
30
+ *
31
+ * @param {Record<string, unknown>} value Response payload to serialize.
32
+ * @returns {string} Pretty JSON response for function-calling output.
33
+ */
34
+ function json(value) {
35
+ return JSON.stringify(value, null, 2);
36
+ }
37
+
38
+ /**
39
+ * Build a compact, self-describing music-generation tool response.
40
+ *
41
+ * The response intentionally keeps durable follow-up references and avoids the
42
+ * full raw API response so old function-call transcripts can be pruned safely
43
+ * after the assistant has repeated the important values in normal text.
44
+ *
45
+ * @param {string} tool Tool/function name that produced the result.
46
+ * @param {Record<string, unknown>} params Tool parameters supplied by the model.
47
+ * @param {{audio_url?: string, local_path?: string, duration?: number}} result Wrapper result.
48
+ * @param {string} note Assistant-facing preservation note.
49
+ * @returns {string} Pretty JSON response for function-calling output.
50
+ */
51
+ function musicToolResponse(tool, params, result, note) {
52
+ return json({
53
+ tool,
54
+ success: true,
55
+ audio_url: result.audio_url,
56
+ audioUrl: result.audio_url,
57
+ local_path: result.local_path,
58
+ localPath: result.local_path,
59
+ duration_ms: result.duration,
60
+ model: tool === 'change_music' ? 'music-cover' : (params.model || 'music-2.6'),
61
+ prompt: params.prompt,
62
+ is_instrumental: params.is_instrumental ?? false,
63
+ output_format: params.output_format || 'url',
64
+ source_audio_url: params.audio_url,
65
+ has_audio_base64: Boolean(params.audio_base64),
66
+ cover_feature_id: params.cover_feature_id,
67
+ note
68
+ });
69
+ }
70
+
24
71
  /* ============================================================
25
72
  WORKFLOW 1: CREATE MUSIC (Text-to-Music)
26
73
  ============================================================ */
@@ -29,8 +76,9 @@ tools.add(
29
76
  'create_music',
30
77
  'Create original music from a text prompt and optional lyrics. ' +
31
78
  'Lyrics are optional for both instrumental and non-instrumental tracks. ' +
32
- 'Uses music-2.6 or music-2.6-free models. ' +
33
- 'No reference audio is allowed — this is pure text-to-music generation.',
79
+ 'Uses minimax music-2.6 or music-2.6-free models. ' +
80
+ 'No reference audio is allowed — this is pure text-to-music generation. ' +
81
+ 'After success, include the returned local_path and audio_url exactly in your assistant response; these are needed for download/playback or follow-up audio operations.',
34
82
  {
35
83
  type: 'object',
36
84
  properties: {
@@ -65,16 +113,7 @@ tools.add(
65
113
  type: 'string',
66
114
  enum: ['url', 'hex'],
67
115
  default: 'url',
68
- description: 'Output format. Default "url".'
69
- },
70
- audio_setting: {
71
- type: 'object',
72
- properties: {
73
- sample_rate: { type: 'integer', enum: [16000, 24000, 32000, 44100], default: 44100 },
74
- bitrate: { type: 'integer', enum: [32000, 64000, 128000, 256000], default: 256000 },
75
- format: { type: 'string', enum: ['mp3', 'wav', 'pcm'], default: 'mp3' }
76
- },
77
- description: 'Audio output configuration.'
116
+ description: 'Output format. Default "url". Prefer "url" for durable assistant-visible references.'
78
117
  },
79
118
  extra: { type: 'object', description: 'Additional parameters.' }
80
119
  },
@@ -83,60 +122,71 @@ tools.add(
83
122
  async (params) => {
84
123
  const result = await minimax.createMusic(params.prompt, params);
85
124
 
86
- return JSON.stringify({
87
- audio_url: result.audio_url,
88
- local_path: result.local_path,
89
- duration_ms: result.duration,
90
- raw_response: result.raw,
91
- note: 'Music created successfully with create_music (text-to-music workflow). ' +
92
- 'Audio saved to local_path.'
93
- }, null, 2);
125
+ return musicToolResponse(
126
+ 'create_music',
127
+ params,
128
+ result,
129
+ 'Music created successfully with create_music. Assistant: tell the user the exact local_path and audio_url. Use local_path/audio_url as durable references after raw function-call history is pruned.'
130
+ );
94
131
  }
95
132
  );
96
133
 
97
134
  /* ============================================================
98
- WORKFLOW 2: CHANGE MUSIC (Cover Generation)
135
+ WORKFLOW 2: CHANGE MUSIC (Cover Generation) — MODEL FIXED
99
136
  ============================================================ */
100
137
 
101
138
  tools.add(
102
139
  'change_music',
103
- 'Generate a cover version of a reference song or track. ' +
104
- 'Uses music-cover or music-cover-free models. ' +
140
+ 'Generate a cover version of a reference song or track with minimax.io. ' +
141
+ 'Uses the music-cover model (fixed — the recommended paid model; music-cover-free is not supported). ' +
105
142
  '**Strict rules**: Provide exactly ONE of audio_url/audio_base64 (direct one-step) ' +
106
143
  'OR cover_feature_id (two-step from analyze_music). Never both. ' +
144
+ '**Critical rule**: When using `cover_feature_id` + non-instrumental (`is_instrumental: false`), ' +
145
+ 'the `lyrics` parameter is **MANDATORY**. ' +
107
146
  'Lyrics are optional for direct reference (API can extract), required/recommended for cover_feature_id. ' +
108
- 'Lyrics are optional for both instrumental and non-instrumental covers.',
147
+ 'Lyrics are optional for both instrumental and non-instrumental covers. ' +
148
+ '**Important**: There are NO dedicated settings or parameters to control how closely the cover stays faithful to the original reference (e.g. no "strength", "fidelity", or "similarity" sliders). ' +
149
+ 'The `prompt` parameter fully controls the degree of adherence to the reference audio. ' +
150
+ 'To stay close to the original, craft detailed (but short) prompts such as:\n' +
151
+ '- "faithful cover, identical melody and arrangement to the original"\n' +
152
+ '- "very close vocal and instrumental cover, minimal changes"\n' +
153
+ '- "exact replica of the reference track"\n' +
154
+ 'Vague prompts may lead to more creative reinterpretations. ' +
155
+ '**Prompt limit**: Maximum 300 characters (enforced). ' +
156
+ '**audio_setting**: Fixed internally to 44100 Hz / 256 kbps / mp3 — not configurable. ' +
157
+ 'Model parameter is ignored (always "music-cover"). ' +
158
+ 'After success, include the returned local_path/audio_url and the source audio_url or cover_feature_id exactly in your assistant response.',
109
159
  {
110
160
  type: 'object',
111
161
  properties: {
112
162
  prompt: {
113
163
  type: 'string',
114
- description: 'Target style/mood for the cover (e.g. "same melody but jazz style"). Required.'
115
- },
116
- model: {
117
- type: 'string',
118
- enum: ['music-cover', 'music-cover-free'],
119
- default: 'music-cover',
120
- description: 'Cover model to use.'
164
+ maxLength: 300,
165
+ description: 'Target style/mood for the cover AND instructions for fidelity to the reference. ' +
166
+ 'Examples for staying faithful: "faithful cover, identical melody and arrangement to the original", ' +
167
+ '"very close vocal and instrumental cover, minimal changes", "exact replica of the reference track". ' +
168
+ 'No other parameters control closeness — the prompt is the only control. ' +
169
+ 'Maximum 300 characters. Required.'
121
170
  },
122
171
  audio_url: {
123
172
  type: 'string',
124
173
  description: 'Public URL of reference audio for direct one-step cover. ' +
125
- 'Mutually exclusive with cover_feature_id.'
174
+ 'Mutually exclusive with cover_feature_id. Prefer audio_url where possible because it is assistant-visible and durable.'
126
175
  },
127
176
  audio_base64: {
128
177
  type: 'string',
129
- description: 'Base64-encoded reference audio (alternative to audio_url).'
178
+ description: 'Base64-encoded reference audio (alternative to audio_url). Prefer audio_url where possible.'
130
179
  },
131
180
  cover_feature_id: {
132
181
  type: 'string',
133
182
  description: 'Feature ID from analyze_music() for two-step cover with modified lyrics. ' +
134
- 'Mutually exclusive with audio_url/audio_base64.'
183
+ '**Requires lyrics** when is_instrumental=false. ' +
184
+ 'Mutually exclusive with audio_url/audio_base64. Include this exact ID in the assistant response when it is used.'
135
185
  },
136
186
  lyrics: {
137
187
  type: 'string',
138
188
  description: 'New or modified structured lyrics. ' +
139
- 'Required/recommended when using cover_feature_id. ' +
189
+ '**MANDATORY** when using cover_feature_id + non-instrumental (`is_instrumental: false`). ' +
140
190
  'Optional when using direct audio_url (API can extract). ' +
141
191
  'Optional for both instrumental and non-instrumental covers.'
142
192
  },
@@ -148,22 +198,13 @@ tools.add(
148
198
  is_instrumental: {
149
199
  type: 'boolean',
150
200
  default: false,
151
- description: 'Generate instrumental cover.'
201
+ description: 'Generate instrumental cover. When false + cover_feature_id, lyrics are required.'
152
202
  },
153
203
  output_format: {
154
204
  type: 'string',
155
205
  enum: ['url', 'hex'],
156
206
  default: 'url',
157
- description: 'Output format. Default "url".'
158
- },
159
- audio_setting: {
160
- type: 'object',
161
- properties: {
162
- sample_rate: { type: 'integer', default: 44100 },
163
- bitrate: { type: 'integer', default: 256000 },
164
- format: { type: 'string', default: 'mp3' }
165
- },
166
- description: 'Audio output settings.'
207
+ description: 'Output format. Default "url". Prefer "url" for durable assistant-visible references.'
167
208
  },
168
209
  extra: { type: 'object', description: 'Additional parameters.' }
169
210
  },
@@ -172,45 +213,38 @@ tools.add(
172
213
  async (params) => {
173
214
  const result = await minimax.changeMusic(params.prompt, params);
174
215
 
175
- return JSON.stringify({
176
- audio_url: result.audio_url,
177
- local_path: result.local_path,
178
- duration_ms: result.duration,
179
- raw_response: result.raw,
180
- note: params.cover_feature_id
181
- ? 'Two-step cover generated using cover_feature_id (from analyze_music). ' +
182
- 'Lyrics were applied. Audio saved to local_path.'
183
- : 'Direct one-step cover generated using audio_url/audio_base64. ' +
184
- 'Audio saved to local_path.'
185
- }, null, 2);
216
+ return musicToolResponse(
217
+ 'change_music',
218
+ params,
219
+ result,
220
+ params.cover_feature_id
221
+ ? 'Two-step cover generated using cover_feature_id. Assistant: tell the user the exact cover_feature_id, local_path, and audio_url. Use local_path/audio_url as durable references after pruning.'
222
+ : 'Direct one-step cover generated using audio_url/audio_base64. Assistant: tell the user the exact source_audio_url when available, plus local_path and audio_url for the generated cover.'
223
+ );
186
224
  }
187
225
  );
188
226
 
189
227
  /* ============================================================
190
- WORKFLOW 3: ANALYZE MUSIC (Preprocess for Cover)
228
+ WORKFLOW 3: ANALYZE MUSIC (Preprocess for Cover) — MODEL FIXED
191
229
  ============================================================ */
192
230
 
193
231
  tools.add(
194
232
  'analyze_music',
195
233
  'Preprocess a reference audio file to extract voice features, structure, and lyrics. ' +
196
234
  'This is the first step of the advanced two-step cover workflow. ' +
197
- 'Returns a cover_feature_id that can be used with change_music for lyric modifications.',
235
+ 'Returns a cover_feature_id that can be used with change_music for lyric modifications. ' +
236
+ 'Model is fixed to "music-cover". ' +
237
+ 'After success, include the exact cover_feature_id, trace_id, and source audio_url in your assistant response; cover_feature_id is valid for 24 hours and is required for follow-up two-step cover calls.',
198
238
  {
199
239
  type: 'object',
200
240
  properties: {
201
241
  audio_url: {
202
242
  type: 'string',
203
- description: 'Public URL of the reference audio (6 seconds to 6 minutes, max 50MB).'
243
+ description: 'Public URL of the reference audio (6 seconds to 6 minutes, max 50MB). Prefer audio_url where possible.'
204
244
  },
205
245
  audio_base64: {
206
246
  type: 'string',
207
- description: 'Base64-encoded reference audio (alternative to audio_url).'
208
- },
209
- model: {
210
- type: 'string',
211
- enum: ['music-cover'],
212
- default: 'music-cover',
213
- description: 'Must be "music-cover".'
247
+ description: 'Base64-encoded reference audio (alternative to audio_url). Prefer audio_url where possible.'
214
248
  }
215
249
  },
216
250
  required: ['audio_url']
@@ -218,16 +252,21 @@ tools.add(
218
252
  async (params) => {
219
253
  const result = await minimax.analyzeMusic(params.audio_url, params);
220
254
 
221
- return JSON.stringify({
255
+ return json({
256
+ tool: 'analyze_music',
257
+ success: true,
222
258
  cover_feature_id: result.cover_feature_id,
259
+ coverFeatureId: result.cover_feature_id,
260
+ source_audio_url: params.audio_url,
261
+ has_audio_base64: Boolean(params.audio_base64),
223
262
  formatted_lyrics: result.formatted_lyrics,
224
263
  structure_result: result.structure_result,
225
264
  audio_duration_seconds: result.audio_duration,
226
265
  trace_id: result.trace_id,
227
- raw_response: result.raw,
228
- note: 'Use this cover_feature_id with change_music for two-step covers with custom lyrics. ' +
229
- 'Valid for 24 hours. Same audio always returns the same ID.'
230
- }, null, 2);
266
+ model: 'music-cover',
267
+ expires_in: '24 hours',
268
+ note: 'Assistant: tell the user the exact cover_feature_id and trace_id. Use cover_feature_id with change_music for two-step covers with custom lyrics. Preserve the exact source_audio_url if present.'
269
+ });
231
270
  }
232
271
  );
233
272
 
@@ -242,7 +281,8 @@ tools.add(
242
281
  '• mode = "write_full_song" (default) + no existing lyrics → creates a complete song with title, style tags, and full structured lyrics.\n' +
243
282
  '• Short prompt only → generates a short snippet, hook, verse, or chorus idea.\n' +
244
283
  '• mode = "edit" + existing lyrics → edits, rewrites, continues, or modifies the provided lyrics.\n' +
245
- '• title parameter → keeps the specified song title in the output.',
284
+ '• title parameter → keeps the specified song title in the output.\n\n' +
285
+ 'After success, include the exact song_title and generated lyrics in your assistant response if they are needed for create_music or change_music follow-up calls.',
246
286
  {
247
287
  type: 'object',
248
288
  properties: {
@@ -278,13 +318,19 @@ tools.add(
278
318
  },
279
319
  async (params) => {
280
320
  const result = await minimax.generateLyrics(params.prompt, params);
281
- return JSON.stringify({
321
+ return json({
322
+ tool: 'lyrics',
323
+ success: true,
282
324
  song_title: result.song_title,
325
+ songTitle: result.song_title,
283
326
  style_tags: result.style_tags,
284
327
  lyrics: result.lyrics,
285
- note: `Lyrics generated using mode: ${params.mode || 'write_full_song'}`
286
- }, null, 2);
328
+ mode: params.mode || 'write_full_song',
329
+ title: params.title,
330
+ prompt: params.prompt,
331
+ note: 'Assistant: preserve the exact song_title, style_tags, and lyrics in your normal response if they are needed for follow-up create_music/change_music calls.'
332
+ });
287
333
  }
288
334
  );
289
335
 
290
- export default tools;
336
+ export default tools;