beplus-mcp 0.32.0 → 0.34.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 CHANGED
@@ -84,7 +84,11 @@ Reinicie o cliente. Rode a tool **`whoami`** para confirmar o vínculo.
84
84
  | `generate_image` | Gera imagem (nano-banana / gpt-image-2). Bloqueante ~90s; retorna URL + imagem inline. Suporta refs, tamanho/qualidade, e extras do gpt-image-2 (background, moderation, output_format/compression). |
85
85
  | `generate_video` | Gera vídeo (Seedance / Kling). Aguarda ~120s; senão devolve o id pra `check_generation`. Suporta first/last frame, refs de imagem/vídeo/áudio, prompt negativo, áudio gerado, mode e motion-control. |
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
- | `generate_audio` | Sintetiza fala (Gemini TTS, ~30 vozes, multi-locutor). Síncrono. |
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
+ | `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). |
88
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. |
89
93
  | `check_generation` | Status de uma geração async por id. |
90
94
  | `cancel_generation` | Cancela uma geração em fila/processamento (estorna diamantes). |
package/dist/index.js CHANGED
@@ -21621,6 +21621,19 @@ var BeplusClient = class {
21621
21621
  tts(body2) {
21622
21622
  return this.request("POST", "/tts", { body: body2, timeoutMs: 9e4 });
21623
21623
  }
21624
+ ttsVoices(query) {
21625
+ return this.request("GET", "/tts/voices", { query, timeoutMs: 2e4 });
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
+ }
21624
21637
  models() {
21625
21638
  return this.request("GET", "/models");
21626
21639
  }
@@ -22179,9 +22192,14 @@ var MUSIC_MODELS = [
22179
22192
  ];
22180
22193
  var VOCAL_GENDERS = ["f", "m"];
22181
22194
  var TTS_MODELS = [
22195
+ "gemini-3.8-flash-lite-tts",
22196
+ "gemini-3.8-flash-tts",
22182
22197
  "gemini-3.1-flash-tts-preview",
22183
22198
  "gemini-2.5-pro-preview-tts"
22184
22199
  ];
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}$/;
22202
+ var LIBRARY_VOICE_ID = /^[a-z]{2,3}-[a-z0-9]{2,4}-[a-z0-9-]{1,60}$/;
22185
22203
  var VOICES = [
22186
22204
  "Zephyr",
22187
22205
  "Puck",
@@ -22226,7 +22244,7 @@ var DEFAULTS = {
22226
22244
  videoAspect: "16:9",
22227
22245
  videoResolution: "720p",
22228
22246
  videoDuration: 5,
22229
- ttsModel: "gemini-3.1-flash-tts-preview",
22247
+ ttsModel: "gemini-3.8-flash-lite-tts",
22230
22248
  voice: "Kore",
22231
22249
  musicModel: "suno/v5-5"
22232
22250
  };
@@ -23463,26 +23481,65 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
23463
23481
  }
23464
23482
 
23465
23483
  // src/tools/audio.ts
23484
+ 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).";
23485
+ 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).`;
23486
+ var voiceSchema = external_exports.string().refine((v) => VOICES.includes(v) || LIBRARY_VOICE_ID.test(v), {
23487
+ message: "Voz inv\xE1lida: use uma das 30 vozes cl\xE1ssicas (ex.: Kore) ou um id da biblioteca (ex.: pt-br-advisor-10)."
23488
+ });
23489
+ var topVoiceSchema = external_exports.string().refine((v) => VOICES.includes(v) || LIBRARY_VOICE_ID.test(v) || CUSTOM_VOICE_ID.test(v), {
23490
+ 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)."
23491
+ });
23492
+ function isCustomVoice(v) {
23493
+ return CUSTOM_VOICE_ID.test(v);
23494
+ }
23495
+ function isLibraryVoice(v) {
23496
+ return !VOICES.includes(v) && LIBRARY_VOICE_ID.test(v);
23497
+ }
23498
+ var speakerSchema = external_exports.object({
23499
+ name: external_exports.string().min(1).max(50),
23500
+ voice: voiceSchema.describe(VOICE_HELP),
23501
+ style: external_exports.string().max(500).optional().describe('Entrega deste locutor (s\xF3 modelos 3.8), ex.: "calmo, grave, pausado".')
23502
+ });
23466
23503
  function registerAudioTools(server, client, cfg) {
23467
23504
  server.registerTool(
23468
23505
  "generate_audio",
23469
23506
  {
23470
23507
  title: "Gerar \xE1udio (TTS)",
23471
- description: 'Sintetiza fala a partir de texto (s\xEDncrono \u2014 retorna a URL na hora) usando o IA Lab da BePlus. ~30 vozes. Opcional `style_instruction` (notas de dire\xE7\xE3o, ex.: "fale animado e pausado") e di\xE1logo com 2 locutores via `multi_speaker`. Consome diamantes por segundo de \xE1udio.' + TEAM_GATING_NOTE,
23508
+ 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,
23472
23509
  inputSchema: {
23473
23510
  text: external_exports.string().min(1).max(1e4).describe("Texto a ser falado."),
23474
- voice: external_exports.enum(VOICES).default(DEFAULTS.voice).describe("Voz (ex.: Kore, Puck, Charon)."),
23511
+ voice: topVoiceSchema.default(DEFAULTS.voice).describe(VOICE_HELP_TOP),
23475
23512
  model: external_exports.enum(TTS_MODELS).default(DEFAULTS.ttsModel).describe("Modelo TTS."),
23476
23513
  style_instruction: external_exports.string().max(2e3).optional().describe("Instru\xE7\xE3o de estilo/tom aplicada \xE0 fala."),
23477
23514
  multi_speaker: external_exports.object({
23478
- speaker1: external_exports.object({ name: external_exports.string().min(1).max(50), voice: external_exports.enum(VOICES) }),
23479
- speaker2: external_exports.object({ name: external_exports.string().min(1).max(50), voice: external_exports.enum(VOICES) })
23515
+ speaker1: speakerSchema,
23516
+ speaker2: speakerSchema
23480
23517
  }).optional().describe('Di\xE1logo de 2 locutores. Marque as falas no texto como "Nome: ...".'),
23481
23518
  project: external_exports.string().max(64).optional().describe('Projeto (uuid OU code curto, ex.: "VRAO-26"). Omita para usar o projeto ativo da conta.')
23482
23519
  }
23483
23520
  },
23484
23521
  async (args) => {
23485
23522
  try {
23523
+ const ms = args.multi_speaker;
23524
+ const voices = [args.voice, ms?.speaker1.voice, ms?.speaker2.voice].filter((v) => !!v);
23525
+ if (isCustomVoice(args.voice)) {
23526
+ if (!TTS_MODELS_38.includes(args.model)) {
23527
+ return errorResult("Vozes pr\xF3prias s\xF3 funcionam nos modelos Gemini 3.8 (gemini-3.8-flash-lite-tts, gemini-3.8-flash-tts).");
23528
+ }
23529
+ if (ms) {
23530
+ return errorResult("Vozes pr\xF3prias n\xE3o funcionam no modo di\xE1logo (multi_speaker). Use uma voz da biblioteca ou cl\xE1ssica.");
23531
+ }
23532
+ }
23533
+ if (!TTS_MODELS_38.includes(args.model)) {
23534
+ if (voices.some(isLibraryVoice)) {
23535
+ return errorResult(
23536
+ `Vozes da biblioteca s\xF3 funcionam nos modelos Gemini 3.8 (gemini-3.8-flash-lite-tts, gemini-3.8-flash-tts). O modelo ${args.model} s\xF3 aceita as 30 vozes cl\xE1ssicas (Kore, Puck, Charon...).`
23537
+ );
23538
+ }
23539
+ if (ms?.speaker1.style || ms?.speaker2.style) {
23540
+ return errorResult("O estilo por locutor (`style`) s\xF3 funciona nos modelos Gemini 3.8.");
23541
+ }
23542
+ }
23486
23543
  const body2 = compact({
23487
23544
  text: args.text,
23488
23545
  voice: args.voice,
@@ -23516,6 +23573,119 @@ ${BUDGET_BLOCKED_GUIDANCE}`);
23516
23573
  }
23517
23574
  }
23518
23575
  );
23576
+ server.registerTool(
23577
+ "list_tts_voices",
23578
+ {
23579
+ title: "Listar vozes da biblioteca TTS",
23580
+ description: 'Lista vozes da biblioteca do Gemini 3.8 TTS (n\xE3o inclui as 30 cl\xE1ssicas como Kore e Puck). Filtre por idioma (`language`, BCP-47, padr\xE3o pt-BR; "all" = todos), `gender`, `pitch`, `context` (ex.: Audiobook) e `search` (texto livre em nome, persona, descri\xE7\xE3o, sotaque). Passe o `id` da voz em `voice` do generate_audio com um modelo 3.8 (gemini-3.8-flash-lite-tts ou gemini-3.8-flash-tts). Somente leitura, sem custo.',
23581
+ inputSchema: {
23582
+ language: external_exports.string().max(12).optional().describe('Idioma BCP-47, ex.: pt-BR, en-US. Padr\xE3o pt-BR. "all" = sem filtro.'),
23583
+ gender: external_exports.enum(["female", "male", "neutral"]).optional(),
23584
+ pitch: external_exports.enum(["low", "medium", "high"]).optional(),
23585
+ context: external_exports.string().max(60).optional().describe("Uso da voz (trecho), ex.: Audiobook, Enterprise Agent."),
23586
+ search: external_exports.string().max(100).optional().describe("Texto livre: nome, persona, descri\xE7\xE3o, sotaque."),
23587
+ limit: external_exports.number().int().min(1).max(200).optional().describe("Padr\xE3o 60."),
23588
+ offset: external_exports.number().int().min(0).optional()
23589
+ }
23590
+ },
23591
+ async (args) => {
23592
+ try {
23593
+ const res = await client.ttsVoices(compact(args));
23594
+ const offset = args.offset ?? 0;
23595
+ if (!res.voices.length) {
23596
+ return textResult(`Nenhuma voz encontrada (total ${res.total}). Idiomas dispon\xEDveis: ${res.languages.join(", ")}.`);
23597
+ }
23598
+ const lines = res.voices.map((v) => {
23599
+ const desc = v.description ? ` | ${v.description.length > 110 ? `${v.description.slice(0, 107)}...` : v.description}` : "";
23600
+ return `${v.id} | ${v.name} | ${v.gender} | ${v.pitch}${desc}`;
23601
+ });
23602
+ const more = res.total > offset + res.voices.length ? ` Use offset=${offset + res.voices.length} para ver mais.` : "";
23603
+ return textResult(
23604
+ `Vozes ${offset + 1}-${offset + res.voices.length} de ${res.total} (id | nome | g\xEAnero | tom | descri\xE7\xE3o):
23605
+ ${lines.join("\n")}
23606
+
23607
+ Use o id em voice (modelos 3.8).${more}
23608
+ Contextos: ${res.contexts.join(", ")}.`
23609
+ );
23610
+ } catch (e) {
23611
+ return errorResult(apiErrorToUserMessage(e));
23612
+ }
23613
+ }
23614
+ );
23615
+ server.registerTool(
23616
+ "list_custom_voices",
23617
+ {
23618
+ title: "Listar vozes pr\xF3prias",
23619
+ 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.",
23620
+ inputSchema: {}
23621
+ },
23622
+ async () => {
23623
+ try {
23624
+ const res = await client.customVoices();
23625
+ const head = `Vozes pr\xF3prias: ${res.used} de ${res.limit}. Criar uma voz custa ${res.design_cost} \u{1F48E}.`;
23626
+ if (!res.voices.length) return textResult(`${head}
23627
+ Nenhuma ainda. Use design_voice para criar.`);
23628
+ const lines = res.voices.map(
23629
+ (v) => `${v.id} | ${v.voice} | ${v.name} | ${v.kind} | expira ${v.expires_at.slice(0, 10)}`
23630
+ );
23631
+ return textResult(
23632
+ `${head} (id | voice | nome | tipo | validade):
23633
+ ${lines.join("\n")}
23634
+
23635
+ Use o valor de "voice" (voice_xxx) no generate_audio. Para apagar, use o "id" em delete_custom_voice.`
23636
+ );
23637
+ } catch (e) {
23638
+ return errorResult(apiErrorToUserMessage(e));
23639
+ }
23640
+ }
23641
+ );
23642
+ server.registerTool(
23643
+ "design_voice",
23644
+ {
23645
+ title: "Criar voz pr\xF3pria por descri\xE7\xE3o",
23646
+ 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).",
23647
+ inputSchema: {
23648
+ name: external_exports.string().min(1).max(40).describe("Nome da voz (1 a 40 caracteres)."),
23649
+ 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)."),
23650
+ language: external_exports.string().max(12).optional().describe("Idioma BCP-47. Padr\xE3o pt-BR."),
23651
+ gender: external_exports.enum(["female", "male", "neutral"]).optional()
23652
+ }
23653
+ },
23654
+ async (args) => {
23655
+ try {
23656
+ const res = await client.designVoice(compact(args));
23657
+ const v = res.voice;
23658
+ return textResult(
23659
+ `\u2705 Voz criada: ${v.name} (${v.kind}).
23660
+ voice: ${v.voice}
23661
+ id: ${v.id}
23662
+ ` + (v.sample_url ? `Amostra: ${v.sample_url}
23663
+ ` : "") + `Custo: ${res.diamond_cost} \u{1F48E} \xB7 Saldo: ${res.new_balance} \u{1F48E} \xB7 Expira em ${v.expires_at.slice(0, 10)}.
23664
+ Use o valor de "voice" no generate_audio com um modelo 3.8 (sem multi_speaker).`
23665
+ );
23666
+ } catch (e) {
23667
+ return errorResult(apiErrorToUserMessage(e));
23668
+ }
23669
+ }
23670
+ );
23671
+ server.registerTool(
23672
+ "delete_custom_voice",
23673
+ {
23674
+ title: "Apagar voz pr\xF3pria",
23675
+ 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.",
23676
+ inputSchema: {
23677
+ id: external_exports.string().uuid().describe('Campo "id" (uuid) da voz em list_custom_voices.')
23678
+ }
23679
+ },
23680
+ async (args) => {
23681
+ try {
23682
+ await client.deleteCustomVoice(args.id);
23683
+ return textResult(`\u2705 Voz ${args.id} apagada. Uma vaga foi liberada.`);
23684
+ } catch (e) {
23685
+ return errorResult(apiErrorToUserMessage(e));
23686
+ }
23687
+ }
23688
+ );
23519
23689
  }
23520
23690
 
23521
23691
  // src/tools/music.ts
@@ -24321,7 +24491,7 @@ var KINDS = {
24321
24491
  tts: {
24322
24492
  title: "Locu\xE7\xE3o",
24323
24493
  size: { w: 320, h: 212 },
24324
- data: { model: "gemini-3.1-flash-tts-preview", voice: "Algieba", speed: "normal" },
24494
+ data: { model: "gemini-3.8-flash-lite-tts", voice: "Algieba", speed: "normal" },
24325
24495
  inputs: ["text"],
24326
24496
  outputs: ["audio", "approved"],
24327
24497
  dynamic: "style conforme o modelo"
@@ -26867,7 +27037,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
26867
27037
  import { createRequire } from "module";
26868
27038
  var require2 = createRequire(import.meta.url);
26869
27039
  function readVersion() {
26870
- if ("0.32.0") return "0.32.0";
27040
+ if ("0.34.0") return "0.34.0";
26871
27041
  try {
26872
27042
  const pkg = require2("../package.json");
26873
27043
  return pkg.version ?? "0.0.0-unknown";