sapiens-mcp 1.43.3 → 1.43.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.
- package/dist/registry.js +3 -3
- package/dist/skills.js +1 -1
- package/dist/tools/helen.js +32 -8
- package/dist/tools/pipeline.js +61 -4
- package/dist/tools/stockAudio.js +1 -1
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -42,7 +42,7 @@ import { skillMenuLine } from "./skills.js";
|
|
|
42
42
|
*/
|
|
43
43
|
export const TOOLS = {
|
|
44
44
|
sapiens_pipeline: {
|
|
45
|
-
description: "CRUD do content pipeline Sapiens (sources/productions/publishables). Sub-actions: list_sources, list_articles (use includeDrafts pra incluir drafts; onlyAvailable pra esconder os já virados em source), get_source, get_production, list_versions, add_article_as_source, create_draft_article_and_source (seed), create_production (sourceId+format → productionId draft), update_production (substitui payload, opcionalmente muda status), finalize_production (cria publishable v1, v2... com snapshot), remove_production, remove_source, set_source_done, update_source_notes, restore_version (volta payload duma versão antiga), set_publishable_title (renomeia um publishable), backfill_via (rotula em lote o campo 'via' das productions antigas; dryRun=true só lista), propose_mega_grafico_plan (granular: só gera plano via Gemini, devolve fullPrompt+spec), run_mega_grafico_full (ONE-SHOT, recomendado: cria production+propõe plano+gera imagem+aplica selo Sapiens+finaliza publishable numa chamada só), generate_carousel (gera um carrossel editorial standalone a partir de brief OU articleId — 7-9 slides na voz Sapiens + imagens do banco; devolve id + url do editor pro humano abrir, ajustar e exportar; admin-only, cobra Sinapses, reembolsa se falhar). generate_carousel_production (o IRMÃO PIPELINE do generate_carousel: recebe um sourceId de artigo, CRIA a production carrossel_ig e a preenche pelo MESMO motor da casa, já no shape editorial (templateId+slots) que o editor de pipeline renderiza — prefira ESTE a create_production+payload cru pro carrossel, que abre VAZIO no editor; devolve productionId + url do editor de pipeline; admin-only, cobra Sinapses, reembolsa se falhar). CARROSSEL FINO (edição sem tela, admin-only): list_carousels (seus carrosséis standalone), get_carousel (payload completo + catálogo de templates com slots/limites + paletas — tudo pra VOCÊ escrever os slides), update_carousel (payload inteiro de volta, sanitizado no servidor; preserve os campos image dos slides que não mexeu), carousel_auto_images (IA escolhe imagens do banco pros slides de foto, 60 Sinapses; makeVisual=true converte slides de texto pra layouts de foto antes — ritmo visual; generateMissing=true gera imagem nova pros que o banco não cobrir, ~450 Sinapses cada, até 4, avise o custo antes), carousel_generate_image (imagem nova pra UM slide, ~450 Sinapses, customPrompt opcional). Fluxo confortável (standalone): generate_carousel → get_carousel → update_carousel (afia os textos) → carousel_auto_images → humano abre a url pra exportar. Fluxo pipeline (carrossel atrelado a um artigo/source): generate_carousel_production (sourceId) → humano abre a url do editor de pipeline pra revisar e finalizar (finalize_production). Pra mega_grafico, SEMPRE prefira run_mega_grafico_full em vez de sequenciar manualmente (menos drift). Idempotente só na production (passa productionId pra reusar a MESMA row), mas cada run RE-GERA a imagem e cobra de novo (~900 Sinapses): não é grátis re-rodar. OBRIGATÓRIO perguntar ao user antes se withHelen=true (cartoon Helen interage com tema, ~15-25% do poster) ou false (poster 100% diagramático). Custo ~900-1000 sinapses por geração. run_mega_grafico_full, generate_carousel, generate_carousel_production, carousel_auto_images (com generateMissing) e carousel_generate_image são SÍNCRONAS e pesadas: vale a REGRA DO TIMEOUT (podem cobrar mesmo voltando 'Timeout'; cheque get_carousel/dashboard antes de repetir). Use skipFinalize=true se quiser deixar production em 'ready' pro admin revisar antes de publishable. Payload livre por formato — chame sapiens_meta action=formats pra ver schemas sugeridos.",
|
|
45
|
+
description: "CRUD do content pipeline Sapiens (sources/productions/publishables). Sub-actions: list_sources, list_articles (use includeDrafts pra incluir drafts; onlyAvailable pra esconder os já virados em source), get_source, get_production, list_versions, add_article_as_source, create_draft_article_and_source (seed), create_production (sourceId+format → productionId draft), update_production (substitui payload, opcionalmente muda status), finalize_production (cria publishable v1, v2... com snapshot), remove_production, remove_source, set_source_done, update_source_notes, restore_version (volta payload duma versão antiga), set_publishable_title (renomeia um publishable), backfill_via (rotula em lote o campo 'via' das productions antigas; dryRun=true só lista), propose_mega_grafico_plan (granular: só gera plano via Gemini, devolve fullPrompt+spec), run_mega_grafico_full (ONE-SHOT, recomendado: cria production+propõe plano+gera imagem+aplica selo Sapiens+finaliza publishable numa chamada só), generate_carousel (gera um carrossel editorial standalone a partir de brief OU articleId — 7-9 slides na voz Sapiens + imagens do banco; devolve id + url do editor pro humano abrir, ajustar e exportar; admin-only, cobra Sinapses, reembolsa se falhar; model opcional trava uma folha registrada da casa, ex 'feed' ou 'reflexao', em vez do caminho editorial livre). generate_carousel_production (o IRMÃO PIPELINE do generate_carousel: recebe um sourceId de artigo, CRIA a production carrossel_ig e a preenche pelo MESMO motor da casa, já no shape editorial (templateId+slots) que o editor de pipeline renderiza — prefira ESTE a create_production+payload cru pro carrossel, que abre VAZIO no editor; devolve productionId + url do editor de pipeline; admin-only, cobra Sinapses, reembolsa se falhar; model opcional trava a folha registrada; beats opcional entrega copy PRONTO por beat da espinha, [{n, slots}], quando o agente JÁ escreveu e validou os blocos: com beats o Gemini de escrita NÃO roda e a rodada cobra só o picker de imagens, zero com autoPickImages=false; caption opcional vira a legenda do meta). CARROSSEL FINO (edição sem tela, admin-only): list_carousels (seus carrosséis standalone), get_carousel (payload completo + catálogo de templates com slots/limites + paletas — tudo pra VOCÊ escrever os slides), update_carousel (payload inteiro de volta, sanitizado no servidor; preserve os campos image dos slides que não mexeu), carousel_auto_images (IA escolhe imagens do banco pros slides de foto, 60 Sinapses; aceita carouselId standalone OU productionId de carrossel da pipeline; makeVisual=true converte slides de texto pra layouts de foto antes — ritmo visual; generateMissing=true gera imagem nova pros que o banco não cobrir, ~450 Sinapses cada, até 4, avise o custo antes), carousel_generate_image (imagem nova pra UM slide, ~450 Sinapses, customPrompt opcional). Fluxo confortável (standalone): generate_carousel → get_carousel → update_carousel (afia os textos) → carousel_auto_images → humano abre a url pra exportar. Fluxo pipeline (carrossel atrelado a um artigo/source): generate_carousel_production (sourceId) → humano abre a url do editor de pipeline pra revisar e finalizar (finalize_production). Fluxo pipeline com copy do agente (a skill escreveu os blocos): generate_carousel_production (sourceId + model + beats) → carousel_auto_images (productionId) se faltar foto → humano revisa e finaliza. Pra mega_grafico, SEMPRE prefira run_mega_grafico_full em vez de sequenciar manualmente (menos drift). Idempotente só na production (passa productionId pra reusar a MESMA row), mas cada run RE-GERA a imagem e cobra de novo (~900 Sinapses): não é grátis re-rodar. OBRIGATÓRIO perguntar ao user antes se withHelen=true (cartoon Helen interage com tema, ~15-25% do poster) ou false (poster 100% diagramático). Custo ~900-1000 sinapses por geração. run_mega_grafico_full, generate_carousel, generate_carousel_production, carousel_auto_images (com generateMissing) e carousel_generate_image são SÍNCRONAS e pesadas: vale a REGRA DO TIMEOUT (podem cobrar mesmo voltando 'Timeout'; cheque get_carousel/dashboard antes de repetir). Use skipFinalize=true se quiser deixar production em 'ready' pro admin revisar antes de publishable. Payload livre por formato — chame sapiens_meta action=formats pra ver schemas sugeridos.",
|
|
46
46
|
schema: pipelineSchema,
|
|
47
47
|
handler: pipeline,
|
|
48
48
|
},
|
|
@@ -107,7 +107,7 @@ export const TOOLS = {
|
|
|
107
107
|
handler: persona,
|
|
108
108
|
},
|
|
109
109
|
sapiens_helen: {
|
|
110
|
-
description: "Helen Voice TTS via ElevenLabs
|
|
110
|
+
description: "Helen Voice TTS via ElevenLabs, Google Gemini ou Fish Audio (qualquer logado; cobra Sinapses). Sub-actions: list_presets (catálogo de voiceIds/voiceNames recomendados + stylePreambles), speak (sintetiza, retorna audioBase64+mimeType+sizeBytes). provider=fish é o S2.1 Pro, o mais forte em japonês, mandarim e coreano: fala de personagem e cena de anime pedem ele. `language` escolhe o idioma (auto|pt|en|ja|es|ko|zh|fr|it|de). BYOK suportado via clientApiKey, senão usa env do deploy. Custo: ElevenLabs ~$0.30/500c, Google ~$0.01/500c, Fish grátis via API até 31/08/2026. Max 5000 chars (quebra antes em chunks). text pré-processado pelo caller (sem em-dash, sem markdown).",
|
|
111
111
|
schema: helenSchema,
|
|
112
112
|
handler: helen,
|
|
113
113
|
},
|
|
@@ -127,7 +127,7 @@ export const TOOLS = {
|
|
|
127
127
|
handler: video,
|
|
128
128
|
},
|
|
129
129
|
sapiens_stock_audio: {
|
|
130
|
-
description: "Banco de som da casa: trilha pronta E efeito sonoro (tabela stockAudio). Sub-actions de leitura (públicas, sem auth): categories (lista os moods/usos), list (busca com filtros mood/albumSlug/durationMax/search; kind='sfx' traz os EFEITOS: whoosh, clique, impacto, ambiência, foley — devolve {count, items} com title/url/durationSeconds/tags), get (1 item por audioId). Use pra puxar trilha/efeito pronto: pega a `url` e usa direto no ffmpeg. Não achou o efeito? generate (COBRA Sinapses, exige login) cria um novo por texto: prompt + durationSeconds (1-15, default 5) + provider ('mirelo' padrão
|
|
130
|
+
description: "Banco de som da casa: trilha pronta E efeito sonoro (tabela stockAudio). Sub-actions de leitura (públicas, sem auth): categories (lista os moods/usos), list (busca com filtros mood/albumSlug/durationMax/search; kind='sfx' traz os EFEITOS: whoosh, clique, impacto, ambiência, foley — devolve {count, items} com title/url/durationSeconds/tags), get (1 item por audioId). Use pra puxar trilha/efeito pronto: pega a `url` e usa direto no ffmpeg. Não achou o efeito? generate (COBRA Sinapses, exige login) cria um novo por texto: prompt + durationSeconds (1-15, default 5) + provider ('mirelo' padrão 35 Sinapses/s mín 70 | 'elevenlabs' premium 60/s mín 120) + promptInfluence opcional (0..1, só elevenlabs: fidelidade ao texto, default 0.3), assíncrono — acompanhe com generation-status (generationId) até 'ready' (audioUrl; o efeito também entra no acervo kind=sfx) ou 'failed' (Sinapses reembolsadas). Efeito é CURTO (1-15s): música/trilha nova é no sapiens_musicator. Mood disponíveis: calmo, intenso, narrativo, épico, sombrio.",
|
|
131
131
|
schema: stockAudioSchema,
|
|
132
132
|
handler: stockAudio,
|
|
133
133
|
},
|
package/dist/skills.js
CHANGED
|
@@ -144,7 +144,7 @@ Depois de pronta: \`action=publish\` põe a faixa no Acervo da Comunidade (só a
|
|
|
144
144
|
Efeito é CURTO. Música inteira é no Musicator, não aqui.
|
|
145
145
|
|
|
146
146
|
1. Procure pronto primeiro: \`sapiens_stock_audio action=list kind=sfx\`. Grátis.
|
|
147
|
-
2. Não achou: \`action=generate\` com \`prompt\` e \`durationSeconds\` (1 a 15, default 5) e \`provider\` ('mirelo' padrão
|
|
147
|
+
2. Não achou: \`action=generate\` com \`prompt\` e \`durationSeconds\` (1 a 15, default 5) e \`provider\` ('mirelo' padrão 35 Sinapses/s mín 70, 'elevenlabs' premium 60/s mín 120). \`promptInfluence\` (0..1) só vale no elevenlabs.
|
|
148
148
|
3. É assíncrono: devolve \`generationId\`, acompanhe com \`action=generation-status\` até 'ready' (traz audioUrl) ou 'failed' (reembolsa sozinho).
|
|
149
149
|
|
|
150
150
|
## Sonorizar um clipe
|
package/dist/tools/helen.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { convexAction, getSessionToken } from "../convexClient.js";
|
|
3
3
|
/**
|
|
4
|
-
* Helen Voice — Text-to-Speech via ElevenLabs ou
|
|
4
|
+
* Helen Voice — Text-to-Speech via ElevenLabs, Google Gemini ou Fish Audio.
|
|
5
5
|
*
|
|
6
6
|
* Sub-actions:
|
|
7
7
|
* - speak: sintetiza fala. Retorna audioBase64 + mimeType + sizeBytes.
|
|
@@ -18,13 +18,13 @@ export const helenSchema = z.object({
|
|
|
18
18
|
.optional()
|
|
19
19
|
.describe("Texto a falar (action=speak). Max 5000 chars."),
|
|
20
20
|
provider: z
|
|
21
|
-
.enum(["elevenlabs", "google"])
|
|
21
|
+
.enum(["elevenlabs", "google", "fish"])
|
|
22
22
|
.optional()
|
|
23
|
-
.describe("elevenlabs (
|
|
23
|
+
.describe("elevenlabs (inglês expressivo, mais caro), google (Gemini TTS, mais barato) ou fish (S2.1 Pro, o melhor em japonês e nas línguas asiáticas). Default elevenlabs."),
|
|
24
24
|
modelId: z
|
|
25
25
|
.string()
|
|
26
26
|
.optional()
|
|
27
|
-
.describe("ElevenLabs: 'eleven_v3' (default) ou 'eleven_multilingual_v2'. Google: 'gemini-3.1-flash-tts-preview' (default)."),
|
|
27
|
+
.describe("ElevenLabs: 'eleven_v3' (default) ou 'eleven_multilingual_v2'. Google: 'gemini-3.1-flash-tts-preview' (default). Fish: escolhido no servidor, o que vier aqui é ignorado."),
|
|
28
28
|
voiceId: z
|
|
29
29
|
.string()
|
|
30
30
|
.optional()
|
|
@@ -33,10 +33,18 @@ export const helenSchema = z.object({
|
|
|
33
33
|
.string()
|
|
34
34
|
.optional()
|
|
35
35
|
.describe("Google prebuilt voice (default Kore). Use list_presets pra ver opções."),
|
|
36
|
+
fishReferenceId: z
|
|
37
|
+
.string()
|
|
38
|
+
.optional()
|
|
39
|
+
.describe("Fish: id da voz no acervo do fish.audio. Sem ele vai a voz default do modelo."),
|
|
40
|
+
language: z
|
|
41
|
+
.enum(["auto", "pt", "en", "ja", "es", "ko", "zh", "fr", "it", "de"])
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("Idioma da fala. Cada motor recebe no dialeto dele; fish e google detectam pelo texto, então lá isto é informativo. Default pt."),
|
|
36
44
|
languageCode: z
|
|
37
45
|
.string()
|
|
38
46
|
.optional()
|
|
39
|
-
.describe("ElevenLabs: ex 'pt' pra PT-BR otimizado."),
|
|
47
|
+
.describe("ElevenLabs: ex 'pt' pra PT-BR otimizado. Vence o `language` quando os dois vêm."),
|
|
40
48
|
stylePreamble: z
|
|
41
49
|
.string()
|
|
42
50
|
.optional()
|
|
@@ -85,6 +93,16 @@ const PRESETS = {
|
|
|
85
93
|
"Read this slow and contemplative, with pauses:",
|
|
86
94
|
],
|
|
87
95
|
},
|
|
96
|
+
fish: {
|
|
97
|
+
note: "Fish Audio S2.1 Pro. Não precisa de modelId (o servidor escolhe) e detecta o idioma pelo texto. É o motor mais forte da casa em japonês, mandarim e coreano: cena de anime, fala de personagem, narração em ja pedem ele. Voz opcional em fishReferenceId; sem ela, a voz default.",
|
|
98
|
+
voices: [
|
|
99
|
+
{
|
|
100
|
+
fishReferenceId: null,
|
|
101
|
+
name: "Voz default do modelo",
|
|
102
|
+
use: "o caminho normal: escreve o texto no idioma que quer e manda",
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
88
106
|
};
|
|
89
107
|
export async function helen(args) {
|
|
90
108
|
if (args.action === "list_presets") {
|
|
@@ -98,9 +116,13 @@ export async function helen(args) {
|
|
|
98
116
|
const modelId = args.modelId ??
|
|
99
117
|
(provider === "elevenlabs"
|
|
100
118
|
? "eleven_v3"
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
119
|
+
: provider === "fish"
|
|
120
|
+
// O motor real do Fish é o header `model` do servidor. Este id viaja só
|
|
121
|
+
// pra log e pra chave de cache não misturar os motores.
|
|
122
|
+
? "s2.1-pro-free"
|
|
123
|
+
// 3.1 Flash é o único TTS do Google que gera nas contas free da casa
|
|
124
|
+
// (o 2.5 responde 200 sem áudio nelas e só sai na conta central).
|
|
125
|
+
: "gemini-3.1-flash-tts-preview");
|
|
104
126
|
if (provider === "elevenlabs" && !args.voiceId) {
|
|
105
127
|
throw new Error("provider=elevenlabs exige voiceId. Use action=list_presets pra ver opções.");
|
|
106
128
|
}
|
|
@@ -112,6 +134,8 @@ export async function helen(args) {
|
|
|
112
134
|
modelId,
|
|
113
135
|
voiceId: args.voiceId,
|
|
114
136
|
googleVoiceName: args.googleVoiceName,
|
|
137
|
+
fishReferenceId: args.fishReferenceId,
|
|
138
|
+
language: args.language,
|
|
115
139
|
languageCode: args.languageCode,
|
|
116
140
|
stylePreamble: args.stylePreamble,
|
|
117
141
|
voiceSettings: args.voiceSettings,
|
package/dist/tools/pipeline.js
CHANGED
|
@@ -89,11 +89,33 @@ export const pipelineSchema = z.object({
|
|
|
89
89
|
.boolean()
|
|
90
90
|
.optional()
|
|
91
91
|
.describe("generate_carousel: se TRUE, a voz do Sintético do dono dirige o copy (amplificar). Default false = estilo do dono."),
|
|
92
|
+
model: z
|
|
93
|
+
.string()
|
|
94
|
+
.optional()
|
|
95
|
+
.describe("generate_carousel / generate_carousel_production: folha travada registrada da casa (ex: 'feed', 'reflexao'). A espinha de slides vem do servidor; a IA (ou seus beats) só escreve a prosa. Ausente = caminho editorial livre."),
|
|
96
|
+
beats: z
|
|
97
|
+
.union([
|
|
98
|
+
z.array(z.object({
|
|
99
|
+
n: z.number().describe("número do beat na espinha (1 a 9)"),
|
|
100
|
+
slots: z
|
|
101
|
+
.record(z.string())
|
|
102
|
+
.describe("só os slots de PROSA daquele beat (title/body/punch/tagline...), já contados e na voz"),
|
|
103
|
+
})),
|
|
104
|
+
// Defesa: cliente que serializa o array como string JSON (mesmo caso do
|
|
105
|
+
// arg payload). O handler normaliza.
|
|
106
|
+
z.string(),
|
|
107
|
+
])
|
|
108
|
+
.optional()
|
|
109
|
+
.describe("generate_carousel_production: copy PRONTO por beat da espinha, [{n, slots}]. Exige model. Com beats o Gemini de escrita NÃO roda e a rodada cobra só o picker de imagens (zero com autoPickImages=false). Use quando a skill do carrossel já escreveu e validou os blocos (o contador emite este JSON com --beats)."),
|
|
110
|
+
keyword: z
|
|
111
|
+
.string()
|
|
112
|
+
.optional()
|
|
113
|
+
.describe("generate_carousel_production (com beats): a palavra única do comment-to-DM, vira meta.keyword do pacote de publicação."),
|
|
92
114
|
// carrossel standalone (get/update/imagens)
|
|
93
115
|
carouselId: z
|
|
94
116
|
.string()
|
|
95
117
|
.optional()
|
|
96
|
-
.describe("carousels_standalone:_id — get_carousel/update_carousel/carousel_auto_images/carousel_generate_image. Vem de generate_carousel ou list_carousels."),
|
|
118
|
+
.describe("carousels_standalone:_id — get_carousel/update_carousel/carousel_auto_images/carousel_generate_image. Vem de generate_carousel ou list_carousels. No carousel_auto_images, alternativa: productionId (carrossel da pipeline)."),
|
|
97
119
|
slideId: z
|
|
98
120
|
.string()
|
|
99
121
|
.optional()
|
|
@@ -129,7 +151,7 @@ export const pipelineSchema = z.object({
|
|
|
129
151
|
productionId: z
|
|
130
152
|
.string()
|
|
131
153
|
.optional()
|
|
132
|
-
.describe("contentProductions:_id — get_production/update_production/finalize_production/remove_production/list_versions. Vem de create_production."),
|
|
154
|
+
.describe("contentProductions:_id — get_production/update_production/finalize_production/remove_production/list_versions/carousel_auto_images (carrossel da pipeline). Vem de create_production ou generate_carousel_production."),
|
|
133
155
|
publishableId: z
|
|
134
156
|
.string()
|
|
135
157
|
.optional()
|
|
@@ -191,6 +213,25 @@ function coercePayloadArg(raw) {
|
|
|
191
213
|
throw new Error('Arg "payload" veio como string mas não é JSON válido. Mande o objeto do payload.');
|
|
192
214
|
}
|
|
193
215
|
}
|
|
216
|
+
// Mesma defesa pro `beats` do generate_carousel_production: aceita o array já
|
|
217
|
+
// estruturado ou a string JSON dele, e valida o shape mínimo antes de mandar.
|
|
218
|
+
function coerceBeatsArg(raw) {
|
|
219
|
+
if (raw == null)
|
|
220
|
+
return undefined;
|
|
221
|
+
let val = raw;
|
|
222
|
+
if (typeof val === "string") {
|
|
223
|
+
try {
|
|
224
|
+
val = JSON.parse(val);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
throw new Error('Arg "beats" veio como string mas não é JSON válido. Mande o array [{n, slots}].');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (!Array.isArray(val) || val.some((b) => typeof b?.n !== "number" || !b?.slots)) {
|
|
231
|
+
throw new Error('Arg "beats" deve ser um array de { n: número do beat, slots: {slot: texto} }.');
|
|
232
|
+
}
|
|
233
|
+
return val;
|
|
234
|
+
}
|
|
194
235
|
export async function pipeline(args) {
|
|
195
236
|
const sessionToken = getSessionToken();
|
|
196
237
|
switch (args.action) {
|
|
@@ -382,6 +423,7 @@ export async function pipeline(args) {
|
|
|
382
423
|
...(articleId ? { publishedArticleId: articleId } : {}),
|
|
383
424
|
autoPickImages: args.autoPickImages,
|
|
384
425
|
useSintetico: args.useSintetico,
|
|
426
|
+
...(args.model ? { model: args.model } : {}),
|
|
385
427
|
});
|
|
386
428
|
}
|
|
387
429
|
case "generate_carousel_production": {
|
|
@@ -393,11 +435,20 @@ export async function pipeline(args) {
|
|
|
393
435
|
// Sinapses (reembolsa se falhar). Devolve productionId + url do editor.
|
|
394
436
|
// SÍNCRONA e pesada (Gemini + imagens): vale a REGRA DO TIMEOUT — se voltar
|
|
395
437
|
// Timeout, confira em get_production/list_sources antes de repetir.
|
|
438
|
+
//
|
|
439
|
+
// model trava a folha registrada; beats = copy pronto do agente (pula o
|
|
440
|
+
// Gemini de escrita, cobra só o picker). beats pode chegar serializado
|
|
441
|
+
// como string JSON (mesmo caso do payload): normaliza antes de mandar.
|
|
442
|
+
const beats = coerceBeatsArg(args.beats);
|
|
396
443
|
return await convexAction("carouselAutofill:mcpFillCarouselFromArticle", {
|
|
397
444
|
sessionToken,
|
|
398
445
|
sourceId: need(args.sourceId, "sourceId"),
|
|
399
446
|
autoPickImages: args.autoPickImages,
|
|
400
447
|
useSintetico: args.useSintetico,
|
|
448
|
+
...(args.model ? { model: args.model } : {}),
|
|
449
|
+
...(beats ? { beats } : {}),
|
|
450
|
+
...(args.caption ? { caption: args.caption } : {}),
|
|
451
|
+
...(args.keyword ? { keyword: args.keyword } : {}),
|
|
401
452
|
});
|
|
402
453
|
}
|
|
403
454
|
case "list_carousels":
|
|
@@ -420,18 +471,24 @@ export async function pipeline(args) {
|
|
|
420
471
|
payload: coercePayloadArg(need(args.payload, "payload")),
|
|
421
472
|
...(args.title ? { title: args.title } : {}),
|
|
422
473
|
});
|
|
423
|
-
case "carousel_auto_images":
|
|
474
|
+
case "carousel_auto_images": {
|
|
424
475
|
// IA escolhe imagens do banco pros slides de foto sem imagem (60 Sinapses).
|
|
476
|
+
// Aceita carouselId (standalone) OU productionId (carrossel da pipeline).
|
|
425
477
|
// makeVisual dá ritmo a carrossel texto-pesado; generateMissing gera as que
|
|
426
478
|
// o banco não cobriu (custo por imagem). SÍNCRONA e pesada com
|
|
427
479
|
// generateMissing: vale a REGRA DO TIMEOUT.
|
|
480
|
+
if (!args.carouselId && !args.productionId) {
|
|
481
|
+
throw new Error("carousel_auto_images: passe carouselId (standalone) OU productionId (carrossel da pipeline).");
|
|
482
|
+
}
|
|
428
483
|
return await convexAction("carouselAutofill:mcpCarouselAutoImages", {
|
|
429
484
|
sessionToken,
|
|
430
|
-
carouselId:
|
|
485
|
+
...(args.carouselId ? { carouselId: args.carouselId } : {}),
|
|
486
|
+
...(!args.carouselId && args.productionId ? { productionId: args.productionId } : {}),
|
|
431
487
|
force: args.force,
|
|
432
488
|
makeVisual: args.makeVisual,
|
|
433
489
|
generateMissing: args.generateMissing,
|
|
434
490
|
});
|
|
491
|
+
}
|
|
435
492
|
case "carousel_generate_image":
|
|
436
493
|
// Gera imagem NOVA pra UM slide (nanoBanana, ~450 Sinapses) e salva no
|
|
437
494
|
// carrossel. SÍNCRONA (~20-60s): vale a REGRA DO TIMEOUT.
|
package/dist/tools/stockAudio.js
CHANGED
|
@@ -67,7 +67,7 @@ export const stockAudioSchema = z.object({
|
|
|
67
67
|
provider: z
|
|
68
68
|
.enum(["mirelo", "elevenlabs"])
|
|
69
69
|
.optional()
|
|
70
|
-
.describe("action=generate: 'mirelo' (padrão,
|
|
70
|
+
.describe("action=generate: 'mirelo' (padrão, 35 Sinapses/s, mín 70) | 'elevenlabs' (premium, 60/s, mín 120)."),
|
|
71
71
|
promptInfluence: z
|
|
72
72
|
.number()
|
|
73
73
|
.min(0)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.43.
|
|
3
|
+
"version": "1.43.5",
|
|
4
4
|
"description": "MCP server pra operar o Sapiens Sintéticos (sapiensinteticos.com) pelo Claude Code: gerar imagem, escrever artigo, voz, música e mais, na sua conta. Login pelo código de sapiensinteticos.com/conectar-claude.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|