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.
- package/README.md +11 -1
- package/dist/index.js +54 -19
- package/dist/index.js.map +1 -1
- package/dist/remote-server.js +54 -19
- package/dist/remote-server.js.map +1 -1
- package/package.json +1 -1
package/dist/remote-server.js
CHANGED
|
@@ -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 >
|
|
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 >
|
|
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 >
|
|
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
|
|
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.
|
|
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 = [
|
|
24792
|
-
if (isCustomVoice(
|
|
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
|
|
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 ?
|
|
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.
|
|
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";
|