sapiens-mcp 1.86.0 → 1.87.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/dist/registry.js +9 -2
- package/dist/skills.js +33 -1
- package/dist/tools/distribution.js +41 -5
- package/dist/tools/meta.js +3 -25
- package/dist/tools/pipeline.js +5 -3
- package/dist/tools/publicar.js +102 -0
- package/dist/tools/video.js +14 -6
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -38,6 +38,7 @@ import { publicidade, publicidadeSchema } from "./tools/publicidade.js";
|
|
|
38
38
|
import { reference, referenceSchema } from "./tools/reference.js";
|
|
39
39
|
import { trilhas, trilhasSchema } from "./tools/trilhas.js";
|
|
40
40
|
import { semana, semanaSchema } from "./tools/semana.js";
|
|
41
|
+
import { publicar, publicarSchema } from "./tools/publicar.js";
|
|
41
42
|
import { distribution, distributionSchema } from "./tools/distribution.js";
|
|
42
43
|
import { shareDrop, shareDropSchema } from "./tools/shareDrop.js";
|
|
43
44
|
import { skill, skillSchema } from "./tools/skill.js";
|
|
@@ -224,10 +225,15 @@ export const TOOLS = {
|
|
|
224
225
|
handler: trilhas,
|
|
225
226
|
},
|
|
226
227
|
sapiens_distribution: {
|
|
227
|
-
description: "Despachar peças (Distribution Workflow) — a peça pronta entra na FILA com canal, copy e a aba de quem ela é. ADMIN-ONLY: despacho depende de rede conectada e hoje só a casa tem. NADA aqui posta em rede nenhuma; quem despacha é a tela em /experimentos/distribution-workflow, que é onde a conta conectada mora. A ABA (`voice`) responde de quem é a peça: sapiens (a casa), helen-ailith, borderless, ou o slug de um personagem seu — slug livre, então personagem novo ganha aba sozinho na primeira peça dele, sem deploy. Em queue, aba ausente = o servidor deriva do personagem da peça e cai em sapiens quando não há. Sub-actions: queue (põe na fila: title e channel obrigatórios, mais copy/hashtags/assetUrl/notes; replyText é o comentário que sai junto do post, onde vai o link, e só o X (resposta no fio) e a Página do LinkedIn (primeiro comentário) publicam, o resto recusa; num canal do Instagram, format instagram_story faz a peça sair como STORY: uma mídia só, sem legenda nem link, some em 24h). Em queue, DOIS campos que parecem opcionais e não são: `lang` diz em que língua a copy já está, e sem ele canal de rede internacional reescreve a sua copy sozinho, dois segundos depois, na voz da casa; `assetPageAssetId` é o imageId da obra da casa, e sem ele a peça só encontra a obra se a assetUrl bater letra a letra, então versão web de um master nasce órfã de ficha, list (o que está na fila, filtrável por status e por aba), voices (as abas que existem hoje com a contagem de cada uma), status (move a peça de lane: fila, agendado, postado, descartado; postado aceita postUrl e fecha o rastro, agendado aceita scheduledFor em ms), sign (liga ou desliga a ASSINATURA da peça, imagem e vídeo do CDN da casa, com o carimbo da LINHAGEM de quem assina: sint.fyi/<endereço dela> no canto e o fecho de 2s no vídeo, ou a marca própria dela sem nada da casa; itemId, e signed com true de default; o carimbo da casa é recusado em peça +18 e praça adulta, a marca própria passa; o carimbo leva uns 30s e até lá a peça não sai; em queue, signed:true já enfileira assinada), bio (lê ou troca a BIO de uma conta da casa no Bluesky, channel bluesky ou bluesky-2 a bluesky-5: sem texto só lê; bioLine acrescenta uma linha no fim sem mexer no resto e não repete linha que já está lá; bio reescreve a inteira; teto de 256; ESTA sub-action muda o perfil público na hora, e bio não aceita hiperlink, o endereço aparece escrito), lineages (o CADASTRO das linhagens, o mesmo da aba Teia: de cada personagem, produto e da casa, a mãe no Bluesky onde a peça nasce, as contas próprias, as galerias que a mãe alimenta sozinha, as fichas e o post do dia, mais as regras que a teia desdobra e as vagas de conta ainda sem dona), lineage-new (nasce uma linhagem: nome obrigatório, grupo, artigo, lang; nasce sem mãe, então nada viaja sozinho até o lineage-save dar a mãe), lineage-save (slug e só o que muda: mae, contas rede->canal, galerias, fichaIds, rotina, contaNaCasa, assinatura {estilo casa|propria|nenhuma, marca, padrao}; o servidor recusa conta que já é de outra linhagem e canal de outra rede, e a vaga assumida ganha o nome da linhagem), lineage-archive (slug + arquivada), tree (a ÁRVORE DE CONTAS, o formulário de quem existe onde: linhagem × rede, com o email, o @, o canal e o estado de cada conta, ligada, desligada, fora, falta ou dispensa, mais o passo pra ligar cada rede; slug filtra uma linhagem), tree-mark (slug + celulas [{rede, handle, canal, dispensada}]: registra o email ou o @ que existe lá fora, associa a conta da casa ou dispensa rede opcional, a linhagem inteira de uma vez e tudo ou nada; X, Instagram, Bluesky, email e Telegram são obrigatórias e não se dispensam), garimpo (o ACERVO em famílias pra escolher o que vai pra fila: só as candidatas saem, a versão velha de um corte ou upscale vem marcada como substituída, as irmãs da mesma ideia vêm agrupadas pra escolha no olho, o painel cortado vem em recortes (o original e os quadros em ordem, que só saem juntos em carrossel), e cada família diz por onde já saiu; paraCanal tira o que já foi pro canal pedido, soResumo conta sem listar, página por cursor em antesDe; o passo a passo é a skill distribuir). Sem custo em Sinapses: isto organiza, não gera. A copy segue a voz de QUEM ASSINA a peça, que não é sempre a voz da casa: peça da Helen fala como a Helen. E a peça sai pela CONTA de quem assina ela: conta extra da mesma rede é um canal próprio (bluesky-2 é outra conta no Bluesky, instagram-pro outra no Instagram), então case o canal com a aba antes de despachar.",
|
|
228
|
+
description: "Despachar peças (Distribution Workflow) — a peça pronta entra na FILA com canal, copy e a aba de quem ela é. ADMIN-ONLY: despacho depende de rede conectada e hoje só a casa tem. NADA aqui posta em rede nenhuma; quem despacha é a tela em /experimentos/distribution-workflow, que é onde a conta conectada mora. A ABA (`voice`) responde de quem é a peça: sapiens (a casa), helen-ailith, borderless, ou o slug de um personagem seu — slug livre, então personagem novo ganha aba sozinho na primeira peça dele, sem deploy. Em queue, aba ausente = o servidor deriva do personagem da peça e cai em sapiens quando não há. Sub-actions: queue (põe na fila: title e channel obrigatórios, mais copy/hashtags/assetUrl/notes; replyText é o comentário que sai junto do post, onde vai o link, e só o X (resposta no fio) e a Página do LinkedIn (primeiro comentário) publicam, o resto recusa; num canal do Instagram, format instagram_story faz a peça sair como STORY: uma mídia só, sem legenda nem link, some em 24h). Em queue, DOIS campos que parecem opcionais e não são: `lang` diz em que língua a copy já está, e sem ele canal de rede internacional reescreve a sua copy sozinho, dois segundos depois, na voz da casa; `assetPageAssetId` é o imageId da obra da casa, e sem ele a peça só encontra a obra se a assetUrl bater letra a letra, então versão web de um master nasce órfã de ficha, list (o que está na fila, filtrável por status e por aba, com copy, hashtags e notas de cada peça; fila maior que o limit se lê inteira pelo cursor antesDe=proximoCursor), voices (as abas que existem hoje com a contagem de cada uma), status (move a peça de lane: fila, agendado, postado, descartado; postado aceita postUrl e fecha o rastro, agendado aceita scheduledFor em ms), edit (reescreve a peça da FILA sem tirar ela do lugar: itemId e só o que muda, copy, title, publicTitle, hashtags, notes, lang, replyText, assetUrl/assetKind ou assets; é o gesto pra corrigir legenda, nunca descartar e enfileirar de novo; texto de peça postada o servidor recusa), sign (liga ou desliga a ASSINATURA da peça, imagem e vídeo do CDN da casa, com o carimbo da LINHAGEM de quem assina: sint.fyi/<endereço dela> no canto e o fecho de 2s no vídeo, ou a marca própria dela sem nada da casa; itemId, e signed com true de default; o carimbo da casa é recusado em peça +18 e praça adulta, a marca própria passa; o carimbo leva uns 30s e até lá a peça não sai; em queue, signed:true já enfileira assinada), bio (lê ou troca a BIO de uma conta da casa no Bluesky, channel bluesky ou bluesky-2 a bluesky-5: sem texto só lê; bioLine acrescenta uma linha no fim sem mexer no resto e não repete linha que já está lá; bio reescreve a inteira; teto de 256; ESTA sub-action muda o perfil público na hora, e bio não aceita hiperlink, o endereço aparece escrito), lineages (o CADASTRO das linhagens, o mesmo da aba Teia: de cada personagem, produto e da casa, a mãe no Bluesky onde a peça nasce, as contas próprias, as galerias que a mãe alimenta sozinha, as fichas e o post do dia, mais as regras que a teia desdobra e as vagas de conta ainda sem dona), lineage-new (nasce uma linhagem: nome obrigatório, grupo, artigo, lang; nasce sem mãe, então nada viaja sozinho até o lineage-save dar a mãe), lineage-save (slug e só o que muda: mae, contas rede->canal, galerias, fichaIds, rotina, contaNaCasa, assinatura {estilo casa|propria|nenhuma, marca, padrao}; o servidor recusa conta que já é de outra linhagem e canal de outra rede, e a vaga assumida ganha o nome da linhagem), lineage-archive (slug + arquivada), tree (a ÁRVORE DE CONTAS, o formulário de quem existe onde: linhagem × rede, com o email, o @, o canal e o estado de cada conta, ligada, desligada, fora, falta ou dispensa, mais o passo pra ligar cada rede; slug filtra uma linhagem), tree-mark (slug + celulas [{rede, handle, canal, dispensada}]: registra o email ou o @ que existe lá fora, associa a conta da casa ou dispensa rede opcional, a linhagem inteira de uma vez e tudo ou nada; X, Instagram, Bluesky, email e Telegram são obrigatórias e não se dispensam), garimpo (o ACERVO em famílias pra escolher o que vai pra fila: só as candidatas saem, a versão velha de um corte ou upscale vem marcada como substituída, as irmãs da mesma ideia vêm agrupadas pra escolha no olho, o painel cortado vem em recortes (o original e os quadros em ordem, que só saem juntos em carrossel), e cada família diz por onde já saiu; paraCanal tira o que já foi pro canal pedido, soResumo conta sem listar, página por cursor em antesDe; o passo a passo é a skill distribuir). Sem custo em Sinapses: isto organiza, não gera. A copy segue a voz de QUEM ASSINA a peça, que não é sempre a voz da casa: peça da Helen fala como a Helen. E a peça sai pela CONTA de quem assina ela: conta extra da mesma rede é um canal próprio (bluesky-2 é outra conta no Bluesky, instagram-pro outra no Instagram), então case o canal com a aba antes de despachar.",
|
|
228
229
|
schema: distributionSchema,
|
|
229
230
|
handler: distribution,
|
|
230
231
|
},
|
|
232
|
+
sapiens_publicar: {
|
|
233
|
+
description: "Publicar uma peça SUA nas SUAS redes (TikTok, Instagram, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Bluesky), pelo Distribution da pessoa (assinatura ou convite). Identidade SEMPRE pelo sessionToken. Sub-actions: 'painel' (as redes com conectada ou não, o @, o limite de texto e a régua de cada praça; com handle, a peça: onde ela já está por rede, com estado e link, e a sugestão de onde mandar, as que ficam de fora com o motivo e as que valeria conectar), 'rascunho' (handle + rede + legenda: guarda a legenda de UMA rede pra peça, vazia apaga; acima do limite da rede volta erro com o número), 'publicar' (handle + redes, agora ou agendarPara ISO com fuso; a legenda vai em BLOCOS: text é o corpo, cta a chamada, hashtags sem #, e cada rede leva o que cabe no limite dela, saindo primeiro as hashtags, depois a chamada, e o corpo corta em fim de frase; legendas {rede: texto} passa por cima dos blocos naquela rede; o retorno diz em `adaptadas` quais redes receberam menos do que foi escrito), 'lista' (o que já saiu: os envios recentes com o estado de cada rede), 'conferir' (postId: pergunta o que cada rede fez e grava o link), 'cancelar' (postId: cancela agendado que ainda não saiu). Fluxo: painel com handle, escolhe pela sugestão, publicar, conferir. Só peça da própria pessoa, e só rede conectada (conectar é na tela /dashboard/distribution). Sem custo em Sinapses: o teto é o de publicações por ciclo do plano. Publicar POSTA DE VERDADE na conta da pessoa: confirme redes e legenda com ela antes. A fila da casa é outra tool (sapiens_distribution, admin). Passo a passo: skill publicar.",
|
|
234
|
+
schema: publicarSchema,
|
|
235
|
+
handler: publicar,
|
|
236
|
+
},
|
|
231
237
|
sapiens_semana: {
|
|
232
238
|
description: "As Atividades da SUA semana na casa: o que você produziu e quanto XP isso rendeu. Identidade SEMPRE pelo sessionToken. Sub-actions: 'get' (quais atividades você fez nesta semana, quantas peças em cada, o XP já pago, quanto a Casa Cheia renderia no fecho, quanto vale abrir mais uma atividade e QUAIS abrir agora, a sequência de semanas seguidas com o recorde, as semanas anteriores com o que cada uma rendeu, e uma leitura pronta da semana pra você dizer em voz alta), 'fechar' (fecha as semanas pendentes e credita a Casa Cheia de cada uma). Como a régua funciona: cada peça pronta anda o contador da atividade e paga em degraus (1a, 3a, 7a, 15a, 30a peça da semana, com retorno decrescente); no fecho, a LARGURA paga à parte, 2 atividades valem 20 XP, 5 valem 200, 8 valem 560, então atividades diferentes rendem mais que repetir a mesma. Esta tool PAGA XP, não cobra Sinapses. Idempotente: chamar 'fechar' duas vezes não credita duas vezes.",
|
|
233
239
|
schema: semanaSchema,
|
|
@@ -261,7 +267,7 @@ O passo a passo travado de cada fluxo mora na tool sapiens_skill, servida por es
|
|
|
261
267
|
- sapiens_skill action=list -> o índice (slug + quando usar cada uma).
|
|
262
268
|
- sapiens_skill action=get name=<slug> -> a skill inteira.
|
|
263
269
|
Slugs: ${skillMenuLine()}
|
|
264
|
-
Puxe a skill ANTES de: gerar música ou efeito sonoro (musica), escolher modelo de vídeo (video), gerar imagem (imagem), criar personagem ou prompt de Midjourney (personagem), criar na identidade do usuário (studio), postar no Fórum ou no chat (forum-comunidade), redigir qualquer texto publicável (voz-da-casa), incorporar o Sintético (companhia), missão de Desafio (trilhas), montar currículo (curriculo), guardar obra ou ferramenta no acervo (repertorio), gerar em motor de fora com crédito próprio e trazer a peça pro acervo (pontes). Perdido no começo: primeiros-passos.
|
|
270
|
+
Puxe a skill ANTES de: gerar música ou efeito sonoro (musica), escolher modelo de vídeo (video), gerar imagem (imagem), criar personagem ou prompt de Midjourney (personagem), criar na identidade do usuário (studio), postar no Fórum ou no chat (forum-comunidade), redigir qualquer texto publicável (voz-da-casa), incorporar o Sintético (companhia), missão de Desafio (trilhas), montar currículo (curriculo), guardar obra ou ferramenta no acervo (repertorio), gerar em motor de fora com crédito próprio e trazer a peça pro acervo (pontes), publicar peça nas redes da pessoa (publicar). Perdido no começo: primeiros-passos.
|
|
265
271
|
Cliente que lê resources MCP acha o MESMO conteúdo em skill://sapiens/<slug>/SKILL.md.
|
|
266
272
|
|
|
267
273
|
REGRA DE OURO:
|
|
@@ -330,6 +336,7 @@ const TOOL_TITLES = {
|
|
|
330
336
|
sapiens_trilhas: "Trilhas & Desafios",
|
|
331
337
|
sapiens_distribution: "Despachar peças",
|
|
332
338
|
sapiens_semana: "Minha Semana",
|
|
339
|
+
sapiens_publicar: "Publicar nas minhas redes",
|
|
333
340
|
sapiens_instagram: "Auto-DM Instagram",
|
|
334
341
|
sapiens_share: "Share Drop",
|
|
335
342
|
sapiens_resume: "Currículo PRO",
|
package/dist/skills.js
CHANGED
|
@@ -242,7 +242,7 @@ Duração é o que pesa aqui, não o modelo: um take de 30s em 720p passa de 40
|
|
|
242
242
|
- \`sapiens-video-wan-3\`: WAN 3.0, texto ou imagem, som nativo, frame final e 1080p, 5 a 10s.
|
|
243
243
|
- \`sapiens-video-kling-motion\`: passa o movimento de um vídeo pra uma imagem. Precisa de pessoa com tronco visível na imagem E no vídeo.
|
|
244
244
|
- \`sapiens-video-shot-mimic\`: recria o plano, a câmera e os cortes de um vídeo de referência como cena nova.
|
|
245
|
-
- \`sapiens-video-omni-11\`: Gemini Omni 1.1, texto ou imagem vira clipe de 4, 6, 8 ou 10s (sem \`durationSec\`, 10s) em 720p com áudio nativo. O preço é por segundo: o take de 4s custa 40% do de 10s. Aceita até 3 imagens suas (frame inicial, frame final ou referência de personagem e estilo); vídeo de referência não, e \`resolution\` segue ignorada. O truque: \`editOfImageId\` aponta um vídeo Omni seu e o prompt vira instrução de edição sobre a MESMA cena (troca item ou personagem, preserva câmera e ambiente). É o caminho pra variações com continuidade: gera a base uma vez, edita N vezes. Cada edição debita como geração nova.
|
|
245
|
+
- \`sapiens-video-omni-11\`: Gemini Omni 1.1, texto ou imagem vira clipe de 4, 6, 8 ou 10s (sem \`durationSec\`, 10s) em 720p com áudio nativo. O preço é por segundo: o take de 4s custa 40% do de 10s. Aceita até 3 imagens suas (frame inicial, frame final ou referência de personagem e estilo); vídeo de referência não, e \`resolution\` segue ignorada. O truque: \`editOfImageId\` aponta um vídeo Omni seu e o prompt vira instrução de edição sobre a MESMA cena (troca item ou personagem, preserva câmera e ambiente). É o caminho pra variações com continuidade: gera a base uma vez, edita N vezes. Cada edição debita como geração nova. Pra ir ADIANTE no tempo é \`action=extend\` (o pedaço seguinte, cobrado pela duração dele): o arquivo de cada parte já traz as anteriores na frente, então a última parte pronta é o filme inteiro. Não emende as partes, a abertura repete; \`action=chain\` aponta o \`filmeInteiro\`.
|
|
246
246
|
- \`sapiens-video-omni\`: o Gemini Omni 1.0, a versão preview. Mesmo preço e mesmo repertório do 1.1, mantida só pra comparar as duas. Nasce desligada (não aparece na lista de motores), então peça o 1.1.
|
|
247
247
|
- \`sapiens-video-lite\` / \`-fast\` / \`-quality\`: Veo 3.1, 4, 6 ou 8s (sem \`durationSec\`, 8s), preço por segundo. Com imagem de referência ou frame final o Google só faz 8s: pedir menos com elas recusa antes de gastar.
|
|
248
248
|
|
|
@@ -273,6 +273,8 @@ Dá pra somar 1 vídeo de movimento via \`referenceVideoUrls\` (até 15s, host d
|
|
|
273
273
|
|
|
274
274
|
Frame inicial e final: \`startImageId\`/\`endImageId\` (galeria) ou \`startImageUrl\`/\`endImageUrl\`. Arquivo local (\`startImagePath\`) só funciona no MCP instalado via stdio, nunca no remoto. Suporte a frame final varia por modelo.
|
|
275
275
|
|
|
276
|
+
Frame de borda e referência são caminhos EXCLUSIVOS no Seedance 2.0/Fast/Mini/2.5 e no H3: ou o take nasce do frame (\`startImage*\`/\`endImage*\`), ou das referências (\`referenceImage*\`/\`referenceVideoUrls\`), nunca dos dois. No Seedance a mistura é recusada antes de cobrar; no H3 a referência troca o endpoint e o frame inicial fica de fora. Quer a pessoa da foto no take? Mande a foto como referência e descreva o primeiro quadro no prompt; quer o quadro exato? Só o frame inicial.
|
|
277
|
+
|
|
276
278
|
## É assíncrono
|
|
277
279
|
|
|
278
280
|
\`create\` cria o row, debita e volta NA HORA com \`{imageId, status:'rendering'}\`. Acompanhe com \`action=status imageId=<id>\` até 'completed' (traz a url) ou 'error'/'blocked'.
|
|
@@ -820,6 +822,36 @@ O que a peça vira: NATIVA, PRIVADA, publicável depois por \`action=publish\` (
|
|
|
820
822
|
- Motor exclusivo da casa: Helen TTS, Musicator, os templates de take (\`templateSlug\`), Sombras, o carimbo assinado. Isso só existe em Sinapse.
|
|
821
823
|
- A pessoa tem Sinapse e o take é curto: \`sapiens_video\` é um comando só, com a régua de qualidade da casa. Menos atrito vence quando o custo cabe.
|
|
822
824
|
- Peça achada pronta na internet, sem direção dela: é \`action=upload\` (privada pra sempre), não ingest.`,
|
|
825
|
+
},
|
|
826
|
+
{
|
|
827
|
+
name: "publicar",
|
|
828
|
+
title: "Publicar nas redes da pessoa",
|
|
829
|
+
description: "A peça da pessoa saindo pelas contas dela: ler o painel, escolher as redes pela sugestão, escrever a legenda em blocos, confirmar e conferir. Puxe ANTES de sapiens_publicar.",
|
|
830
|
+
body: `## O que é
|
|
831
|
+
|
|
832
|
+
A pessoa liga as redes dela (TikTok, Instagram, YouTube, LinkedIn, Facebook, X, Threads, Pinterest, Bluesky) na tela do Distribution, e daqui a peça dela sai por essas contas, com o nome dela. Só peça DELA, e só rede que ela já ligou. Conectar rede nova é sempre na tela: \`/dashboard/distribution\`.
|
|
833
|
+
|
|
834
|
+
## O fluxo
|
|
835
|
+
|
|
836
|
+
1. \`sapiens_publicar action=painel handle=<img_... ou vid_...>\`. Volta:
|
|
837
|
+
- \`redes\`: cada rede com \`conectada\`, o \`conta\` (@), o \`copyMax\` (limite de texto) e o \`fit\` (o que rende lá).
|
|
838
|
+
- \`peca.porRede\`: onde a peça já está, uma linha por rede, com \`status\` (rascunho, enviado, agendado, publicado, falhou, cancelado) e \`url\` quando saiu.
|
|
839
|
+
- \`sugestao\`: \`sugeridas\` (conectadas, na ordem do que rende, com o motivo), \`fora\` (as que não levam essa peça e por quê) e \`valeConectar\` (não ligadas onde a peça iria bem).
|
|
840
|
+
2. Proponha as redes pela \`sugestao\`, na voz da pessoa. Não repita rede onde a peça já saiu, a não ser que ela peça.
|
|
841
|
+
3. Escreva a legenda em BLOCOS: \`text\` é o corpo, \`cta\` a chamada, \`hashtags\` a lista sem #. Cada rede leva o que cabe no limite dela: onde aperta, saem primeiro as hashtags, depois a chamada, e o corpo corta em fim de frase. Rede que precisa de texto próprio (o Threads curto, o LinkedIn mais longo) vai em \`legendas: {threads: "..."}\`. Texto publicável segue a skill voz-da-casa só se a peça for da casa; peça da pessoa fala na voz DELA.
|
|
842
|
+
4. **Mostre redes, legenda e horário e espere o ok.** Publicar posta de verdade na conta dela.
|
|
843
|
+
5. \`action=publicar\` com \`handle\`, \`redes\`, os blocos e, se for agendar, \`agendarPara\` em ISO com fuso (mínimo 5 minutos à frente, até um ano). O retorno traz \`adaptadas\`: diga quais redes receberam menos do que foi escrito.
|
|
844
|
+
6. Depois de uns minutos, \`action=lista\` e \`action=conferir postId=...\` pra ver o que cada rede fez e pegar o link.
|
|
845
|
+
|
|
846
|
+
## Rascunho
|
|
847
|
+
|
|
848
|
+
\`action=rascunho handle rede legenda\` guarda a legenda de uma rede sem mandar. Ela aparece no painel da tela quando a pessoa abrir a peça, e o envio usa ela. Legenda vazia apaga. Acima do limite da rede volta erro com o número: corte você, não deixe pra rede.
|
|
849
|
+
|
|
850
|
+
## Limites
|
|
851
|
+
|
|
852
|
+
- Sem custo em Sinapses. O teto é o do plano do Distribution: publicações por ciclo, mais o limite diário de cada rede. O erro diz qual bateu.
|
|
853
|
+
- Imagem não vai pra TikTok nem YouTube (só vídeo). Áudio não sai por aqui.
|
|
854
|
+
- Agendado se cancela com \`action=cancelar postId=...\` até 2 minutos antes da hora.`,
|
|
823
855
|
},
|
|
824
856
|
{
|
|
825
857
|
name: "carrossel",
|
|
@@ -23,6 +23,9 @@ import { convexQuery, convexMutation, convexAction, describeConvexError, getSess
|
|
|
23
23
|
* - list: o que está na fila, filtrável por status e por aba.
|
|
24
24
|
* - voices: as abas que existem hoje, com a contagem de cada uma.
|
|
25
25
|
* - status: move a peça de lane (fila, agendado, postado, descartado).
|
|
26
|
+
* - edit: reescreve a peça que está na fila (copy, título, hashtags,
|
|
27
|
+
* notas, mídia, língua, comentário). Só manda o que muda. Texto de peça
|
|
28
|
+
* POSTADA não se reescreve: o post na rede não muda junto.
|
|
26
29
|
* - sign: liga ou desliga a ASSINATURA da peça (imagem e vídeo). O carimbo
|
|
27
30
|
* é o da LINHAGEM de quem assina: sint.fyi/<endereço dela> (e o fecho de 2s
|
|
28
31
|
* no vídeo) ou a marca própria dela, sem nada da casa. A mesma chave da
|
|
@@ -149,6 +152,7 @@ export const distributionSchema = z.object({
|
|
|
149
152
|
"list",
|
|
150
153
|
"voices",
|
|
151
154
|
"status",
|
|
155
|
+
"edit",
|
|
152
156
|
"sign",
|
|
153
157
|
"bio",
|
|
154
158
|
"lineages",
|
|
@@ -170,12 +174,12 @@ export const distributionSchema = z.object({
|
|
|
170
174
|
copy: z
|
|
171
175
|
.string()
|
|
172
176
|
.optional()
|
|
173
|
-
.describe("queue: a legenda pronta pra colar, na voz de quem assina a peça. Sem em-dash."),
|
|
177
|
+
.describe("queue/edit: a legenda pronta pra colar, na voz de quem assina a peça. Sem em-dash. Em edit, troca a legenda inteira da peça da fila."),
|
|
174
178
|
replyText: z
|
|
175
179
|
.string()
|
|
176
180
|
.optional()
|
|
177
181
|
.describe("queue: o COMENTÁRIO que sai junto do post, pra onde vai o link (a copy fica sem ele e fecha apontando pro comentário). Só dois lugares publicam: o X pelo Buffer (x-buffer, x-buffer-2..4) e o X da API própria (x), como resposta no mesmo fio, teto 280; e a Página do LinkedIn pelo Buffer (linkedin-page, linkedin-page-2), como primeiro comentário, teto 1250. Threads (threads, threads-pro, threads-3..5), LinkedIn Perfil (linkedin) e o resto NÃO publicam comentário: lá o link mora na própria copy. O servidor recusa a peça com replyText num canal que não publica, e recusa o comentário acima do teto com a contagem; nada é cortado calado."),
|
|
178
|
-
hashtags: z.array(z.string()).optional().describe("queue: sem o #, o servidor limpa."),
|
|
182
|
+
hashtags: z.array(z.string()).optional().describe("queue/edit: sem o #, o servidor limpa. Em edit, a lista troca a inteira (vazia tira todas)."),
|
|
179
183
|
publicTitle: z
|
|
180
184
|
.string()
|
|
181
185
|
.max(100)
|
|
@@ -235,7 +239,7 @@ export const distributionSchema = z.object({
|
|
|
235
239
|
.number()
|
|
236
240
|
.optional()
|
|
237
241
|
.describe("queue, só canais fanvue e fanvue-dm: preço em CENTAVOS de dólar (pay-per-view). 1200 = $12. Piso de 300 na API deles, e peça paga EXIGE mídia. Ausente ou 0 = de graça pra quem já tem acesso."),
|
|
238
|
-
notes: z.string().optional().describe("queue: recado pra você mesmo na hora de postar."),
|
|
242
|
+
notes: z.string().optional().describe("queue/edit: recado pra você mesmo na hora de postar."),
|
|
239
243
|
format: z
|
|
240
244
|
.enum(["instagram_story"])
|
|
241
245
|
.optional()
|
|
@@ -244,7 +248,7 @@ export const distributionSchema = z.object({
|
|
|
244
248
|
.boolean()
|
|
245
249
|
.optional()
|
|
246
250
|
.describe("sign: true liga (o default), false desliga. queue: true enfileira a peça já com a assinatura ligada. A ASSINATURA carimba a IMAGEM e o VÍDEO da peça que moram no CDN da casa (o que sapiens_image/sapiens_video/sapiens_gallery devolvem), com o carimbo da LINHAGEM de quem assina a peça (a aba dela, ver lineages): no estilo casa, sint.fyi/<conta da linhagem na casa, ou o dono> no canto e, no vídeo, o fecho de 2 segundos no fim (o vídeo fica 2s mais longo); no estilo propria, só a marca da linhagem (ex: Velourie), sem nada da casa e sem fecho; no estilo nenhuma, o servidor recusa. O carimbo da casa é RECUSADO em peça +18 e em praça com teto adulto (fanvue, fanvue-dm, pornhub, civitai-red), porque sint.fyi é endereço da casa; a marca própria passa. A imagem do feed do Instagram é carimbada já recortada pra 4:5 a 1.91:1. O carimbo leva uns 30s na primeira vez (na hora quando a mídia já foi assinada antes), e enquanto ele não fica pronto a peça NÃO sai: o botão de postar da tela devolve o motivo."),
|
|
247
|
-
itemId: z.string().optional().describe("status/sign: o id da peça (vem do list ou do queue)."),
|
|
251
|
+
itemId: z.string().optional().describe("status/sign/edit: o id da peça (vem do list ou do queue)."),
|
|
248
252
|
status: z
|
|
249
253
|
.enum(["fila", "agendado", "postado", "descartado"])
|
|
250
254
|
.optional()
|
|
@@ -341,7 +345,7 @@ export const distributionSchema = z.object({
|
|
|
341
345
|
antesDe: z
|
|
342
346
|
.number()
|
|
343
347
|
.optional()
|
|
344
|
-
.describe("garimpo: o cursor, o `proximoCursor` da página anterior. Ausente = a página mais recente
|
|
348
|
+
.describe("garimpo e list: o cursor, o `proximoCursor` da página anterior. Ausente = a página mais recente. Em list, a fila com mais peças que o limit se lê inteira chamando de novo até proximoCursor voltar null."),
|
|
345
349
|
limite: z
|
|
346
350
|
.number()
|
|
347
351
|
.int()
|
|
@@ -469,7 +473,39 @@ export async function distribution(args) {
|
|
|
469
473
|
status: args.status,
|
|
470
474
|
voice: args.voice,
|
|
471
475
|
limit: args.limit,
|
|
476
|
+
antesDe: args.antesDe,
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
if (args.action === "edit") {
|
|
480
|
+
if (!args.itemId)
|
|
481
|
+
throw new Error("action=edit exige itemId (vem do list ou do queue).");
|
|
482
|
+
const campos = {
|
|
483
|
+
title: args.title,
|
|
484
|
+
publicTitle: args.publicTitle,
|
|
485
|
+
copy: args.copy,
|
|
486
|
+
replyText: args.replyText,
|
|
487
|
+
hashtags: args.hashtags,
|
|
488
|
+
notes: args.notes,
|
|
489
|
+
lang: args.lang,
|
|
490
|
+
assetUrl: args.assetUrl,
|
|
491
|
+
assetKind: args.assetKind,
|
|
492
|
+
assets: args.assets,
|
|
493
|
+
};
|
|
494
|
+
const mudou = Object.entries(campos).filter(([, v]) => v !== undefined);
|
|
495
|
+
if (mudou.length === 0) {
|
|
496
|
+
throw new Error("action=edit: mande ao menos um campo pra trocar (copy, title, publicTitle, hashtags, notes, lang, replyText, assetUrl/assetKind ou assets).");
|
|
497
|
+
}
|
|
498
|
+
await convexMutation("distributionMcp:mcpUpdateItem", {
|
|
499
|
+
sessionToken,
|
|
500
|
+
itemId: args.itemId,
|
|
501
|
+
...Object.fromEntries(mudou),
|
|
472
502
|
});
|
|
503
|
+
return {
|
|
504
|
+
ok: true,
|
|
505
|
+
itemId: args.itemId,
|
|
506
|
+
mudou: mudou.map(([k]) => k),
|
|
507
|
+
instruction: "A peça continua na mesma lane e na mesma posição da fila, só com o que mudou. Texto de peça já postada o servidor recusa: o post na rede não muda junto.",
|
|
508
|
+
};
|
|
473
509
|
}
|
|
474
510
|
if (args.action === "voices") {
|
|
475
511
|
return await convexQuery("distributionMcp:mcpVoices", { sessionToken });
|
package/dist/tools/meta.js
CHANGED
|
@@ -66,15 +66,6 @@ export const metaSchema = z.object({
|
|
|
66
66
|
});
|
|
67
67
|
const APP_URL = "https://sapiensinteticos.com";
|
|
68
68
|
const FORMAT_GUIDE = {
|
|
69
|
-
post_social: {
|
|
70
|
-
description: "Post de texto curto/médio pra rede social (genérico).",
|
|
71
|
-
payloadHint: {
|
|
72
|
-
text: "string PT principal",
|
|
73
|
-
textEn: "string EN (opcional)",
|
|
74
|
-
hashtags: ["string"],
|
|
75
|
-
cta: "string opcional",
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
69
|
carrossel_ig: {
|
|
79
70
|
description: "Carrossel do Instagram (o modelo Feed tem 9 slides). O editor renderiza por TEMPLATE: cada slide é { id, templateId, slots, image }. O servidor NORMALIZA todo payload de carrossel: o shape cru antigo ({ title, body, imageUrl } por slide, caption e hashtags no topo) vira slots, foto e meta, mas sai sem layout escolhido, e campo fora do shape some. NÃO monte o payload na mão: use sapiens_pipeline action=generate_carousel_production (sourceId), que cria a production E preenche pelo motor da casa, no shape certo, seguindo o artigo. Depois afine com get_carousel/update_carousel (mesmo shape). O membro opera o carrossel dele pela sapiens_carrossel.",
|
|
80
71
|
payloadHint: {
|
|
@@ -98,6 +89,9 @@ const FORMAT_GUIDE = {
|
|
|
98
89
|
],
|
|
99
90
|
},
|
|
100
91
|
},
|
|
92
|
+
// post_social, shorts_yt e video_yt saíram do guia em out/2026 (vídeo vive no
|
|
93
|
+
// gerador de vídeo; post de texto perdeu o lugar). Seguem aceitos só como
|
|
94
|
+
// tolerância de validação, ver pipeline.ts.
|
|
101
95
|
// tirinha saiu do guia em ago/2026: peça aposentada (format vive só como
|
|
102
96
|
// tolerância de validação pra productions antigas, ver pipeline.ts).
|
|
103
97
|
musica: {
|
|
@@ -109,22 +103,6 @@ const FORMAT_GUIDE = {
|
|
|
109
103
|
audioUrl: "string opcional",
|
|
110
104
|
},
|
|
111
105
|
},
|
|
112
|
-
shorts_yt: {
|
|
113
|
-
description: "Roteiro pra short vertical de 30-60s.",
|
|
114
|
-
payloadHint: {
|
|
115
|
-
title: "string",
|
|
116
|
-
script: "string roteiro completo",
|
|
117
|
-
scenes: [{ visual: "string", voiceover: "string", duration: "number" }],
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
|
-
video_yt: {
|
|
121
|
-
description: "Vídeo longer-form.",
|
|
122
|
-
payloadHint: {
|
|
123
|
-
title: "string",
|
|
124
|
-
script: "string roteiro completo",
|
|
125
|
-
scenes: [{ visual: "string", voiceover: "string", duration: "number" }],
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
106
|
mega_grafico: {
|
|
129
107
|
description: "Pôster blueprint denso multi-seção (estilo Pop Chart), texto fiel via gpt-image-2. Tem runner próprio: propose_mega_grafico_plan / run_mega_grafico_full.",
|
|
130
108
|
payloadHint: {
|
package/dist/tools/pipeline.js
CHANGED
|
@@ -7,9 +7,6 @@ import { need } from "../schema.js";
|
|
|
7
7
|
// ou remover formato, mexa nos dois lados.
|
|
8
8
|
const FORMATS = [
|
|
9
9
|
"carrossel_ig",
|
|
10
|
-
"post_social",
|
|
11
|
-
"shorts_yt",
|
|
12
|
-
"video_yt",
|
|
13
10
|
"musica",
|
|
14
11
|
"aula",
|
|
15
12
|
];
|
|
@@ -20,6 +17,8 @@ const FORMATS = [
|
|
|
20
17
|
// seguem de pé). mega_grafico saiu do picker web em ago/2026 mas o fluxo MCP
|
|
21
18
|
// segue vivo e ADVERTIDO (propose_mega_grafico_plan / run_mega_grafico_full
|
|
22
19
|
// criam a production no servidor; o formato aqui é só tolerância de validação).
|
|
20
|
+
// post_social, shorts_yt e video_yt saíram do picker em out/2026: vídeo vive no
|
|
21
|
+
// gerador de vídeo (uma tela só) e o post de texto perdeu o lugar.
|
|
23
22
|
const LEGACY_FORMATS = [
|
|
24
23
|
"post_linkedin",
|
|
25
24
|
"post_twitter",
|
|
@@ -27,6 +26,9 @@ const LEGACY_FORMATS = [
|
|
|
27
26
|
"cena_visual",
|
|
28
27
|
"tirinha",
|
|
29
28
|
"mega_grafico",
|
|
29
|
+
"post_social",
|
|
30
|
+
"shorts_yt",
|
|
31
|
+
"video_yt",
|
|
30
32
|
];
|
|
31
33
|
const ACCEPTED_FORMATS = [...FORMATS, ...LEGACY_FORMATS];
|
|
32
34
|
const STATUSES = ["draft", "ready", "finalized"];
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexAction, getSessionToken } from "../convexClient.js";
|
|
3
|
+
import { need } from "../schema.js";
|
|
4
|
+
/**
|
|
5
|
+
* sapiens_publicar: a peça do MEMBRO saindo pelas redes DELE.
|
|
6
|
+
*
|
|
7
|
+
* O mesmo painel lateral da tela (Publicar nas minhas redes), lido por quem não
|
|
8
|
+
* tem tela: as redes com o limite de texto e a régua de cada praça, onde a peça
|
|
9
|
+
* já está, pra onde vale mandar, a legenda de cada rede e o envio. Irmã da
|
|
10
|
+
* sapiens_distribution, que é a fila da CASA (admin); aqui é a conta da pessoa,
|
|
11
|
+
* pelo Distribution dela (assinatura ou convite).
|
|
12
|
+
*
|
|
13
|
+
* Sub-actions:
|
|
14
|
+
* - painel: as redes (conectada ou não, @, limite, régua). Com `handle`,
|
|
15
|
+
* a peça: onde já está, por rede, e a sugestão de onde mandar.
|
|
16
|
+
* - rascunho: guarda a legenda de UMA rede pra peça (vazia apaga).
|
|
17
|
+
* - publicar: manda agora ou agenda. Legenda em blocos: text (corpo), cta,
|
|
18
|
+
* hashtags. Cada rede leva o que cabe no limite dela.
|
|
19
|
+
* - lista: o que já saiu (os envios recentes, com o estado por rede).
|
|
20
|
+
* - conferir: pergunta ao fornecedor o que cada rede fez com um envio.
|
|
21
|
+
* - cancelar: cancela um envio agendado que ainda não saiu.
|
|
22
|
+
*
|
|
23
|
+
* Identidade SEMPRE pelo sessionToken. Sem custo em Sinapses: o teto é o do
|
|
24
|
+
* plano do Distribution (publicações por ciclo), e o servidor confere tudo de
|
|
25
|
+
* novo (dono da peça, rede, limite, tipo de mídia).
|
|
26
|
+
*/
|
|
27
|
+
export const publicarSchema = z.object({
|
|
28
|
+
action: z.enum(["painel", "rascunho", "publicar", "lista", "conferir", "cancelar"]),
|
|
29
|
+
handle: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("A peça (img_..., vid_...). Obrigatório em rascunho e publicar; em painel traz a peça junto."),
|
|
33
|
+
rede: z.string().optional().describe("rascunho: a rede (id do painel: instagram, tiktok, threads...)."),
|
|
34
|
+
legenda: z.string().optional().describe("rascunho: a legenda daquela rede. Vazia apaga o rascunho."),
|
|
35
|
+
redes: z.array(z.string()).optional().describe("publicar: as redes (ids do painel), só as conectadas."),
|
|
36
|
+
text: z.string().optional().describe("publicar: o CORPO da legenda. Ausente usa o título da peça."),
|
|
37
|
+
cta: z.string().optional().describe("publicar: a chamada, em bloco à parte. Sai antes do corpo quando não cabe."),
|
|
38
|
+
hashtags: z
|
|
39
|
+
.array(z.string())
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("publicar: as hashtags, sem #. São as primeiras a sair onde o limite aperta."),
|
|
42
|
+
legendas: z
|
|
43
|
+
.record(z.string(), z.string())
|
|
44
|
+
.optional()
|
|
45
|
+
.describe("publicar: legenda própria por rede ({threads: '...'}), passa por cima dos blocos naquela rede."),
|
|
46
|
+
agendarPara: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("publicar: data e hora ISO 8601 COM fuso (2026-10-08T19:00:00-03:00). Ausente = agora. Mínimo 5 min à frente."),
|
|
50
|
+
postId: z.string().optional().describe("conferir/cancelar: o id do envio, vindo da lista."),
|
|
51
|
+
});
|
|
52
|
+
export async function publicar(args) {
|
|
53
|
+
const sessionToken = getSessionToken();
|
|
54
|
+
switch (args.action) {
|
|
55
|
+
case "painel":
|
|
56
|
+
return await convexAction("uploadPost:mcpPainel", {
|
|
57
|
+
sessionToken,
|
|
58
|
+
...(args.handle ? { handle: args.handle } : {}),
|
|
59
|
+
});
|
|
60
|
+
case "rascunho":
|
|
61
|
+
return await convexAction("uploadPost:salvarRascunho", {
|
|
62
|
+
sessionToken,
|
|
63
|
+
handle: need(args.handle, "handle"),
|
|
64
|
+
rede: need(args.rede, "rede"),
|
|
65
|
+
legenda: args.legenda ?? "",
|
|
66
|
+
});
|
|
67
|
+
case "publicar": {
|
|
68
|
+
const redes = args.redes ?? [];
|
|
69
|
+
if (redes.length === 0)
|
|
70
|
+
throw new Error("Falta `redes`: em quais redes a peça sai (ids do painel).");
|
|
71
|
+
let scheduledAt;
|
|
72
|
+
if (args.agendarPara) {
|
|
73
|
+
scheduledAt = Date.parse(args.agendarPara);
|
|
74
|
+
if (!Number.isFinite(scheduledAt)) {
|
|
75
|
+
throw new Error("`agendarPara` não é uma data ISO válida. Ex: 2026-10-08T19:00:00-03:00.");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return await convexAction("uploadPost:publishOwn", {
|
|
79
|
+
sessionToken,
|
|
80
|
+
handle: need(args.handle, "handle"),
|
|
81
|
+
networks: redes,
|
|
82
|
+
...(args.text ? { text: args.text } : {}),
|
|
83
|
+
...(args.cta ? { cta: args.cta } : {}),
|
|
84
|
+
...(args.hashtags?.length ? { hashtags: args.hashtags } : {}),
|
|
85
|
+
...(args.legendas && Object.keys(args.legendas).length ? { captions: args.legendas } : {}),
|
|
86
|
+
...(scheduledAt !== undefined ? { scheduledAt } : {}),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
case "lista":
|
|
90
|
+
return await convexAction("uploadPost:mcpMinhasPublicacoes", { sessionToken });
|
|
91
|
+
case "conferir":
|
|
92
|
+
return await convexAction("uploadPost:conferirPublicacao", {
|
|
93
|
+
sessionToken,
|
|
94
|
+
postId: need(args.postId, "postId"),
|
|
95
|
+
});
|
|
96
|
+
case "cancelar":
|
|
97
|
+
return await convexAction("uploadPost:cancelarAgendado", {
|
|
98
|
+
sessionToken,
|
|
99
|
+
postId: need(args.postId, "postId"),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
package/dist/tools/video.js
CHANGED
|
@@ -29,9 +29,15 @@ import { httpUrl } from "../schema.js";
|
|
|
29
29
|
* cobrar. Assíncrono: volta imageId + parte, acompanhe em
|
|
30
30
|
* action=status. Encadeia (a parte 3 sai da parte 2), mas UMA POR
|
|
31
31
|
* VEZ: a próxima precisa da anterior pronta pra continuar dela.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
32
|
+
* No Omni o arquivo de cada parte traz as anteriores na frente:
|
|
33
|
+
* a parte 2 de 4s é um arquivo de 8s. A última parte pronta é o
|
|
34
|
+
* filme inteiro, e emendar as partes repete a abertura.
|
|
35
|
+
* - chain: a corrente inteira de um take (as partes na ordem, o pedaço
|
|
36
|
+
* novo que cada uma cobrou e o tamanho do arquivo dela, e qual
|
|
37
|
+
* parte serve de base pra próxima continuação). No Omni volta
|
|
38
|
+
* `filmeInteiro` (a última parte pronta, com a duração do
|
|
39
|
+
* arquivo) e `comoJuntar` diz pra não emendar. Sem custo.
|
|
40
|
+
* Qualquer parte serve de imageId.
|
|
35
41
|
* - models: catálogo vivo dos motores ativos com a FAIXA de preço (o que uma
|
|
36
42
|
* chamada sem config debita + o canto mais barato e o mais caro).
|
|
37
43
|
* Sem custo, sem login.
|
|
@@ -373,7 +379,8 @@ export const videoSchema = z.object({
|
|
|
373
379
|
"ou um vídeo já criado no site (o row define modelo + custo). Use sapiens_gallery action=list pra descobrir. " +
|
|
374
380
|
"action=sonorize: o imageId do clipe SEU (status completed) que vai ganhar som. " +
|
|
375
381
|
"action=extend: o take SEU (completed) que ganha o pedaço seguinte; pode ser a raiz ou a última parte " +
|
|
376
|
-
"da corrente (o servidor resolve a posição).
|
|
382
|
+
"da corrente (o servidor resolve a posição). No Omni a parte pronta já traz as anteriores na frente: a última é o filme inteiro, " +
|
|
383
|
+
"não junte as partes. action=chain: qualquer parte da corrente (devolve filmeInteiro quando o motor acumula)."),
|
|
377
384
|
// --- comum ---
|
|
378
385
|
prompt: z
|
|
379
386
|
.string()
|
|
@@ -400,7 +407,7 @@ export const videoSchema = z.object({
|
|
|
400
407
|
startImageId: z
|
|
401
408
|
.string()
|
|
402
409
|
.optional()
|
|
403
|
-
.describe("Frame inicial (i2v): generatedImages:_id da SUA galeria. Vira reference role 'start'."),
|
|
410
|
+
.describe("Frame inicial (i2v): generatedImages:_id da SUA galeria. Vira reference role 'start'. No Seedance 2.x e no H3 NÃO combina com referenceImage*/referenceVideoUrls: é um ou outro."),
|
|
404
411
|
startImageUrl: httpUrl()
|
|
405
412
|
.optional()
|
|
406
413
|
.describe("Frame inicial (i2v): url pública (Bunny/Convex/Wikimedia) de galeria/Acervo/personagem. Vira reference role 'start'."),
|
|
@@ -421,7 +428,8 @@ export const videoSchema = z.object({
|
|
|
421
428
|
"como imagens de REFERÊNCIA (role 'ref'). Diferente de startImageId: NÃO viram o 1º frame, guiam " +
|
|
422
429
|
"estilo/personagem/composição. Fluxo storyboard: gere a folha com sapiens_image " +
|
|
423
430
|
"templateSlug='storyboard-sapiens-v1' (ou -vertical-v1) e passe folha + personagem aqui. " +
|
|
424
|
-
"
|
|
431
|
+
"Referência e frame de borda são EXCLUSIVOS no H3 (endpoints diferentes) e na linha Seedance 2.0/Fast/Mini/2.5 (o provider recusa a mistura): mande refs OU startImage*/endImage*, não os dois. " +
|
|
432
|
+
"Quer a pessoa da foto no take? Mande a foto como referência e descreva o primeiro quadro no prompt."),
|
|
425
433
|
referenceImageUrls: z
|
|
426
434
|
.array(httpUrl())
|
|
427
435
|
.optional()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.87.0",
|
|
4
4
|
"mcpName": "com.sapiensinteticos/sapiens",
|
|
5
5
|
"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.",
|
|
6
6
|
"type": "module",
|