beplus-mcp 0.41.0 → 0.43.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.
@@ -22517,7 +22517,7 @@ var BeplusClient = class {
22517
22517
  });
22518
22518
  }
22519
22519
  tts(body2) {
22520
- return this.request("POST", "/tts", { body: body2, timeoutMs: 9e4 });
22520
+ return this.request("POST", "/tts", { body: body2, timeoutMs: body2.model === "seed-audio-1.0" ? 18e4 : 9e4 });
22521
22521
  }
22522
22522
  ttsVoices(query) {
22523
22523
  return this.request("GET", "/tts/voices", { query, timeoutMs: 2e4 });
@@ -22820,7 +22820,7 @@ function tooLarge(name, bytes) {
22820
22820
  `"${name}" ${size} acima do teto de 95 MB para subir pela API (o proxy da Cloudflare corta corpo acima de 100 MB antes de chegar no servidor). Comprima ou corte o arquivo (ex.: ffmpeg -i entrada.mp4 -crf 26 saida.mp4) e tente de novo.`
22821
22821
  );
22822
22822
  }
22823
- async function loadLocal(ref) {
22823
+ async function loadLocal(ref, maxBytes = MAX_UPLOAD_BYTES) {
22824
22824
  const abs = toLocalPath(ref);
22825
22825
  const name = basename(abs);
22826
22826
  let size;
@@ -22832,10 +22832,10 @@ async function loadLocal(ref) {
22832
22832
  `Arquivo local n\xE3o encontrado: "${ref}". Passe um caminho v\xE1lido ou uma URL p\xFAblica (http/https).`
22833
22833
  );
22834
22834
  }
22835
- if (size > MAX_UPLOAD_BYTES) throw tooLarge(name, size);
22835
+ if (size > maxBytes) throw maxBytes === MAX_UPLOAD_BYTES ? tooLarge(name, size) : new ApiError(413, `O arquivo deve ter at\xE9 ${mb(maxBytes)} MB.`);
22836
22836
  return { buf: await readFile2(abs), name, mime: mimeForName(abs), localPath: abs };
22837
22837
  }
