beplus-mcp 0.33.0 → 0.35.0
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/README.md +3 -0
- package/dist/index.js +132 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,9 @@ Reinicie o cliente. Rode a tool **`whoami`** para confirmar o vínculo.
|
|
|
86
86
|
| `upscale` | Melhora a resolução de uma imagem ou vídeo que já existe (Topaz). Detecta o tipo pelo arquivo. Imagem até 4x (~20s, a partir de 6💎); vídeo até 30s e saída até 1080p, custa por bloco de 10s e **descarta o áudio**. Mede o arquivo sozinho para o preço sair certo. ⚠️ Vídeo é restrito à equipe. |
|
|
87
87
|
| `generate_audio` | Sintetiza fala (Gemini TTS, multi-locutor). Padrão `gemini-3.8-flash-lite-tts`; os modelos 3.8 aceitam vozes da biblioteca, tags vocais (`<laugh>`, `<sigh>`...) e `style` por locutor; os legados só as 30 vozes clássicas. Síncrono. |
|
|
88
88
|
| `list_tts_voices` | Lista as vozes da biblioteca do TTS 3.8 (filtros: idioma, gênero, tom, contexto, busca) com o id para usar em `voice`. Somente leitura. |
|
|
89
|
+
| `list_custom_voices` | Lista suas vozes próprias do TTS 3.8 (máx. 3) com o `voice_xxx` para usar em `voice`. Clonar a própria voz só no app web. Somente leitura. |
|
|
90
|
+
| `design_voice` | Cria uma voz própria a partir de uma descrição. Gasta 💎 e leva ~30 s. |
|
|
91
|
+
| `delete_custom_voice` | Apaga uma voz própria (destrutivo, sem volta). |
|
|
89
92
|
| `generate_music` | Gera música completa (Suno v5.5 / v4.5) — modo descrição ou letra própria, tags, instrumental, vocal_gender, controles criativos. Async. |
|
|
90
93
|
| `check_generation` | Status de uma geração async por id. |
|
|
91
94
|
| `cancel_generation` | Cancela uma geração em fila/processamento (estorna diamantes). |
|
package/dist/index.js
CHANGED
|
@@ -21624,6 +21624,16 @@ var BeplusClient = class {
|
|
|
21624
21624
|
ttsVoices(query) {
|
|
21625
21625
|
return this.request("GET", "/tts/voices", { query, timeoutMs: 2e4 });
|
|
21626
21626
|
}
|
|
21627
|
+
customVoices() {
|
|
21628
|
+
return this.request("GET", "/tts/custom-voices", { timeoutMs: 2e4 });
|
|
21629
|
+
}
|
|
21630
|
+
// Leva ~30 s no Google; 90 s cobre a espera com folga.
|
|
21631
|
+
designVoice(body2) {
|
|
21632
|
+
return this.request("POST", "/tts/custom-voices/design", { body: body2, timeoutMs: 9e4 });
|
|
21633
|
+
}
|
|
21634
|
+
deleteCustomVoice(id) {
|
|
21635
|
+
return this.request("DELETE", `/tts/custom-voices/${encodeURIComponent(id)}`, { timeoutMs: 3e4 });
|
|
21636
|
+
}
|
|
21627
21637
|
models() {
|
|
21628
21638
|
return this.request("GET", "/models");
|
|
21629
21639
|
}
|
|
@@ -22188,6 +22198,7 @@ var TTS_MODELS = [
|
|
|
22188
22198
|
"gemini-2.5-pro-preview-tts"
|
|
22189
22199
|
];
|
|
22190
22200
|
var TTS_MODELS_38 = ["gemini-3.8-flash-lite-tts", "gemini-3.8-flash-tts"];
|
|
22201
|
+
var CUSTOM_VOICE_ID = /^voice_[a-z0-9]{6,64}$/;
|
|
22191
22202
|
var LIBRARY_VOICE_ID = /^[a-z]{2,3}-[a-z0-9]{2,4}-[a-z0-9-]{1,60}$/;
|
|
22192
22203
|
var VOICES = [
|
|
22193
22204
|
"Zephyr",
|
|
@@ -22535,7 +22546,7 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22535
22546
|
"generate_video",
|
|
22536
22547
|
{
|
|
22537
22548
|
title: "Gerar v\xEDdeo",
|
|
22538
|
-
description: "Gera um v\xEDdeo curto usando o IA Lab da BePlus. LENTO (geralmente 1-5+ min). Aguarda at\xE9 ~2 min; se n\xE3o terminar, retorna o generation_id e o status \u2014 ent\xE3o use check_generation. Consome diamantes (mais caro para dura\xE7\xF5es/resolu\xE7\xF5es maiores). Suporta image-to-video (`first_frame_image`), \xFAltimo frame (`last_frame_image`), refer\xEAncias de imagem/v\xEDdeo/\xE1udio, prompt negativo, \xE1udio gerado e mais \u2014 os campos aceitos variam por modelo (consulte list_models). `kling-v2.6-motion-control` usa `first_frame_image` + `motion_video`. Nos modelos Seedance
|
|
22549
|
+
description: "Gera um v\xEDdeo curto usando o IA Lab da BePlus. LENTO (geralmente 1-5+ min). Aguarda at\xE9 ~2 min; se n\xE3o terminar, retorna o generation_id e o status \u2014 ent\xE3o use check_generation. Consome diamantes (mais caro para dura\xE7\xF5es/resolu\xE7\xF5es maiores). Suporta image-to-video (`first_frame_image`), \xFAltimo frame (`last_frame_image`), refer\xEAncias de imagem/v\xEDdeo/\xE1udio, prompt negativo, \xE1udio gerado e mais \u2014 os campos aceitos variam por modelo (consulte list_models). `kling-v2.6-motion-control` usa `first_frame_image` + `motion_video`. Nos modelos Seedance d\xE1 pra escolher o provedor com `provider`: `byteplus` (padr\xE3o) ou `fal`. A BytePlus bloqueia refer\xEAncia com rosto de pessoa REAL; a fal.ai aceita (custa mais caro) e \xE9 a alternativa quando a BytePlus estiver inst\xE1vel. Kling e outros modelos n\xE3o t\xEAm essa op\xE7\xE3o." + TEAM_GATING_NOTE,
|
|
22539
22550
|
inputSchema: {
|
|
22540
22551
|
// Sem teto local — ver nota em generate_image. O Seedance não publica
|
|
22541
22552
|
// limite; o Kling publica 2500 e o backend recusa dizendo quanto cortar.
|
|
@@ -22571,16 +22582,17 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22571
22582
|
video_task_type: external_exports.enum(["auto", "reference", "edit", "extend"]).optional().describe(
|
|
22572
22583
|
"O que fazer com os v\xEDdeos de refer\xEAncia (s\xF3 seedance-2.5): `reference` gera um v\xEDdeo novo; `edit` edita o original (exige 1 v\xEDdeo de 4-30s, a dura\xE7\xE3o vira a dele); `extend` estende o original. Sem isto o modelo adivinha e um par\xE2metro incompat\xEDvel s\xF3 falha DEPOIS da fila."
|
|
22573
22584
|
),
|
|
22574
|
-
|
|
22575
|
-
|
|
22585
|
+
provider: external_exports.enum(["byteplus", "fal"]).optional().describe(
|
|
22586
|
+
"S\xF3 Seedance (2.0/2.0-fast/2.0-mini/2.5): qual empresa gera o v\xEDdeo. `byteplus` (padr\xE3o) \xE9 a API oficial da ByteDance. `fal` usa a fal.ai: aceita refer\xEAncia com pessoa real (a BytePlus recusa) e custa mais caro. Na fal, `first_frame_image` + `last_frame_image` funcionam (image-to-video com end frame) e o Draft Mode funciona no seedance-2.5; `output_format` e `video_task_type` (edit/extend) n\xE3o t\xEAm equivalente e s\xE3o recusados antes de cobrar, assim como `seedance-2.0-fast` em 480p (a fal n\xE3o publica pre\xE7o para essa combina\xE7\xE3o)."
|
|
22576
22587
|
),
|
|
22588
|
+
real_people_references: external_exports.boolean().optional().describe('OBSOLETO: use `provider: "fal"`. `true` aqui equivale a `provider: "fal"`.'),
|
|
22577
22589
|
project: external_exports.string().max(64).optional().describe('Projeto (uuid OU code curto, ex.: "VRAO-26"). S\xF3 omita se o usu\xE1rio J\xC1 confirmou o projeto ativo nesta sess\xE3o.'),
|
|
22578
22590
|
billing: BILLING_FIELD,
|
|
22579
22591
|
draft: external_exports.boolean().optional().describe(
|
|
22580
|
-
'Draft Mode (s\xF3 seedance-2.5,
|
|
22592
|
+
'Draft Mode (s\xF3 seedance-2.5, nos dois provedores): gera um preview 480p barato para validar composi\xE7\xE3o/movimento antes de pagar o 1080p. `resolution` fica em 480p (omita ou use "480p"). Depois de check_generation mostrar "completed", o `draft_task_id` e o provedor v\xEAm no retorno \u2014 \xE9 o que voc\xEA passa no pr\xF3ximo generate_video para render a vers\xE3o final, a mesma tomada, sem regenerar do zero.'
|
|
22581
22593
|
),
|
|
22582
22594
|
draft_task_id: external_exports.string().min(1).optional().describe(
|
|
22583
|
-
"Gera a vers\xE3o 1080p de um draft j\xE1 pronto (feito com `draft: true`). Passe aqui o `draft_task_id` que check_generation devolveu para aquele draft \u2014 N\xC3O o generation_id. Prompt/refs/seed/ratio/\xE1udio s\xE3o HERDADOS do draft, n\xE3o os reenvie. `duration` \xE9 OBRIGAT\xD3RIO e tem que ser exatamente a dura\xE7\xE3o do draft original (\xE9 o que precifica certo); `resolution` \xE9 sempre 1080p. Drafts expiram em 7 dias."
|
|
22595
|
+
"Gera a vers\xE3o 1080p de um draft j\xE1 pronto (feito com `draft: true`). Passe aqui o `draft_task_id` que check_generation devolveu para aquele draft \u2014 N\xC3O o generation_id \u2014 e o MESMO `provider` do draft (o id s\xF3 vale no provedor que gerou). Prompt/refs/seed/ratio/\xE1udio s\xE3o HERDADOS do draft, n\xE3o os reenvie. `duration` \xE9 OBRIGAT\xD3RIO e tem que ser exatamente a dura\xE7\xE3o do draft original (\xE9 o que precifica certo); `resolution` \xE9 sempre 1080p. Drafts expiram em 7 dias."
|
|
22584
22596
|
)
|
|
22585
22597
|
}
|
|
22586
22598
|
},
|
|
@@ -22607,6 +22619,12 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22607
22619
|
if (!args.draft_task_id && !args.prompt) {
|
|
22608
22620
|
return errorResult("`prompt` \xE9 obrigat\xF3rio (s\xF3 pode faltar ao usar `draft_task_id`).");
|
|
22609
22621
|
}
|
|
22622
|
+
if (args.draft && args.draft_task_id) {
|
|
22623
|
+
return errorResult("Use `draft` OU `draft_task_id`, n\xE3o os dois no mesmo pedido.");
|
|
22624
|
+
}
|
|
22625
|
+
if (args.draft && args.resolution && args.resolution !== "480p") {
|
|
22626
|
+
return errorResult('O Draft Mode s\xF3 gera em 480p \u2014 omita `resolution` ou use "480p".');
|
|
22627
|
+
}
|
|
22610
22628
|
if (args.draft_task_id) {
|
|
22611
22629
|
if (args.duration == null) {
|
|
22612
22630
|
return errorResult("Ao usar `draft_task_id`, `duration` \xE9 obrigat\xF3rio \u2014 a mesma dura\xE7\xE3o do draft original.");
|
|
@@ -22618,21 +22636,24 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22618
22636
|
if (!isSeedance25 && args.video_task_type && args.video_task_type !== "auto") {
|
|
22619
22637
|
return errorResult(`Editar e estender v\xEDdeo s\xF3 existe no seedance-2.5 (voc\xEA pediu ${args.model}).`);
|
|
22620
22638
|
}
|
|
22621
|
-
|
|
22622
|
-
|
|
22639
|
+
const isSeedance = !!args.model?.startsWith("bytedance/seedance-");
|
|
22640
|
+
if ((args.provider || args.real_people_references) && !isSeedance) {
|
|
22641
|
+
return errorResult(`A escolha de provedor (provider/real_people_references) s\xF3 existe nos modelos Seedance (voc\xEA pediu ${args.model}).`);
|
|
22642
|
+
}
|
|
22643
|
+
if (args.provider === "byteplus" && args.real_people_references) {
|
|
22644
|
+
return errorResult('`real_people_references: true` usa a fal.ai e contradiz `provider: "byteplus"`. Use s\xF3 `provider`.');
|
|
22623
22645
|
}
|
|
22624
|
-
|
|
22646
|
+
const seedanceProvider = args.provider ?? (args.real_people_references ? "fal" : void 0);
|
|
22647
|
+
if (seedanceProvider === "fal") {
|
|
22625
22648
|
const unsupported = [];
|
|
22626
22649
|
if (args.output_format && args.output_format !== "mp4") unsupported.push("output_format");
|
|
22627
22650
|
if (args.video_task_type && args.video_task_type !== "auto") unsupported.push("video_task_type (edit/extend)");
|
|
22628
22651
|
if (args.model === "bytedance/seedance-2.0-fast" && args.resolution === "480p") {
|
|
22629
22652
|
unsupported.push("resolution 480p (a fal n\xE3o publica pre\xE7o para seedance-2.0-fast nesta resolu\xE7\xE3o)");
|
|
22630
22653
|
}
|
|
22631
|
-
if (args.draft) unsupported.push("draft (Modo Rascunho \u2014 s\xF3 existe na BytePlus)");
|
|
22632
|
-
if (args.draft_task_id) unsupported.push("draft_task_id (upscale de rascunho \u2014 s\xF3 existe na BytePlus)");
|
|
22633
22654
|
if (unsupported.length > 0) {
|
|
22634
22655
|
return errorResult(
|
|
22635
|
-
`Com
|
|
22656
|
+
`Com provider "fal", a fal.ai n\xE3o suporta: ${unsupported.join(", ")}. Remova essas op\xE7\xF5es.`
|
|
22636
22657
|
);
|
|
22637
22658
|
}
|
|
22638
22659
|
}
|
|
@@ -22670,11 +22691,12 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22670
22691
|
draft_task_id: args.draft_task_id,
|
|
22671
22692
|
resolution: "1080p",
|
|
22672
22693
|
duration: args.duration,
|
|
22673
|
-
output_format: args.output_format
|
|
22694
|
+
output_format: args.output_format,
|
|
22695
|
+
seedanceProvider
|
|
22674
22696
|
}) : compact({
|
|
22675
22697
|
prompt: args.prompt,
|
|
22676
22698
|
aspect_ratio: args.aspect_ratio ?? DEFAULTS.videoAspect,
|
|
22677
|
-
resolution: args.resolution ?? DEFAULTS.videoResolution,
|
|
22699
|
+
resolution: args.resolution ?? (args.draft ? "480p" : DEFAULTS.videoResolution),
|
|
22678
22700
|
duration: args.duration ?? DEFAULTS.videoDuration,
|
|
22679
22701
|
negative_prompt: args.negative_prompt,
|
|
22680
22702
|
mode: args.mode,
|
|
@@ -22692,7 +22714,7 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22692
22714
|
output_format: args.output_format,
|
|
22693
22715
|
omni_reference_task_type: args.video_task_type,
|
|
22694
22716
|
draft: args.draft,
|
|
22695
|
-
|
|
22717
|
+
seedanceProvider
|
|
22696
22718
|
});
|
|
22697
22719
|
const start = await client.startGeneration(
|
|
22698
22720
|
compact({
|
|
@@ -22750,9 +22772,10 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
22750
22772
|
const urls = outputUrls(status);
|
|
22751
22773
|
const blocks = await buildImageBlocks(urls, cfg);
|
|
22752
22774
|
const list = urls.map((u, i) => `${i + 1}. ${u}`).join("\n") || "(sem URLs)";
|
|
22775
|
+
const draftProvider = status.seedance_provider ?? "byteplus";
|
|
22753
22776
|
const draftHint = status.draft_task_id ? `
|
|
22754
22777
|
|
|
22755
|
-
\u{1F3AC} Draft pronto \u2014 pra gerar em 1080p, chame generate_video de novo com draft_task_id: "${status.draft_task_id}"
|
|
22778
|
+
\u{1F3AC} Draft pronto (provedor: ${draftProvider === "fal" ? "fal.ai" : "BytePlus"}) \u2014 pra gerar em 1080p, chame generate_video de novo com draft_task_id: "${status.draft_task_id}", provider: "${draftProvider}" e a mesma duration deste draft.` : "";
|
|
22756
22779
|
return { content: [{ type: "text", text: `\u2705 Pronto.
|
|
22757
22780
|
${list}${flagsLine(status)}${draftHint}` }, ...blocks] };
|
|
22758
22781
|
}
|
|
@@ -23471,9 +23494,16 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
|
|
|
23471
23494
|
|
|
23472
23495
|
// src/tools/audio.ts
|
|
23473
23496
|
var VOICE_HELP = "Uma das 30 vozes cl\xE1ssicas (Kore, Puck, Charon...) OU o id de uma voz da biblioteca (ex.: pt-br-advisor-10, s\xF3 nos modelos 3.8; descubra ids com list_tts_voices).";
|
|
23497
|
+
var VOICE_HELP_TOP = `${VOICE_HELP} Ou o id de uma voz pr\xF3pria (voice_xxx, de list_custom_voices; s\xF3 3.8 e sem multi_speaker).`;
|
|
23474
23498
|
var voiceSchema = external_exports.string().refine((v) => VOICES.includes(v) || LIBRARY_VOICE_ID.test(v), {
|
|
23475
23499
|
message: "Voz inv\xE1lida: use uma das 30 vozes cl\xE1ssicas (ex.: Kore) ou um id da biblioteca (ex.: pt-br-advisor-10)."
|
|
23476
23500
|
});
|
|
23501
|
+
var topVoiceSchema = external_exports.string().refine((v) => VOICES.includes(v) || LIBRARY_VOICE_ID.test(v) || CUSTOM_VOICE_ID.test(v), {
|
|
23502
|
+
message: "Voz inv\xE1lida: use uma das 30 vozes cl\xE1ssicas (ex.: Kore), um id da biblioteca (ex.: pt-br-advisor-10) ou uma voz pr\xF3pria (voice_xxx)."
|
|
23503
|
+
});
|
|
23504
|
+
function isCustomVoice(v) {
|
|
23505
|
+
return CUSTOM_VOICE_ID.test(v);
|
|
23506
|
+
}
|
|
23477
23507
|
function isLibraryVoice(v) {
|
|
23478
23508
|
return !VOICES.includes(v) && LIBRARY_VOICE_ID.test(v);
|
|
23479
23509
|
}
|
|
@@ -23487,10 +23517,10 @@ function registerAudioTools(server, client, cfg) {
|
|
|
23487
23517
|
"generate_audio",
|
|
23488
23518
|
{
|
|
23489
23519
|
title: "Gerar \xE1udio (TTS)",
|
|
23490
|
-
description: 'Sintetiza fala a partir de texto (s\xEDncrono \u2014 retorna a URL na hora) usando o IA Lab da BePlus. Modelos Gemini 3.8 (`gemini-3.8-flash-lite-tts`, padr\xE3o, r\xE1pido e barato; `gemini-3.8-flash-tts`, qualidade de est\xFAdio, melhor para di\xE1logo e narra\xE7\xE3o longa) aceitam: vozes da biblioteca (milhares, por idioma; liste com `list_tts_voices` e passe o id em `voice`), tags vocais no texto como <laugh> <chuckle> <sigh> <breath> <gasp> <cough> <sneeze> <throat-clearing> <yawn> <groan> <scream> <whimper> <argh> <short pause> <long pause> (viram som de verdade), e estilo por locutor (`style` em cada speaker). No 3.8, `style_instruction` \xE9 dire\xE7\xE3o e N\xC3O \xE9 lida em voz alta. Os modelos legados (`gemini-3.1-flash-tts-preview`, `gemini-2.5-pro-preview-tts`) s\xF3 aceitam as 30 vozes cl\xE1ssicas (Kore, Puck, Charon...) e n\xE3o t\xEAm voz da biblioteca. Opcional `style_instruction` (ex.: "fale animado e pausado") e di\xE1logo com 2 locutores via `multi_speaker`. Consome diamantes por segundo de \xE1udio.' + TEAM_GATING_NOTE,
|
|
23520
|
+
description: 'Sintetiza fala a partir de texto (s\xEDncrono \u2014 retorna a URL na hora) usando o IA Lab da BePlus. Modelos Gemini 3.8 (`gemini-3.8-flash-lite-tts`, padr\xE3o, r\xE1pido e barato; `gemini-3.8-flash-tts`, qualidade de est\xFAdio, melhor para di\xE1logo e narra\xE7\xE3o longa) aceitam: vozes da biblioteca (milhares, por idioma; liste com `list_tts_voices` e passe o id em `voice`), tags vocais no texto como <laugh> <chuckle> <sigh> <breath> <gasp> <cough> <sneeze> <throat-clearing> <yawn> <groan> <scream> <whimper> <argh> <short pause> <long pause> (viram som de verdade), e estilo por locutor (`style` em cada speaker). No 3.8, `style_instruction` \xE9 dire\xE7\xE3o e N\xC3O \xE9 lida em voz alta. Os modelos legados (`gemini-3.1-flash-tts-preview`, `gemini-2.5-pro-preview-tts`) s\xF3 aceitam as 30 vozes cl\xE1ssicas (Kore, Puck, Charon...) e n\xE3o t\xEAm voz da biblioteca. Vozes pr\xF3prias (voice_xxx; liste com `list_custom_voices`, crie com `design_voice`) s\xF3 no 3.8 e sem `multi_speaker`. No 3.8, dire\xE7\xE3o por linha: `(sussurrando) texto` no in\xEDcio da linha vale at\xE9 a pr\xF3xima dire\xE7\xE3o; no di\xE1logo, `Ana (rindo): fala`; rea\xE7\xF5es `|hmm|` `|aham|` no meio da fala (s\xF3 di\xE1logo). Opcional `style_instruction` (ex.: "fale animado e pausado") e di\xE1logo com 2 locutores via `multi_speaker`. Consome diamantes por segundo de \xE1udio.' + TEAM_GATING_NOTE,
|
|
23491
23521
|
inputSchema: {
|
|
23492
23522
|
text: external_exports.string().min(1).max(1e4).describe("Texto a ser falado."),
|
|
23493
|
-
voice:
|
|
23523
|
+
voice: topVoiceSchema.default(DEFAULTS.voice).describe(VOICE_HELP_TOP),
|
|
23494
23524
|
model: external_exports.enum(TTS_MODELS).default(DEFAULTS.ttsModel).describe("Modelo TTS."),
|
|
23495
23525
|
style_instruction: external_exports.string().max(2e3).optional().describe("Instru\xE7\xE3o de estilo/tom aplicada \xE0 fala."),
|
|
23496
23526
|
multi_speaker: external_exports.object({
|
|
@@ -23504,6 +23534,14 @@ function registerAudioTools(server, client, cfg) {
|
|
|
23504
23534
|
try {
|
|
23505
23535
|
const ms = args.multi_speaker;
|
|
23506
23536
|
const voices = [args.voice, ms?.speaker1.voice, ms?.speaker2.voice].filter((v) => !!v);
|
|
23537
|
+
if (isCustomVoice(args.voice)) {
|
|
23538
|
+
if (!TTS_MODELS_38.includes(args.model)) {
|
|
23539
|
+
return errorResult("Vozes pr\xF3prias s\xF3 funcionam nos modelos Gemini 3.8 (gemini-3.8-flash-lite-tts, gemini-3.8-flash-tts).");
|
|
23540
|
+
}
|
|
23541
|
+
if (ms) {
|
|
23542
|
+
return errorResult("Vozes pr\xF3prias n\xE3o funcionam no modo di\xE1logo (multi_speaker). Use uma voz da biblioteca ou cl\xE1ssica.");
|
|
23543
|
+
}
|
|
23544
|
+
}
|
|
23507
23545
|
if (!TTS_MODELS_38.includes(args.model)) {
|
|
23508
23546
|
if (voices.some(isLibraryVoice)) {
|
|
23509
23547
|
return errorResult(
|
|
@@ -23586,6 +23624,80 @@ Contextos: ${res.contexts.join(", ")}.`
|
|
|
23586
23624
|
}
|
|
23587
23625
|
}
|
|
23588
23626
|
);
|
|
23627
|
+
server.registerTool(
|
|
23628
|
+
"list_custom_voices",
|
|
23629
|
+
{
|
|
23630
|
+
title: "Listar vozes pr\xF3prias",
|
|
23631
|
+
description: "Lista as suas vozes pr\xF3prias do TTS 3.8 (m\xE1x. 3, guardadas por 1 ano). Passe o campo `voice` (voice_xxx) em `voice` do generate_audio com um modelo 3.8, sem multi_speaker. Crie com `design_voice`. Clonar a pr\xF3pria voz exige grava\xE7\xE3o de consentimento ao vivo e s\xF3 existe no app web. Somente leitura, sem custo.",
|
|
23632
|
+
inputSchema: {}
|
|
23633
|
+
},
|
|
23634
|
+
async () => {
|
|
23635
|
+
try {
|
|
23636
|
+
const res = await client.customVoices();
|
|
23637
|
+
const head = `Vozes pr\xF3prias: ${res.used} de ${res.limit}. Criar uma voz custa ${res.design_cost} \u{1F48E}.`;
|
|
23638
|
+
if (!res.voices.length) return textResult(`${head}
|
|
23639
|
+
Nenhuma ainda. Use design_voice para criar.`);
|
|
23640
|
+
const lines = res.voices.map(
|
|
23641
|
+
(v) => `${v.id} | ${v.voice} | ${v.name} | ${v.kind} | expira ${v.expires_at.slice(0, 10)}`
|
|
23642
|
+
);
|
|
23643
|
+
return textResult(
|
|
23644
|
+
`${head} (id | voice | nome | tipo | validade):
|
|
23645
|
+
${lines.join("\n")}
|
|
23646
|
+
|
|
23647
|
+
Use o valor de "voice" (voice_xxx) no generate_audio. Para apagar, use o "id" em delete_custom_voice.`
|
|
23648
|
+
);
|
|
23649
|
+
} catch (e) {
|
|
23650
|
+
return errorResult(apiErrorToUserMessage(e));
|
|
23651
|
+
}
|
|
23652
|
+
}
|
|
23653
|
+
);
|
|
23654
|
+
server.registerTool(
|
|
23655
|
+
"design_voice",
|
|
23656
|
+
{
|
|
23657
|
+
title: "Criar voz pr\xF3pria por descri\xE7\xE3o",
|
|
23658
|
+
description: "Cria uma voz pr\xF3pria a partir de uma descri\xE7\xE3o em texto (idade, timbre, sotaque, jeito de falar). GASTA diamantes (o custo aparece em list_custom_voices; estorna se falhar) e leva cerca de 30 s. M\xE1x. 3 vozes por pessoa; a voz fica guardada por 1 ano. Depois use o `voice` retornado no generate_audio (modelos 3.8, sem multi_speaker).",
|
|
23659
|
+
inputSchema: {
|
|
23660
|
+
name: external_exports.string().min(1).max(40).describe("Nome da voz (1 a 40 caracteres)."),
|
|
23661
|
+
description: external_exports.string().min(10).max(500).describe("Como \xE9 a voz: idade, g\xEAnero, timbre, sotaque, jeito de falar (10 a 500 caracteres)."),
|
|
23662
|
+
language: external_exports.string().max(12).optional().describe("Idioma BCP-47. Padr\xE3o pt-BR."),
|
|
23663
|
+
gender: external_exports.enum(["female", "male", "neutral"]).optional()
|
|
23664
|
+
}
|
|
23665
|
+
},
|
|
23666
|
+
async (args) => {
|
|
23667
|
+
try {
|
|
23668
|
+
const res = await client.designVoice(compact(args));
|
|
23669
|
+
const v = res.voice;
|
|
23670
|
+
return textResult(
|
|
23671
|
+
`\u2705 Voz criada: ${v.name} (${v.kind}).
|
|
23672
|
+
voice: ${v.voice}
|
|
23673
|
+
id: ${v.id}
|
|
23674
|
+
` + (v.sample_url ? `Amostra: ${v.sample_url}
|
|
23675
|
+
` : "") + `Custo: ${res.diamond_cost} \u{1F48E} \xB7 Saldo: ${res.new_balance} \u{1F48E} \xB7 Expira em ${v.expires_at.slice(0, 10)}.
|
|
23676
|
+
Use o valor de "voice" no generate_audio com um modelo 3.8 (sem multi_speaker).`
|
|
23677
|
+
);
|
|
23678
|
+
} catch (e) {
|
|
23679
|
+
return errorResult(apiErrorToUserMessage(e));
|
|
23680
|
+
}
|
|
23681
|
+
}
|
|
23682
|
+
);
|
|
23683
|
+
server.registerTool(
|
|
23684
|
+
"delete_custom_voice",
|
|
23685
|
+
{
|
|
23686
|
+
title: "Apagar voz pr\xF3pria",
|
|
23687
|
+
description: "DESTRUTIVO e sem volta: apaga uma voz pr\xF3pria (aqui e no Google) e libera 1 vaga das 3. \xC1udios j\xE1 gerados com ela continuam tocando, mas n\xE3o d\xE1 para gerar novos com essa voz. N\xE3o devolve diamantes. Passe o `id` (uuid) de list_custom_voices, n\xE3o o voice_xxx. Confirme com o usu\xE1rio antes.",
|
|
23688
|
+
inputSchema: {
|
|
23689
|
+
id: external_exports.string().uuid().describe('Campo "id" (uuid) da voz em list_custom_voices.')
|
|
23690
|
+
}
|
|
23691
|
+
},
|
|
23692
|
+
async (args) => {
|
|
23693
|
+
try {
|
|
23694
|
+
await client.deleteCustomVoice(args.id);
|
|
23695
|
+
return textResult(`\u2705 Voz ${args.id} apagada. Uma vaga foi liberada.`);
|
|
23696
|
+
} catch (e) {
|
|
23697
|
+
return errorResult(apiErrorToUserMessage(e));
|
|
23698
|
+
}
|
|
23699
|
+
}
|
|
23700
|
+
);
|
|
23589
23701
|
}
|
|
23590
23702
|
|
|
23591
23703
|
// src/tools/music.ts
|
|
@@ -23771,6 +23883,7 @@ Limites simult\xE2neos por usu\xE1rio: imagem=${m.limits.perUserMaxImage}, v\xED
|
|
|
23771
23883
|
quality: external_exports.string().optional(),
|
|
23772
23884
|
aspect_ratio: external_exports.string().optional().describe("Seedream Pro: a propor\xE7\xE3o muda os pixels e a faixa de pre\xE7o."),
|
|
23773
23885
|
num_images: external_exports.number().int().min(1).optional().describe("Seedream Pro: imagens por pedido; cada uma \xE9 cobrada."),
|
|
23886
|
+
provider: external_exports.enum(["byteplus", "fal"]).optional().describe("Seedance: provedor que vai gerar (padr\xE3o byteplus). `fal` tem pre\xE7o pr\xF3prio, mais caro."),
|
|
23774
23887
|
// Upscale: o preço não sai de uma chave fixa — vem das medidas do
|
|
23775
23888
|
// arquivo (megapixel de saída na imagem, bloco de 10s no vídeo). Sem
|
|
23776
23889
|
// elas o backend responde pelo padrão de 1024²/10s, que não é o preço
|
|
@@ -23814,6 +23927,7 @@ Limites simult\xE2neos por usu\xE1rio: imagem=${m.limits.perUserMaxImage}, v\xED
|
|
|
23814
23927
|
quality: args.quality,
|
|
23815
23928
|
aspect_ratio: args.aspect_ratio,
|
|
23816
23929
|
num_images: args.num_images,
|
|
23930
|
+
seedance_provider: args.provider === "fal" ? "fal" : void 0,
|
|
23817
23931
|
upscale_factor: args.upscale_factor,
|
|
23818
23932
|
model_variant: args.model_variant,
|
|
23819
23933
|
source_width: width2,
|
|
@@ -26937,7 +27051,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
26937
27051
|
import { createRequire } from "module";
|
|
26938
27052
|
var require2 = createRequire(import.meta.url);
|
|
26939
27053
|
function readVersion() {
|
|
26940
|
-
if ("0.
|
|
27054
|
+
if ("0.35.0") return "0.35.0";
|
|
26941
27055
|
try {
|
|
26942
27056
|
const pkg = require2("../package.json");
|
|
26943
27057
|
return pkg.version ?? "0.0.0-unknown";
|