22838
- async function loadRemote(url) {
22838
+ async function loadRemote(url, maxBytes = MAX_UPLOAD_BYTES) {
22839
22839
  const u = new URL(url);
22840
22840
  let name = decodeURIComponent(basename(u.pathname)) || "arquivo";
22841
22841
  let res;
@@ -22851,10 +22851,10 @@ async function loadRemote(url) {
22851
22851
  throw new ApiError(res.status, `N\xE3o consegui baixar ${url}: a origem respondeu HTTP ${res.status}.`);
22852
22852
  }
22853
22853
  const declared = Number(res.headers.get("content-length") ?? NaN);
22854
- if (Number.isFinite(declared) && declared > MAX_UPLOAD_BYTES) {
22854
+ if (Number.isFinite(declared) && declared > maxBytes) {
22855
22855
  await res.body?.cancel().catch(() => {
22856
22856
  });
22857
- throw tooLarge(name, declared);
22857
+ throw maxBytes === MAX_UPLOAD_BYTES ? tooLarge(name, declared) : new ApiError(413, `O arquivo deve ter at\xE9 ${mb(maxBytes)} MB.`);
22858
22858
  }
22859
22859
  const chunks = [];
22860
22860
  let total = 0;
@@ -22865,10 +22865,10 @@ async function loadRemote(url) {
22865
22865
  const { done, value } = await reader.read();
22866
22866
  if (done) break;
22867
22867
  total += value.byteLength;
22868
- if (total > MAX_UPLOAD_BYTES) {
22868
+ if (total > maxBytes) {
22869
22869
  await reader.cancel().catch(() => {
22870
22870
  });
22871
- throw tooLarge(name, null);
22871
+ throw maxBytes === MAX_UPLOAD_BYTES ? tooLarge(name, null) : new ApiError(413, `O arquivo deve ter at\xE9 ${mb(maxBytes)} MB.`);
22872
22872
  }
22873
22873
  chunks.push(Buffer.from(value.buffer, value.byteOffset, value.byteLength));
22874
22874
  }
@@ -23179,6 +23179,7 @@ var MUSIC_TASK_TYPES = ["create", "extend", "cover", "upload_extend", "upload_co
23179
23179
  var MUSIC_TOOLS = ["wav", "midi", "stems-basic", "stems-full", "bpm", "lyrics-timeline"];
23180
23180
  var VOCAL_GENDERS = ["f", "m"];
23181
23181
  var TTS_MODELS = [
23182
+ "seed-audio-1.0",
23182
23183
  "gemini-3.8-flash-lite-tts",
23183
23184
  "gemini-3.8-flash-tts",
23184
23185
  "gemini-3.1-flash-tts-preview",
@@ -24753,7 +24754,7 @@ var VOICE_HELP_TOP = `${VOICE_HELP} Ou o id de uma voz pr\xF3pria (voice_xxx, de
24753
24754
  var voiceSchema = external_exports.string().refine((v) => VOICES.includes(v) || LIBRARY_VOICE_ID.test(v), {
24754
24755
  message: "Voz inv\xE1lida: use uma das 30 vozes cl\xE1ssicas (ex.: Kore) ou um id da biblioteca (ex.: pt-br-advisor-10)."
24755
24756
  });
24756
- var topVoiceSchema = external_exports.string().refine((v) => VOICES.includes(v) || LIBRARY_VOICE_ID.test(v) || CUSTOM_VOICE_ID.test(v), {
24757
+ var topVoiceSchema = external_exports.string().refine((v) => v === "seed-auto" || VOICES.includes(v) || LIBRARY_VOICE_ID.test(v) || CUSTOM_VOICE_ID.test(v), {
24757
24758
  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)."
24758
24759
  });
24759
24760
  function isCustomVoice(v) {
@@ -24772,10 +24773,15 @@ function registerAudioTools(server, client, cfg) {
24772
24773
  "generate_audio",
24773
24774
  {
24774
24775
  title: "Gerar \xE1udio (TTS)",
24775
- 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,
24776
+ description: 'Sintetiza fala a partir de texto e retorna a URL usando o IA Lab da BePlus. SeedAudio 1.0 (seed-audio-1.0) aceita dire\xE7\xE3o, volume e at\xE9 3 refer\xEAncias de voz em seed_references (ou seed_reference legado), com seed_consent. Para v\xE1rias vozes, marque todas no texto: @Audio1: Ol\xE1. @Audio2: Oi. Um ID pr\xF3prio em seed_reference_generation_id reutiliza todas as refer\xEAncias. Texto e dire\xE7\xE3o somados at\xE9 2700 caracteres. N\xE3o aceita multi_speaker nem vozes Gemini. 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,
24776
24777
  inputSchema: {
24777
24778
  text: external_exports.string().min(1).max(1e4).describe("Texto a ser falado."),
24778
- voice: topVoiceSchema.default(DEFAULTS.voice).describe(VOICE_HELP_TOP),
24779
+ voice: topVoiceSchema.optional().describe(VOICE_HELP_TOP + " No SeedAudio, omita ou use seed-auto."),
24780
+ seed_reference: external_exports.string().min(1).optional().describe("SeedAudio: arquivo local (stdio) ou URL p\xFAblica de uma voz autorizada, de 1 a 30 s e at\xE9 3 MiB. N\xE3o \xE9 publicado pelo MCP."),
24781
+ seed_references: external_exports.array(external_exports.string().min(1)).min(1).max(3).optional().describe("SeedAudio: at\xE9 3 arquivos locais (stdio) ou URLs p\xFAblicas, na ordem @Audio1, @Audio2, @Audio3. Cada \xE1udio de 1 a 30 s; soma de at\xE9 3 MiB. Use todos os marcadores no texto quando houver v\xE1rias vozes."),
24782
+ seed_loudness_rate: external_exports.number().int().min(-50).max(100).optional().describe("SeedAudio: volume nativo. -50 = 50%, 0 = 100% (normal), 100 = 200%."),
24783
+ seed_reference_generation_id: external_exports.string().uuid().optional().describe("Reutiliza a refer\xEAncia de uma gera\xE7\xE3o SeedAudio sua. Alternativa a seed_reference e seed_references; reutiliza todas as vozes da gera\xE7\xE3o."),
24784
+ seed_consent: external_exports.literal(true).optional().describe("Confirme apenas ap\xF3s autoriza\xE7\xE3o expl\xEDcita da pessoa para usar sua voz. Obrigat\xF3rio com refer\xEAncia."),
24779
24785
  model: external_exports.enum(TTS_MODELS).default(DEFAULTS.ttsModel).describe("Modelo TTS."),
24780
24786
  style_instruction: external_exports.string().max(2e3).optional().describe("Instru\xE7\xE3o de estilo/tom aplicada \xE0 fala."),
24781
24787
  multi_speaker: external_exports.object({
@@ -24787,9 +24793,24 @@ function registerAudioTools(server, client, cfg) {
24787
24793
  },
24788
24794
  async (args) => {
24789
24795
  try {
24796
+ const seed = args.model === "seed-audio-1.0";
24797
+ const voice = args.voice ?? (seed ? "seed-auto" : DEFAULTS.voice);
24798
+ const hasReference = !!(args.seed_reference || args.seed_references || args.seed_reference_generation_id);
24799
+ if (!seed && (hasReference || args.seed_consent !== void 0 || args.seed_loudness_rate !== void 0 || voice === "seed-auto")) return errorResult("Os controles SeedAudio exigem seed-audio-1.0.");
24800
+ if (seed && (voice !== "seed-auto" || args.multi_speaker)) return errorResult("SeedAudio usa seed-auto. Para v\xE1rias vozes, use seed_references e marcadores @Audio, sem multi_speaker.");
24801
+ if ([args.seed_reference, args.seed_references, args.seed_reference_generation_id].filter(Boolean).length > 1) return errorResult("Use apenas uma origem de refer\xEAncia.");
24802
+ if (hasReference && !args.seed_consent) return errorResult("Confirme a autoriza\xE7\xE3o da voz em seed_consent.");
24803
+ if (seed && args.text.trim().length + (args.style_instruction?.trim().length ?? 0) > 2700) return errorResult("SeedAudio: texto e dire\xE7\xE3o devem somar at\xE9 2700 caracteres.");
24804
+ const referenceSources = args.seed_references ?? (args.seed_reference ? [args.seed_reference] : []);
24805
+ if (seed && !args.seed_reference_generation_id) {
24806
+ const markersIn = (value) => (value.match(/@Audio[^\s:,.!?;"'()\[\]{}]*/gi) ?? []).map((token) => /^@Audio[1-3]$/.test(token) ? Number(token.slice(6)) : 0);
24807
+ const markers = markersIn(args.text);
24808
+ const allMarkers = [...markers, ...markersIn(args.style_instruction ?? "")];
24809
+ if (allMarkers.some((index) => index < 1 || index > referenceSources.length) || referenceSources.length > 1 && referenceSources.some((_, index) => !markers.includes(index + 1))) return errorResult("Use os marcadores @Audio1, @Audio2 e @Audio3 correspondentes a todas as refer\xEAncias enviadas.");
24810
+ }
24790
24811
  const ms = args.multi_speaker;
24791
- const voices = [args.voice, ms?.speaker1.voice, ms?.speaker2.voice].filter((v) => !!v);
24792
- if (isCustomVoice(args.voice)) {
24812
+ const voices = [voice, ms?.speaker1.voice, ms?.speaker2.voice].filter((v) => !!v);
24813
+ if (isCustomVoice(voice)) {
24793
24814
  if (!TTS_MODELS_38.includes(args.model)) {
24794
24815
  return errorResult("Vozes pr\xF3prias s\xF3 funcionam nos modelos Gemini 3.8 (gemini-3.8-flash-lite-tts, gemini-3.8-flash-tts).");
24795
24816
  }
@@ -24797,7 +24818,7 @@ function registerAudioTools(server, client, cfg) {
24797
24818
  return errorResult("Vozes pr\xF3prias n\xE3o funcionam no modo di\xE1logo (multi_speaker). Use uma voz da biblioteca ou cl\xE1ssica.");
24798
24819
  }
24799
24820
  }
24800
- if (!TTS_MODELS_38.includes(args.model)) {
24821
+ if (!seed && !TTS_MODELS_38.includes(args.model)) {
24801
24822
  if (voices.some(isLibraryVoice)) {
24802
24823
  return errorResult(
24803
24824
  `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...).`
@@ -24807,9 +24828,22 @@ function registerAudioTools(server, client, cfg) {
24807
24828
  return errorResult("O estilo por locutor (`style`) s\xF3 funciona nos modelos Gemini 3.8.");
24808
24829
  }
24809
24830
  }
24831
+ const seedReferences = [];
24832
+ let remainingBytes = 3 * 1024 * 1024;
24833
+ for (const source of referenceSources) {
24834
+ const file = await (isRemoteRef(source) ? loadRemote(source, remainingBytes) : loadLocal(source, remainingBytes));
24835
+ if (!file.buf.length || file.buf.length > remainingBytes) return errorResult("As refer\xEAncias devem somar at\xE9 3 MiB.");
24836
+ remainingBytes -= file.buf.length;
24837
+ seedReferences.push({ audio: file.buf.toString("base64"), mime: file.mime });
24838
+ }
24810
24839
  const body2 = compact({
24840
+ seedReference: args.seed_reference ? seedReferences[0] : void 0,
24841
+ seedReferences: args.seed_references ? seedReferences : void 0,
24842
+ seedLoudnessRate: args.seed_loudness_rate,
24843
+ seedReferenceGenerationId: args.seed_reference_generation_id,
24844
+ seedConsent: args.seed_consent,
24811
24845
  text: args.text,
24812
- voice: args.voice,
24846
+ voice,
24813
24847
  model: args.model,
24814
24848
  styleInstruction: args.style_instruction,
24815
24849
  multiSpeaker: args.multi_speaker,
@@ -24819,12 +24853,13 @@ function registerAudioTools(server, client, cfg) {
24819
24853
  const parts = [`Custo: ${res.diamond_cost} \u{1F48E}`];
24820
24854
  if (res.diamonds_refunded) parts.push(`Estorno: ${res.diamonds_refunded} \u{1F48E}`);
24821
24855
  const projLine = res.project_code ? `
24822
- \u{1F4C1} Projeto: ${res.project_code}${res.project_name ? ` \u2014 ${res.project_name}` : ""}` : "";
24856
+ \u{1F4C1} Projeto: ${res.project_code}${res.project_name ? `: ${res.project_name}` : ""}` : "";
24823
24857
  const wa = weeklyAllowanceLine(res.weekly_allowance);
24824
24858
  const budget = budgetLine(res.budget);
24825
24859
  return textResult(
24826
- `\u2705 \xC1udio gerado (${res.model}, voz ${res.voice}, ${res.duration_sec.toFixed(1)}s).
24860
+ `\u2705 \xC1udio gerado (${res.model}, voz ${seed ? "por refer\xEAncia ou descri\xE7\xE3o" : res.voice}, ${res.duration_sec.toFixed(1)}s).
24827
24861
  ${res.url}
24862
+ Gera\xE7\xE3o: ${res.generation_id}
24828
24863
  ${parts.join(" \xB7 ")}${projLine}` + (budget ? `
24829
24864
  ${budget}` : "") + (wa ? `
24830
24865
  ${wa}` : "")
@@ -25670,7 +25705,7 @@ var KINDS = {
25670
25705
  data: { model: "gemini-3.8-flash-lite-tts", voice: "Algieba", speed: "normal" },
25671
25706
  inputs: ["text"],
25672
25707
  outputs: ["audio", "approved"],
25673
- dynamic: "style conforme o modelo"
25708
+ dynamic: "style conforme o modelo; SeedAudio 1.0 tem reference (audio, at\xE9 3 vozes na ordem @Audio1..3), volume seedLoudnessRate (-50..100), usa voice: seed-auto e seedConsent: true com refer\xEAncia; alternativa seedReferenceGenerationId de gera\xE7\xE3o pr\xF3pria"
25674
25709
  },
25675
25710
  music: {
25676
25711
  title: "Trilha",
@@ -28720,7 +28755,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
28720
28755
  import { createRequire } from "module";
28721
28756
  var require2 = createRequire(import.meta.url);
28722
28757
  function readVersion() {
28723
- if ("0.41.0") return "0.41.0";
28758
+ if ("0.43.0") return "0.43.0";
28724
28759
  try {
28725
28760
  const pkg = require2("../package.json");
28726
28761
  return pkg.version ?? "0.0.0-unknown";