sapiens-mcp 1.102.1 → 1.103.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.
@@ -280,15 +280,25 @@ export function describeConvexError(e) {
280
280
  // cliente MESMO tendo gerado e COBRADO. 120s cobre esses casos; render de vídeo
281
281
  // (minutos) ainda precisa do fluxo assíncrono. Override por env pra outro teto.
282
282
  const CONVEX_TIMEOUT_MS = Number(process.env.SAPIENS_CONVEX_TIMEOUT_MS) || 120000;
283
- function withTimeout(p, label) {
283
+ /** O fim da mensagem quando quem chama não diz onde o resultado cai. */
284
+ const ONDE_CONFERIR_GENERICO = "Espere alguns minutos e leia o estado real por uma leitura (o `get`/`list`/`status` do mesmo tool) antes de decidir.";
285
+ /**
286
+ * A mensagem do Timeout. `ondeConferir` troca a frase genérica pela leitura
287
+ * certa daquele tool: o "status do mesmo tool" não existe em todo tool, e o
288
+ * agente que seguia a frase genérica no sapiens_image caía na galeria, que não
289
+ * mostra peça ainda gerando, e repetia a cobrança.
290
+ */
291
+ export function mensagemDeTimeout(label, ondeConferir) {
292
+ return (`Timeout: o backend Sapiens não respondeu em ${Math.round(CONVEX_TIMEOUT_MS / 1000)}s (${label}). Isto é o CLIENTE desistindo de esperar, não a ` +
293
+ `operação morrendo: ela segue rodando no servidor e, se cobra ` +
294
+ `Sinapses, JÁ cobrou. NÃO repita a chamada: repetir gera e cobra ` +
295
+ `de novo. ${ondeConferir ?? ONDE_CONFERIR_GENERICO}`);
296
+ }
297
+ function withTimeout(p, label, ondeConferir) {
284
298
  let timer;
285
299
  const timeout = new Promise((_, reject) => {
286
300
  timer = setTimeout(() => {
287
- reject(new Error(`Timeout: o backend Sapiens não respondeu em ${Math.round(CONVEX_TIMEOUT_MS / 1000)}s (${label}). Isto é o CLIENTE desistindo de esperar, não a ` +
288
- `operação morrendo: ela segue rodando no servidor e, se cobra ` +
289
- `Sinapses, JÁ cobrou. NÃO repita a chamada — repetir gera e cobra ` +
290
- `de novo. Espere alguns minutos e leia o estado real por uma ` +
291
- `leitura (o \`get\`/\`list\`/\`status\` do mesmo tool) antes de decidir.`));
301
+ reject(new Error(mensagemDeTimeout(label, ondeConferir)));
292
302
  }, CONVEX_TIMEOUT_MS);
293
303
  });
294
304
  return Promise.race([
@@ -344,7 +354,10 @@ export async function touchSession(token) {
344
354
  // best-effort: renovar é conforto, não pré-requisito da chamada em curso
345
355
  }
346
356
  }
347
- export async function convexAction(fnPath, args) {
357
+ export async function convexAction(fnPath, args,
358
+ // Onde o agente confere o resultado se o cliente desistir de esperar: a
359
+ // leitura daquele tool, no lugar da frase genérica da mensagem de Timeout.
360
+ opts = {}) {
348
361
  const client = getConvex();
349
- return (await withTimeout(client.action(fnPath, args), `action ${fnPath}`));
362
+ return (await withTimeout(client.action(fnPath, args), `action ${fnPath}`, opts.ondeConferir));
350
363
  }
package/dist/registry.js CHANGED
@@ -71,7 +71,7 @@ export const TOOLS = {
71
71
  handler: carrossel,
72
72
  },
73
73
  sapiens_image: {
74
- description: "Operações de imagem via Sapiens (Gemini, GPT Image 2 e 2.5, Grok, Seedream/ByteDance). Sub-actions: 'upscale' (sourceImageId de uma imagem SUA pronta: a mesma peça em resolução maior vira peça nova no acervo, a original fica; cobra Sinapses, preço fixo igual ao da ficha no site; SÍNCRONA e pode passar de 2 min, então Timeout é o cliente desistindo: olhe sapiens_gallery action=list antes de repetir), 'sombra' (sourceImageId de uma foto SUA pronta: extrai a sombra, o mapa de profundidade colorido da foto, como peça nova no acervo, pra usar de referência de pose e volume; cobra Sinapses, preço fixo; síncrona), 'generate' (gera imagem completa imediato — prompt+model+aspectRatio+size; suporta mode=edit/variation e MULTI-REFERÊNCIA: combine até 5 imagens como referência numa geração só, igual ao modal 'Selecionar Referência' do web — via referenceImageUrls (sua galeria + Acervo + personagens públicos de sapiens_character) e/ou sourceImageIds (ids da sua galeria); quem aceita e quantas chegam ao motor saem de supportsReferences e maxReferences em action=models (a ref acima do teto do motor some sem erro); EDIÇÃO POR ÁREA: sourceImageId + maskRegions (caixas em fração da imagem) muda SÓ a região marcada e devolve o resto igual ao pixel, no nano-banana-2 e no nano-banana-max, pelo preço da geração comum; FUNDO TRANSPARENTE: transparentBackground=true devolve PNG com alpha, o recorte feito pelo próprio motor, pelo preço da geração comum e sem o Remover Fundo pago depois, só na linha GPT Image (supportsTransparentBackground em action=models; nos outros recusa sem cobrar)), 'compose' (combina persona+screen via Gemini pra app-demo Shorts; 25 sinapses, rate limit 10/min). generate=image one-shot, compose=montar start frame app-demo. 'request_generation' é legado e recusa sem cobrar: vídeo nasce inteiro em sapiens_video action=create. TEMPLATE: passe templateSlug numa generate pra usar um super-prompt travado da casa — o `prompt` vira só a CENA (quem + pose + objeto-conceito) e o template embrulha estilo+fundo+enquadramento+ref de traço. 'retrato-sapiens-v1' = retrato editorial cartoon de um personagem no grid verde Sapiens (mesma 'mão' dos artigos); sem ref própria, injeta a Helen como âncora de traço (passar referenceImageUrls troca quem aparece). Mutuamente exclusivo com brandSlug. Sub-action 'models' (sem custo, sem login): lista o catálogo vivo (modelos ativos + preço cobrado em 1K com override admin + resolutionAdders, o adder por resolução já clampado ao teto de cada motor + maxResolution + se aceita referência e quantas, maxReferences) pra descobrir modelo/preço em vez de chutar. O preço de uma geração é priceSinapses + resolutionAdders[size], então 2K/4K custam MAIS que o número base: nunca cite o base como se fosse o total quando o size não for 1K. O generate devolve custoSinapses, o que o extrato debitou: é esse que se cita depois. NOTA: generate é SÍNCRONA e cobra ao concluir; modelo pesado (Pro, gpt-image-2-high, Grok quality, 2K/4K) cai na REGRA DO TIMEOUT (cheque sapiens_gallery action=list antes de repetir, evita cobrança dupla).",
74
+ description: "Operações de imagem via Sapiens (Gemini, GPT Image 2 e 2.5, Grok, Seedream/ByteDance). Sub-actions: 'upscale' (sourceImageId de uma imagem SUA pronta: a mesma peça em resolução maior vira peça nova no acervo, a original fica; cobra Sinapses, preço fixo igual ao da ficha no site; SÍNCRONA e pode passar de 2 min, então Timeout é o cliente desistindo: a peça nova entra pronta em até uns 6 min, leia action=status antes de repetir), 'sombra' (sourceImageId de uma foto SUA pronta: extrai a sombra, o mapa de profundidade colorido da foto, como peça nova no acervo, pra usar de referência de pose e volume; cobra Sinapses, preço fixo; síncrona), 'generate' (gera imagem completa imediato: prompt+model+aspectRatio+size; suporta mode=edit/variation e MULTI-REFERÊNCIA: combine até 5 imagens como referência numa geração só, igual ao modal 'Selecionar Referência' do web, via referenceImageUrls (sua galeria + Acervo + personagens públicos de sapiens_character) e/ou sourceImageIds (ids da sua galeria); quem aceita e quantas chegam ao motor saem de supportsReferences e maxReferences em action=models (a ref acima do teto do motor some sem erro); EDIÇÃO POR ÁREA: sourceImageId + maskRegions (caixas em fração da imagem) muda SÓ a região marcada e devolve o resto igual ao pixel, no nano-banana-2 e no nano-banana-max, pelo preço da geração comum; FUNDO TRANSPARENTE: transparentBackground=true devolve PNG com alpha, o recorte feito pelo próprio motor, pelo preço da geração comum e sem o Remover Fundo pago depois, só na linha GPT Image (supportsTransparentBackground em action=models; nos outros recusa sem cobrar)), 'compose' (combina persona+screen via Gemini pra app-demo Shorts; 25 sinapses, rate limit 10/min). generate=image one-shot, compose=montar start frame app-demo. 'request_generation' é legado e recusa sem cobrar: vídeo nasce inteiro em sapiens_video action=create. TEMPLATE: passe templateSlug numa generate pra usar um super-prompt travado da casa: o `prompt` vira só a CENA (quem + pose + objeto-conceito) e o template embrulha estilo+fundo+enquadramento+ref de traço. 'retrato-sapiens-v1' = retrato editorial cartoon de um personagem no grid verde Sapiens (mesma 'mão' dos artigos); sem ref própria, injeta a Helen como âncora de traço (passar referenceImageUrls troca quem aparece). Mutuamente exclusivo com brandSlug. Sub-action 'models' (sem custo, sem login): lista o catálogo vivo (modelos ativos + preço cobrado em 1K com override admin + resolutionAdders, o adder por resolução já clampado ao teto de cada motor + maxResolution + se aceita referência e quantas, maxReferences) pra descobrir modelo/preço em vez de chutar. O preço de uma geração é priceSinapses + resolutionAdders[size], então 2K/4K custam MAIS que o número base: nunca cite o base como se fosse o total quando o size não for 1K. O generate devolve custoSinapses, o que o extrato debitou: é esse que se cita depois. Sub-action 'status' (somente leitura, sem custo): as gerações de imagem mais recentes da conta, a mais nova primeiro, com o estado de cada uma (gerando, pronta, falhou, bloqueada, presa) e há quantos minutos nasceu. É a leitura depois de um Timeout: mostra a peça que AINDA está gerando, que a galeria (sapiens_gallery action=list) não mostra. NOTA: generate é SÍNCRONA e cobra no disparo; modelo pesado (Pro, gpt-image-2-high, GPT Image 2.5 Sunburst, Seedream 5.0 Pro, Grok quality, 2K/4K) cai na REGRA DO TIMEOUT: leia action=status antes de repetir. gerando = ainda no servidor e já cobrada, não gere de novo; pronta = mostre essa; falhou = o débito voltou, aí sim gere de novo.",
75
75
  schema: imageSchema,
76
76
  handler: image,
77
77
  },
@@ -91,7 +91,7 @@ export const TOOLS = {
91
91
  handler: repertorio,
92
92
  },
93
93
  sapiens_gallery: {
94
- description: "Browse, publicação e upload das imagens do user. Sub-actions: list (últimas N peças, com prompt/model/url + isPublic + acervoUrl; kind=image por default, kind=video traz os takes com posterUrl, a capa, e kind=all mistura. Depois de ingerir ou gerar vídeo, é o list kind=video que dá a capa pra mostrar miniatura + player em vez de link solto), get (1 imagem com metadados, opcionalmente base64), publish (torna a PRÓPRIA imagem pública: entra na galeria pública + feed Pinterest, e ganha página indexável /imagem/<id> se o modelo não for degen devolve publicPageUrl; publicado NÃO despublica, não existe unpublish), upload (traz pra galeria uma peça gerada FORA da casa, por sourceUrl https, filePath local ou base64; ADMIN por ora), ingest (A PONTE, qualquer conta logada: peça que a PESSOA dirigiu com a ficha do personagem daqui e um motor de fora renderizou, no crédito dela (Kie, fal, Magnific, Sogni, a própria placa): entra NATIVA na timeline e nasce PRIVADA (isPublic false), publicável DEPOIS por ela como qualquer geração da casa, nunca sozinha, com custo 0 em Sinapses e o custo real guardado em externalCost; carrega o prompt VERBATIM, as referências da casa (referenceImageIds), o personagem (characterId) e o motor (externalEngine 'provedor-motor'); a peça chega por filePath (local, só no MCP instalado), sourceUrl (o render, baixado pelo MCP na máquina da pessoa, nunca pelo servidor) ou base64; o carimbo +18 nasce na entrada pela CLASSE do provedor (peso aberto como Sogni, Replicate, HF, fal, WaveSpeed, Civitai e a própria placa entram carimbados, só a curadoria tira; serviço com moderação como Kie, Magnific, Freepik, Krea entra sem) ou por unfiltered=true dito pela pessoa (carimbo dela, ela tira depois); idempotente por sourceUrl ou pelo hash do arquivo, então re-ingerir corrige a ficha em vez de duplicar; tetos 12 MB imagem, 60 MB vídeo, 40 por dia. A chave do provedor NUNCA passa por aqui: quem gerou foi o harness da pessoa. Passo a passo na skill 'pontes'), refs (acopla peças da casa como REFERÊNCIA numa peça que já existe, de upload ou de ingest; ADMIN, e só na própria peça), processo (O COMO JUNTO DO QUE: anexa a uma peça as peças que mostram como ela foi dirigida, o mapa de rota desenhado sobre o still, a prancha de frames com o tempo de cada marco, o antes e depois de duas rodadas; elas viram a seção 'Como foi feito' na página pública da peça, na ordem que você mandar e com a sua legenda por peça; qualquer membro, só na própria peça, teto de 12. É IRMÃ do refs e a diferença importa: refs é o INSUMO que entrou na geração, processo é o REGISTRO de como ela foi dirigida, e uma lista não mexe na outra. Peça de processo privada não aparece pra quem está de fora nem em miniatura: pra aparecer, publique ela também), cast (QUEM ESTÁ EM CENA numa peça que já existe, quando é mais de uma criatura: characterIds em ordem, o protagonista primeiro, e a peça passa a contar na ficha de todos eles em vez de sumir da segunda; qualquer membro, na própria peça), parts (O INTEIRO E OS PEDAÇOS de um vídeo: o clipe de 30s que foi montado a partir de dois takes de 15s, a fita longa feita de partes. COM imageId devolve a ficha de parentesco daquela peça, quais são as partes dela e de qual inteiro ela é parte, com a url do arquivo completo pra baixar. SEM imageId devolve o que AINDA NÃO FOI MONTADO: varre os takes soltos da conta, agrupa os que têm cara de par (mesmo personagem, mesmo período, prompt de 'Part one/Part two' ou arquivo terminando em -a/-b) e diz o PORQUE de cada agrupamento, pra você saber o que falta juntar antes de o autor perguntar. É heurística e não monta nada sozinha: adianta a descoberta, quem decide é quem lê. characterId filtra por personagem. Sem custo), link_parts (LIGA o inteiro aos pedaços: imageId é o vídeo montado e partIds são os takes NA ORDEM em que aparecem nele. O juntador da casa e o ingest que traz referências de vídeo já gravam esse laço sozinhos; esta porta é pra montagem feita FORA (ffmpeg na máquina, ingest do arquivo já pronto) e pra corrigir ligação errada. Só na própria peça, teto de 16 partes, e a lista TROCA o que estava gravado antes. Sem custo), reprovar (O VETO do dono: imageId + motivo, o porquê numa frase concreta. A peça que errou (rosto do personagem trocado, mão quebrada, a referência errada) não sai mais por porta nenhuma, fila do Distribution, publicar, Telegram, e some das levas do garimpo; fica no acervo com o porquê, pra ensinar. Chame NO MESMO TURNO em que o dono condena uma peça: peça condenada e não marcada volta numa leva. desfazer=true tira o veto. Imagem e vídeo, só na própria peça, sem custo), reprovadas (as peças vetadas da conta com o prompt que as gerou e o motivo, a mais recente primeiro; characterId filtra por personagem. LEIA ANTES de gerar de novo um personagem que já teve peça reprovada: é a lista do que não repetir. Sem custo), carimbo (o +18 da peça: imageId + adulta true liga, false tira, com a regra do botão da ficha: a curadoria mexe em qualquer carimbo, inclusive o que a ponte põe por classe de motor sem autor, e o dono liga na própria peça e só tira o que ele mesmo pôs. Peça carimbada não entra em praça sfw do Distribution, então tirar o carimbo de peça vestida destrava Instagram, TikTok, YouTube e LinkedIn; peça com nudez fica carimbada. Sem custo). Use list/get pra reusar imagem como referência (passe o imageId em sapiens_image mode=edit ou mode=variation) ou pra mostrar pro user o que ele já tem; publish quando o user quer divulgar a imagem dele. IMPORTANTE sobre upload: a peça entra PRIVADA e continua privada: o servidor recusa publicar e recusa compartilhar na comunidade, porque ela é do usuário e a responsabilidade é dele. O caminho pra ela virar coisa pública é usar como referência numa geração daqui e publicar o resultado. O refs escreve só proveniência (de que ficha/folha a peça nasceu): não promove nada, e um upload continua sem publicar depois de ganhar referência. COMO A PEÇA FOI FEITA: list aceita skill=<slug> e devolve só o que saiu daquela skill (o mesmo slug que sapiens_image gravou em skills), com a busca varrendo as últimas 200 peças antes de cortar no limit; cada item volta com o campo skills, e null ali quer dizer que ninguém marcou, não que foi feita sem skill.",
94
+ description: "Browse, publicação e upload das imagens do user. Sub-actions: list (últimas N peças, com prompt/model/url + isPublic + acervoUrl; kind=image por default, kind=video traz os takes com posterUrl, a capa, e kind=all mistura. Depois de ingerir ou gerar vídeo, é o list kind=video que dá a capa pra mostrar miniatura + player em vez de link solto), get (1 imagem com metadados, opcionalmente base64), publish (torna a PRÓPRIA peça pública, imagem ou vídeo: a imagem entra na galeria pública + feed Pinterest e ganha página indexável /imagem/<id>, o vídeo ganha a /video/<id>, pela mesma régua do botão Publicar da ficha (peça oculta ou reprovada não publica, upload de fora também não, ingest da ponte sim); publicPageUrl volta null em peça +18 e de modelo degen; publicado NÃO despublica, não existe unpublish), upload (traz pra galeria uma peça gerada FORA da casa, por sourceUrl https, filePath local ou base64; ADMIN por ora), ingest (A PONTE, qualquer conta logada: peça que a PESSOA dirigiu com a ficha do personagem daqui e um motor de fora renderizou, no crédito dela (Kie, fal, Magnific, Sogni, a própria placa): entra NATIVA na timeline e nasce PRIVADA (isPublic false), publicável DEPOIS por ela como qualquer geração da casa, nunca sozinha, com custo 0 em Sinapses e o custo real guardado em externalCost; carrega o prompt VERBATIM, as referências da casa (referenceImageIds), o personagem (characterId) e o motor (externalEngine 'provedor-motor'); a peça chega por filePath (local, só no MCP instalado), sourceUrl (o render, baixado pelo MCP na máquina da pessoa, nunca pelo servidor) ou base64; o carimbo +18 nasce na entrada pela CLASSE do provedor (peso aberto como Sogni, Replicate, HF, fal, WaveSpeed, Civitai e a própria placa entram carimbados, só a curadoria tira; serviço com moderação como Kie, Magnific, Freepik, Krea entra sem) ou por unfiltered=true dito pela pessoa (carimbo dela, ela tira depois); idempotente por sourceUrl ou pelo hash do arquivo, então re-ingerir corrige a ficha em vez de duplicar; tetos 12 MB imagem, 60 MB vídeo, 40 por dia. A chave do provedor NUNCA passa por aqui: quem gerou foi o harness da pessoa. Passo a passo na skill 'pontes'), refs (acopla peças da casa como REFERÊNCIA numa peça que já existe, de upload ou de ingest; ADMIN, e só na própria peça), processo (O COMO JUNTO DO QUE: anexa a uma peça as peças que mostram como ela foi dirigida, o mapa de rota desenhado sobre o still, a prancha de frames com o tempo de cada marco, o antes e depois de duas rodadas; elas viram a seção 'Como foi feito' na página pública da peça, na ordem que você mandar e com a sua legenda por peça; qualquer membro, só na própria peça, teto de 12. É IRMÃ do refs e a diferença importa: refs é o INSUMO que entrou na geração, processo é o REGISTRO de como ela foi dirigida, e uma lista não mexe na outra. Peça de processo privada não aparece pra quem está de fora nem em miniatura: pra aparecer, publique ela também), cast (QUEM ESTÁ EM CENA numa peça que já existe, quando é mais de uma criatura: characterIds em ordem, o protagonista primeiro, e a peça passa a contar na ficha de todos eles em vez de sumir da segunda; qualquer membro, na própria peça), parts (O INTEIRO E OS PEDAÇOS de um vídeo: o clipe de 30s que foi montado a partir de dois takes de 15s, a fita longa feita de partes. COM imageId devolve a ficha de parentesco daquela peça, quais são as partes dela e de qual inteiro ela é parte, com a url do arquivo completo pra baixar. SEM imageId devolve o que AINDA NÃO FOI MONTADO: varre os takes soltos da conta, agrupa os que têm cara de par (mesmo personagem, mesmo período, prompt de 'Part one/Part two' ou arquivo terminando em -a/-b) e diz o PORQUE de cada agrupamento, pra você saber o que falta juntar antes de o autor perguntar. É heurística e não monta nada sozinha: adianta a descoberta, quem decide é quem lê. characterId filtra por personagem. Sem custo), link_parts (LIGA o inteiro aos pedaços: imageId é o vídeo montado e partIds são os takes NA ORDEM em que aparecem nele. O juntador da casa e o ingest que traz referências de vídeo já gravam esse laço sozinhos; esta porta é pra montagem feita FORA (ffmpeg na máquina, ingest do arquivo já pronto) e pra corrigir ligação errada. Só na própria peça, teto de 16 partes, e a lista TROCA o que estava gravado antes. Sem custo), reprovar (O VETO do dono: imageId + motivo, o porquê numa frase concreta. A peça que errou (rosto do personagem trocado, mão quebrada, a referência errada) não sai mais por porta nenhuma, fila do Distribution, publicar, Telegram, e some das levas do garimpo; fica no acervo com o porquê, pra ensinar. Chame NO MESMO TURNO em que o dono condena uma peça: peça condenada e não marcada volta numa leva. desfazer=true tira o veto. Imagem e vídeo, só na própria peça, sem custo), reprovadas (as peças vetadas da conta com o prompt que as gerou e o motivo, a mais recente primeiro; characterId filtra por personagem. LEIA ANTES de gerar de novo um personagem que já teve peça reprovada: é a lista do que não repetir. Sem custo), carimbo (o +18 da peça: imageId + adulta true liga, false tira, com a regra do botão da ficha: a curadoria mexe em qualquer carimbo, inclusive o que a ponte põe por classe de motor sem autor, e o dono liga na própria peça e só tira o que ele mesmo pôs. Peça carimbada não entra em praça sfw do Distribution, então tirar o carimbo de peça vestida destrava Instagram, TikTok, YouTube e LinkedIn; peça com nudez fica carimbada. Sem custo). Use list/get pra reusar imagem como referência (passe o imageId em sapiens_image mode=edit ou mode=variation) ou pra mostrar pro user o que ele já tem; publish quando o user quer divulgar a peça dele (imagem ou vídeo). IMPORTANTE sobre upload: a peça entra PRIVADA e continua privada: o servidor recusa publicar e recusa compartilhar na comunidade, porque ela é do usuário e a responsabilidade é dele. O caminho pra ela virar coisa pública é usar como referência numa geração daqui e publicar o resultado. O refs escreve só proveniência (de que ficha/folha a peça nasceu): não promove nada, e um upload continua sem publicar depois de ganhar referência. COMO A PEÇA FOI FEITA: list aceita skill=<slug> e devolve só o que saiu daquela skill (o mesmo slug que sapiens_image gravou em skills), com a busca varrendo as últimas 200 peças antes de cortar no limit; cada item volta com o campo skills, e null ali quer dizer que ninguém marcou, não que foi feita sem skill.",
95
95
  schema: gallerySchema,
96
96
  handler: gallery,
97
97
  },
@@ -146,7 +146,7 @@ export const TOOLS = {
146
146
  handler: musicator,
147
147
  },
148
148
  sapiens_video: {
149
- description: "Sapiens Video — gera vídeo (qualquer membro logado; vídeo é caro, cobra as Sinapses da sua conta). Sub-action 'create' (recomendada): escolhe modelo + config e gera num call (cria a row + renderiza). Modelos: 'sapiens-video-seedance' (Seedance 2.0, cena+áudio nativo, 4-15s, 480/720/1080p, t2v/i2v; aceita até 4 imagens de REFERÊNCIA via referenceImageIds/referenceImageUrls/referenceImagePaths (o H3 aceita até 9, o Omni 1.1 até 3; Kling, Hailuo, WAN 2.5 e 3.0 e os dois Spicy não), que guiam estilo/personagem/composição SEM virar o 1º frame — é o fluxo STORYBOARD: gere a folha de key poses com sapiens_image templateSlug='storyboard-sapiens-v1', passe folha + personagem como refs num t2v e descreva o take contínuo no prompt, citando as refs por descrição e mandando ignorar o traço do sketch; aceita também 1 VÍDEO DE MOVIMENTO via referenceVideoUrls (role 'refvideo' -> reference_videos, <=15s, host da casa): a coreografia/câmera do clipe guia o take, combinável com a folha), 'sapiens-video-seedance-2-fast' e 'sapiens-video-seedance-2-mini' (os irmãos do 2.0: MESMO repertório completo, incluindo referência, frame final e vídeo de movimento; o Fast custa 20% menos e o Mini METADE, ambos com teto 720p — pedir 1080p neles entrega e cobra 720p. Use o Mini pra iterar enquadramento/prompt barato e feche no 'sapiens-video-seedance' quando o take estiver certo), 'sapiens-video-seedance-25' (Seedance 2.5, a geração SEGUINTE e não um quarto tier da 2.0: take de 4 a 30s num fôlego, edita e estende vídeo, mesmo repertório de referência mais ÁUDIO como referência; teto 720p e ~1,5x o preço por segundo do 2.0. Duração é o que pesa aqui: 30s em 720p passa de 40 mil Sinapses, então confirme a duração com a pessoa antes de disparar. Quem precisa de 1080p fica no 'sapiens-video-seedance'), 'sapiens-video-kling' (Kling 3.0 Pro, anima imagem, 3-15s, sound opcional, i2v/t2v), 'sapiens-video-hailuo' (Hailuo 2.3 da MiniMax, física e movimento em 768p, 6 ou 10s, t2v/i2v) e 'sapiens-video-hailuo-pro' (o mesmo em 1080p, 5s fixo — duração não é param aqui): motores PUROS, sem áudio nativo, sem imagens de referência e sem frame final, então quem precisa disso fica no Seedance 2.0; o Pro é o 1080p mais barato da casa, 'sapiens-video-h3' (MiniMax H3: som nativo incluso sem toggle, 5 a 15s em '2k' ou '768p' (sem resolution cai no 2k, que custa 33% mais por segundo), t2v/i2v e frame final; ACEITA até 9 imagens e 3 vídeos de referência (somando 15s), o caminho de take longo com personagem travada; referência e frame inicial são exclusivos, mande um dos dois; o 2K de 15s leva uns 9 minutos de render, acompanhe em status e não gere de novo), 'sapiens-video-pvideo-2-pro' (P-Video-2 Pro, o H3 acelerado pela Pruna: o RASCUNHO de personagem travada, até 9 imagens contando referências e frame inicial e final no mesmo pedido, 5 a 15s em '480p' ou '768p', som nativo, o take volta em segundos; sem t2v, precisa de ao menos uma imagem ou um clipe; cobra por imagem além do segundo, então cote em 'price' com as mesmas imagens do create; aceita ainda até 3 vídeos (referenceVideoUrls) e 3 áudios (referenceAudioUrls) de referência, 15s somados por tipo, cada segundo cobrado à parte e medido pelo servidor antes do débito (cote com referenceVideoSec/referenceAudioSec), e keepAudio com um áudio só faz ele virar a trilha do take), 'sapiens-video-h3-spicy' (MiniMax H3 Spicy: o H3 SEM freio de conteúdo, i2v puro a partir de uma imagem sua, que é o que trava a identidade; 3 a 15s, 480p/768p/1080p, som nativo, frame final; o segundo de vídeo mais barato e o render mais rápido da casa), 'sapiens-video-seedance-spicy' (Seedance 2.0 Spicy: o 2.0 SEM freio, também i2v puro, som nativo; 4 a 15s em 480p e 720p, para em 10s em 1080p; sem frame final; o som tem interruptor no mesmo preço), 'sapiens-video-wan' (WAN 2.5, imagem que fala/canta com áudio+lip-sync, 5/10s, i2v), 'sapiens-video-wan-3' (WAN 3.0: texto ou imagem, som nativo com interruptor no mesmo preço, frame final, 5/8/10s em 480/720/1080p; sem imagem de referência), 'sapiens-video-kling-motion' (Motion transfer: passa o movimento de um vídeo pra uma imagem, PRECISA de pessoa com tronco visível na imagem E no vídeo), 'sapiens-video-shot-mimic' (Shot Mimic: recria o plano/câmera/cortes de um vídeo de referência como cena nova), 'sapiens-video-omni-11' (Gemini Omni 1.1: texto ou imagem vira vídeo de 4, 6, 8 ou 10s (sem durationSec, 10s) com áudio nativo, de '360p' a '4k' (sem resolution, 720p; 360p custa 1/3 do 720p, 1080p 1,5x, 4k 3x); aceita até 3 imagens de referência; editOfImageId aponta um vídeo Omni seu e o prompt edita a MESMA cena, preservando câmera e ambiente; e VÍDEO-FONTE: sourceVideoId (vídeo seu da galeria) ou sourceVideoUrl (link da casa), mp4 até 10 s, editado (sourceVideoMode 'edit', o padrão, ex: trocar a pessoa do vídeo pelo personagem da imagem de referência, cobrado pelo tamanho do clipe) ou estendido ('extend', cobrado pelo durationSec do pedaço novo)) ('sapiens-video-omni', o Omni 1.0, e 'sapiens-video-lite/fast/quality', o Veo 3.1, SAÍRAM: o Google apagou os quatro em 22/10/2026 e o pedido é recusado antes de cobrar). Args create: model, prompt, durationSec, resolution ('480p'/'720p'/'1080p'; no H3 '768p'/'2k'; no Omni 1.1 '360p' a '4k'), audio, aspectRatio. RECEITA DE TAKE (templateSlug + brief), o irmão do templateSlug da imagem: em vez de escrever o prompt inteiro, passe templateSlug e a receita travada da casa embrulha a cena com estilo, cenário, arco, áudio e look, e ainda escolhe o motor (por isso model fica opcional). O `prompt` vira só a CENA e o `brief` preenche os campos do formato (subject, persona, hook, shots com voiceLine e propVisible, uvps, language, energy); campo vazio some do prompt em vez de virar buraco. Receitas de hoje: 'ugc-vertical-v1' (selfie que fala, o formato nativo de Reels/TikTok/Shorts), 'unboxing-vertical-v1' (mãos e reveal, som real do papel e do lacre), 'app-demo-vertical-v1' (a tela do app legível na mão da pessoa) e 'reflexao-vertical-v1' (talking-head lento pra ideia ou ensaio). Override de model/aspectRatio/durationSec/resolution vale dentro do que a receita aceita, e o erro lista as opções. Sub-action 'templates' (sem custo, sem login) traz o catálogo vivo com spec default, whitelist e os briefFields de cada uma. Isto substitui a tool sapiens_shorts, que era admin-only e só falava Veo 3.1 Fast; o mesmo UGC de 8s sai a 720p no Seedance 2.0 Mini por bem menos. FRAME INICIAL/FINAL POR REFERÊNCIA (recomendado): startImageId/endImageId (id da sua galeria) ou startImageUrl/endImageUrl (url de galeria/Acervo/personagem) — resolvidos server-side igual à imagem, descubra via sapiens_reference. FRAME POR ARQUIVO LOCAL (só no MCP instalado/stdio, não no remoto): startImagePath/endImagePath = caminho absoluto de uma imagem no seu PC (PNG/JPEG/WebP até 8MB); o processo lê o arquivo e sobe como frame inicial/final, igual a subir no gerador do site — 1 imagem inicial + 1 final por vídeo, então pra vários vídeos rode create uma vez por imagem. No remoto use id/url. Alternativa base64: references (role 'start'=imagem i2v, 'end'=frame final, 'driving'=vídeo de movimento do Motion). Suporte a frame final varia por modelo. Custo server-side por config. Sub-action 'generate' (legado): renderiza um imageId de vídeo já criado no site. Retorna {success, url, imageId, cost}. VITRINE (sem custo): sub-action 'demos' lista os SEUS demo films (kind=demo do Estúdio de Vídeo) com slug + estado de vitrine; sub-action 'showcase' põe/tira um demo (por slug) do mini-cinema da /conectar-claude, com showcaseTag (chip de capacidade) e showcaseOrder (ordem asc). Fluxo: 'demos' pra achar o slug, depois 'showcase' com showcase=true. Só entra na vitrine pública se for a conta da casa. VÍDEOS PROGRAMÁTICOS (ADMIN, sem custo): o Lab do Estúdio de Vídeo (/experimentos/films, tabela videoSpecs, 5 kinds: demo | aula-tour | essay | tipografia-musical | dataviz) opera por aqui sem browser — 'film-list' (todos os kinds; filtros filmKind/filmStatus), 'film-get' (spec inteiro por slug), 'film-upsert' (cria/atualiza por slug, idempotente; spec = objeto JSON no shape do 'Copiar spec' da tela, validação no servidor), 'film-status' (produção por slug: filmStatus + videoUrl + durationSecMeasured; o fecho do render é os três num call), 'film-publish' (Acervo aba Fitas + portfólio; exige pronto+URL), 'film-delete' (limpar rascunho). O RENDER do filme segue no agente local (skill /film, repo da casa): o MCP registra e fecha o ciclo, não renderiza. create é ASSÍNCRONA: cria o row, debita e volta NA HORA com {imageId, status:'rendering', cost} (não espera o render, que leva de segundos a minutos). Acompanhe com a sub-action 'status' (imageId) até status='completed' (traz a url) ou 'error'/'blocked'. NÃO chame create de novo enquanto renderiza (cria outro vídeo e cobra de novo); falha de provider refunda sozinha. EDIÇÃO (as ações da ficha do site, cada uma vira peça nova e o original fica): 'trim' (imageId + startSec, endSec opcional: corta um trecho; grátis), 'join' (imageIds: 2 a 8 vídeos SEUS na ordem, até 180 s somados: compilado; grátis), 'fecho' (imageId + ending 'marca'/'sapiens'/'none', watermark, musicUrl de trilha da casa, nameCard {name, subtitle}: fecha o vídeo com a assinatura da casa; grátis), 'render-ref' (imageId do take + refUrl da folha que o gerou: a peça com a referência ao lado; cobra Sinapses, o mesmo par já feito volta de graça). Síncronas, podem passar de 2 min: Timeout é o cliente desistindo, olhe sapiens_gallery action=list kind=video antes de repetir. RESOLUÇÃO: 'upscale' (imageId de vídeo SEU completed + resolution = o alvo, '720p', '1080p', '2k' ou '4k') gera uma VARIANTE nova em resolução maior, o original fica intacto; cobra Sinapses por segundo do clipe, mais caro quanto maior o alvo, assíncrona como o create (acompanhe em status). SOM: 'sonorize' (imageId de vídeo SEU completed + prompt do som da cena) gera uma VARIANTE nova com trilha sincronizada (o original fica intacto; sonorize sempre o original, nunca uma variante). engine escolhe o motor: 'mirelo-sfx-2.0' (42 Sinapses/s, o default: GUARDA a fala do clipe, tira a música e refaz o resto), 'mmaudio-v2' (20 Sinapses/s, segue o texto em vez da imagem: é o motor do bicho trocado, onde o Mirelo devolve o som do bicho original; refaz o som inteiro e a fala se perde) ou 'elevenlabs-video-to-music' (26 Sinapses/s, faz a TRILHA e não o som da cena: uma música que acompanha os cortes, mixada por baixo do som que o clipe já tem; o prompt descreve a música). ADMIN: 'shadows' (videoUrl + title) extrai o depth map (depth-map) de um vídeo: entra na sua timeline de vídeos e no Acervo como driving reutilizável; 'shadows-list' lista os depth maps prontos. PREÇO DE VÍDEO É FAIXA, NÃO NÚMERO: nos motores por segundo (todo Seedance, Kling, WAN 2.5 e 3.0, Hailuo, H3, os dois Spicy, Shot Mimic, e desde out/2026 o Gemini Omni) a conta é duração x resolução [x áudio], e OMITIR não pega o barato: sem 'resolution' o servidor cobra o tier MAIS CARO do motor (menos o Gemini Omni 1.1, que fica no 720p), sem 'durationSec' cobra o piso de duração (no Omni, o padrão: 10s). Um create de Seedance 2.0 sem resolution debita 1080p. Nunca prometa um valor sem cotar: sub-action 'price' (sem custo, sem login) devolve o número EXATO que o create vai debitar pra model + durationSec + resolution + audio, e avisa (clamped=true) quando o que você pediu não é o que vai ser cobrado. Sub-action 'models' (sem custo, sem login): lista os modelos ativos + a faixa de preço calculada pela mesma função que debita (priceDefault = o que uma chamada sem config custa, priceMin e priceMax = os dois cantos do motor, cada um com a config que o produz) + config (durações/resoluções) + disponibilidade (motor em preview pode aparecer como 'em breve'). LEGENDA (fita, por slug): 'caption-list' (sem custo, mostra os idiomas que a peça já tem), 'caption-generate' (captionLang = idioma FALADO; captionTrio=true já traduz pro trio da casa pt+en+ja na mesma chamada) e 'caption-translate' (captionLang = destino, parte sempre da faixa original). Cobra por minuto começado de vídeo: 50 Sinapses o minuto transcrito, 20 o traduzido, com a duração vindo do doc da peça. A legenda é desenhada pela casa em dois estilos (discreta e social), trocáveis no play sem regerar e sem custo.",
149
+ description: "Sapiens Video — gera vídeo (qualquer membro logado; vídeo é caro, cobra as Sinapses da sua conta). Sub-action 'create' (recomendada): escolhe modelo + config e gera num call (cria a row + renderiza). Modelos: 'sapiens-video-seedance' (Seedance 2.0, cena+áudio nativo, 4-15s, 480/720/1080p, t2v/i2v; aceita até 4 imagens de REFERÊNCIA via referenceImageIds/referenceImageUrls/referenceImagePaths (o H3 aceita até 9, o Omni 1.1 até 3; Kling, Hailuo, WAN 2.5 e 3.0 e os dois Spicy não), que guiam estilo/personagem/composição SEM virar o 1º frame — é o fluxo STORYBOARD: gere a folha de key poses com sapiens_image templateSlug='storyboard-sapiens-v1', passe folha + personagem como refs num t2v e descreva o take contínuo no prompt, citando as refs por descrição e mandando ignorar o traço do sketch; aceita também 1 VÍDEO DE MOVIMENTO via referenceVideoUrls (role 'refvideo' -> reference_videos, <=15s, host da casa): a coreografia/câmera do clipe guia o take, combinável com a folha), 'sapiens-video-seedance-2-fast' e 'sapiens-video-seedance-2-mini' (os irmãos do 2.0: MESMO repertório completo, incluindo referência, frame final e vídeo de movimento; o Fast custa 20% menos e o Mini METADE, ambos com teto 720p — pedir 1080p neles entrega e cobra 720p. Use o Mini pra iterar enquadramento/prompt barato e feche no 'sapiens-video-seedance' quando o take estiver certo), 'sapiens-video-seedance-25' (Seedance 2.5, a geração SEGUINTE e não um quarto tier da 2.0: take de 4 a 30s num fôlego, edita e estende vídeo, mesmo repertório de referência mais ÁUDIO como referência; teto 720p e ~1,5x o preço por segundo do 2.0. Duração é o que pesa aqui: 30s em 720p passa de 40 mil Sinapses, então confirme a duração com a pessoa antes de disparar. Quem precisa de 1080p fica no 'sapiens-video-seedance'), 'sapiens-video-kling' (Kling 3.0 Pro, anima imagem, 3-15s, sound opcional, i2v/t2v), 'sapiens-video-hailuo' (Hailuo 2.3 da MiniMax, física e movimento em 768p, 6 ou 10s, t2v/i2v) e 'sapiens-video-hailuo-pro' (o mesmo em 1080p, 5s fixo — duração não é param aqui): motores PUROS, sem áudio nativo, sem imagens de referência e sem frame final, então quem precisa disso fica no Seedance 2.0; o Pro é o 1080p mais barato da casa, 'sapiens-video-h3' (MiniMax H3: som nativo incluso sem toggle, 5 a 15s em '2k' ou '768p' (sem resolution cai no 2k, que custa 33% mais por segundo), t2v/i2v e frame final; ACEITA até 9 imagens e 3 vídeos de referência (somando 15s), o caminho de take longo com personagem travada; referência e frame inicial são exclusivos, mande um dos dois; o 2K de 15s leva uns 9 minutos de render, acompanhe em status e não gere de novo), 'sapiens-video-pvideo-2-pro' (P-Video-2 Pro, o H3 acelerado pela Pruna: o RASCUNHO de personagem travada, até 9 imagens contando referências e frame inicial e final no mesmo pedido, 5 a 15s em '480p' ou '768p', som nativo, o take volta em segundos; sem t2v, precisa de ao menos uma imagem ou um clipe; cobra por imagem além do segundo, então cote em 'price' com as mesmas imagens do create; aceita ainda até 3 vídeos (referenceVideoUrls) e 3 áudios (referenceAudioUrls) de referência, 15s somados por tipo, cada segundo cobrado à parte e medido pelo servidor antes do débito (cote com referenceVideoSec/referenceAudioSec), e keepAudio com um áudio só faz ele virar a trilha do take), 'sapiens-video-h3-spicy' (MiniMax H3 Spicy: o H3 SEM freio de conteúdo, i2v puro a partir de uma imagem sua, que é o que trava a identidade; 3 a 15s, 480p/768p/1080p, som nativo, frame final; o segundo de vídeo mais barato e o render mais rápido da casa), 'sapiens-video-seedance-spicy' (Seedance 2.0 Spicy: o 2.0 SEM freio, também i2v puro, som nativo; 4 a 15s em 480p e 720p, para em 10s em 1080p; sem frame final; o som tem interruptor no mesmo preço), 'sapiens-video-wan' (WAN 2.5, imagem que fala/canta com áudio+lip-sync, 5/10s, i2v), 'sapiens-video-wan-3' (WAN 3.0: texto ou imagem, som nativo com interruptor no mesmo preço, frame final, 5/8/10s em 480/720/1080p; sem imagem de referência), 'sapiens-video-flux-3-max' (FLUX 3 Max, fal + Black Forest Labs: texto ou imagem, 5 a 20s em 720p/1080p, som nativo com interruptor, frame final junto do inicial; sem imagem de referência), 'sapiens-video-kling-motion' (Motion transfer: passa o movimento de um vídeo pra uma imagem, PRECISA de pessoa com tronco visível na imagem E no vídeo), 'sapiens-video-shot-mimic' (Shot Mimic: recria o plano/câmera/cortes de um vídeo de referência como cena nova), 'sapiens-video-omni-11' (Gemini Omni 1.1: texto ou imagem vira vídeo de 4, 6, 8 ou 10s (sem durationSec, 10s) com áudio nativo, de '360p' a '4k' (sem resolution, 720p; 360p custa 1/3 do 720p, 1080p 1,5x, 4k 3x); aceita até 3 imagens de referência; editOfImageId aponta um vídeo Omni seu e o prompt edita a MESMA cena, preservando câmera e ambiente; e VÍDEO-FONTE: sourceVideoId (vídeo seu da galeria) ou sourceVideoUrl (link da casa), mp4 até 10 s, editado (sourceVideoMode 'edit', o padrão, ex: trocar a pessoa do vídeo pelo personagem da imagem de referência, cobrado pelo tamanho do clipe) ou estendido ('extend', cobrado pelo durationSec do pedaço novo)) ('sapiens-video-omni', o Omni 1.0, e 'sapiens-video-lite/fast/quality', o Veo 3.1, SAÍRAM: o Google apagou os quatro em 22/10/2026 e o pedido é recusado antes de cobrar). Args create: model, prompt, durationSec, resolution ('480p'/'720p'/'1080p'; no H3 '768p'/'2k'; no Omni 1.1 '360p' a '4k'), audio, aspectRatio. RECEITA DE TAKE (templateSlug + brief), o irmão do templateSlug da imagem: em vez de escrever o prompt inteiro, passe templateSlug e a receita travada da casa embrulha a cena com estilo, cenário, arco, áudio e look, e ainda escolhe o motor (por isso model fica opcional). O `prompt` vira só a CENA e o `brief` preenche os campos do formato (subject, persona, hook, shots com voiceLine e propVisible, uvps, language, energy); campo vazio some do prompt em vez de virar buraco. Receitas de hoje: 'ugc-vertical-v1' (selfie que fala, o formato nativo de Reels/TikTok/Shorts), 'unboxing-vertical-v1' (mãos e reveal, som real do papel e do lacre), 'app-demo-vertical-v1' (a tela do app legível na mão da pessoa) e 'reflexao-vertical-v1' (talking-head lento pra ideia ou ensaio). Override de model/aspectRatio/durationSec/resolution vale dentro do que a receita aceita, e o erro lista as opções. Sub-action 'templates' (sem custo, sem login) traz o catálogo vivo com spec default, whitelist e os briefFields de cada uma. Isto substitui a tool sapiens_shorts, que era admin-only e só falava Veo 3.1 Fast; o mesmo UGC de 8s sai a 720p no Seedance 2.0 Mini por bem menos. FRAME INICIAL/FINAL POR REFERÊNCIA (recomendado): startImageId/endImageId (id da sua galeria) ou startImageUrl/endImageUrl (url de galeria/Acervo/personagem) — resolvidos server-side igual à imagem, descubra via sapiens_reference. FRAME POR ARQUIVO LOCAL (só no MCP instalado/stdio, não no remoto): startImagePath/endImagePath = caminho absoluto de uma imagem no seu PC (PNG/JPEG/WebP até 8MB); o processo lê o arquivo e sobe como frame inicial/final, igual a subir no gerador do site — 1 imagem inicial + 1 final por vídeo, então pra vários vídeos rode create uma vez por imagem. No remoto use id/url. Alternativa base64: references (role 'start'=imagem i2v, 'end'=frame final, 'driving'=vídeo de movimento do Motion). Suporte a frame final varia por modelo. Custo server-side por config. Sub-action 'generate' (legado): renderiza um imageId de vídeo já criado no site. Retorna {success, url, imageId, cost}. VITRINE (sem custo): sub-action 'demos' lista os SEUS demo films (kind=demo do Estúdio de Vídeo) com slug + estado de vitrine; sub-action 'showcase' põe/tira um demo (por slug) do mini-cinema da /conectar-claude, com showcaseTag (chip de capacidade) e showcaseOrder (ordem asc). Fluxo: 'demos' pra achar o slug, depois 'showcase' com showcase=true. Só entra na vitrine pública se for a conta da casa. VÍDEOS PROGRAMÁTICOS (ADMIN, sem custo): o Lab do Estúdio de Vídeo (/experimentos/films, tabela videoSpecs, 5 kinds: demo | aula-tour | essay | tipografia-musical | dataviz) opera por aqui sem browser — 'film-list' (todos os kinds; filtros filmKind/filmStatus), 'film-get' (spec inteiro por slug), 'film-upsert' (cria/atualiza por slug, idempotente; spec = objeto JSON no shape do 'Copiar spec' da tela, validação no servidor), 'film-status' (produção por slug: filmStatus + videoUrl + durationSecMeasured; o fecho do render é os três num call), 'film-publish' (Acervo aba Fitas + portfólio; exige pronto+URL), 'film-delete' (limpar rascunho). O RENDER do filme segue no agente local (skill /film, repo da casa): o MCP registra e fecha o ciclo, não renderiza. create é ASSÍNCRONA: cria o row, debita e volta NA HORA com {imageId, status:'rendering', cost} (não espera o render, que leva de segundos a minutos). Acompanhe com a sub-action 'status' (imageId) até status='completed' (traz a url) ou 'error'/'blocked'. NÃO chame create de novo enquanto renderiza (cria outro vídeo e cobra de novo); falha de provider refunda sozinha. EDIÇÃO (as ações da ficha do site, cada uma vira peça nova e o original fica): 'trim' (imageId + startSec, endSec opcional: corta um trecho; grátis), 'join' (imageIds: 2 a 8 vídeos SEUS na ordem, até 180 s somados: compilado; grátis), 'fecho' (imageId + ending 'marca'/'sapiens'/'none', watermark, musicUrl de trilha da casa, nameCard {name, subtitle}: fecha o vídeo com a assinatura da casa; grátis), 'render-ref' (imageId do take + refUrl da folha que o gerou: a peça com a referência ao lado; cobra Sinapses, o mesmo par já feito volta de graça). Síncronas, podem passar de 2 min: Timeout é o cliente desistindo, olhe sapiens_gallery action=list kind=video antes de repetir. RESOLUÇÃO: 'upscale' (imageId de vídeo SEU completed + resolution = o alvo, '720p', '1080p', '2k' ou '4k') gera uma VARIANTE nova em resolução maior, o original fica intacto; cobra Sinapses por segundo do clipe, mais caro quanto maior o alvo, assíncrona como o create (acompanhe em status). SOM: 'sonorize' (imageId de vídeo SEU completed + prompt do som da cena) gera uma VARIANTE nova com trilha sincronizada (o original fica intacto; sonorize sempre o original, nunca uma variante). engine escolhe o motor: 'mirelo-sfx-2.0' (42 Sinapses/s, o default: GUARDA a fala do clipe, tira a música e refaz o resto), 'mmaudio-v2' (20 Sinapses/s, segue o texto em vez da imagem: é o motor do bicho trocado, onde o Mirelo devolve o som do bicho original; refaz o som inteiro e a fala se perde) ou 'elevenlabs-video-to-music' (26 Sinapses/s, faz a TRILHA e não o som da cena: uma música que acompanha os cortes, mixada por baixo do som que o clipe já tem; o prompt descreve a música). ADMIN: 'shadows' (videoUrl + title) extrai o depth map (depth-map) de um vídeo: entra na sua timeline de vídeos e no Acervo como driving reutilizável; 'shadows-list' lista os depth maps prontos. PREÇO DE VÍDEO É FAIXA, NÃO NÚMERO: nos motores por segundo (todo Seedance, Kling, WAN 2.5 e 3.0, Hailuo, H3, os dois Spicy, Shot Mimic, e desde out/2026 o Gemini Omni) a conta é duração x resolução [x áudio], e OMITIR não pega o barato: sem 'resolution' o servidor cobra o tier MAIS CARO do motor (menos o Gemini Omni 1.1, que fica no 720p), sem 'durationSec' cobra o piso de duração (no Omni, o padrão: 10s). Um create de Seedance 2.0 sem resolution debita 1080p. Nunca prometa um valor sem cotar: sub-action 'price' (sem custo, sem login) devolve o número EXATO que o create vai debitar pra model + durationSec + resolution + audio, e avisa (clamped=true) quando o que você pediu não é o que vai ser cobrado. Sub-action 'models' (sem custo, sem login): lista os modelos ativos + a faixa de preço calculada pela mesma função que debita (priceDefault = o que uma chamada sem config custa, priceMin e priceMax = os dois cantos do motor, cada um com a config que o produz) + config (durações/resoluções) + disponibilidade (motor em preview pode aparecer como 'em breve'). LEGENDA (fita, por slug): 'caption-list' (sem custo, mostra os idiomas que a peça já tem), 'caption-generate' (captionLang = idioma FALADO; captionTrio=true já traduz pro trio da casa pt+en+ja na mesma chamada) e 'caption-translate' (captionLang = destino, parte sempre da faixa original). Cobra por minuto começado de vídeo: 50 Sinapses o minuto transcrito, 20 o traduzido, com a duração vindo do doc da peça. A legenda é desenhada pela casa em dois estilos (discreta e social), trocáveis no play sem regerar e sem custo.",
150
150
  schema: videoSchema,
151
151
  handler: video,
152
152
  },
@@ -231,7 +231,7 @@ export const TOOLS = {
231
231
  handler: trilhas,
232
232
  },
233
233
  sapiens_distribution: {
234
- 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; num Reel, videoCoverUrl é a CAPA da casa, que pela API só entra aqui, e o retorno traz `aviso` quando a mesma abertura, a 1a linha da copy, já foi ao ar na mesma rede por qualquer aba: a peça entra mesmo assim, e você mostra o aviso ao dono antes de seguir, porque série de molde abre igual e é outra peça, mas a mesma notícia por duas abas é repetição). 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; e `categoria` diz o que a peça É (arte, personagem, tecnico, novidade, educativo, mercado, o significado de cada uma na descrição do campo): declare sempre que souber, senão a régua chuta pelo título e a peça cai na gaveta errada da fila, list (o que está na fila, filtrável por status, por aba e por categoria ('sem' é a triagem), 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, assets, videoCoverUrl ou categoria (esta vale em peça postada também, e null devolve pra régua); é 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.",
234
+ 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; num Reel, videoCoverUrl é a CAPA da casa, que pela API só entra aqui, e o retorno traz `aviso` quando a mesma abertura, a 1a linha da copy, já foi ao ar na mesma rede por qualquer aba: a peça entra mesmo assim, e você mostra o aviso ao dono antes de seguir, porque série de molde abre igual e é outra peça, mas a mesma notícia por duas abas é repetição). 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; e `categoria` diz o que a peça É (arte, personagem, tecnico, novidade, educativo, mercado, pessoal, o significado de cada uma na descrição do campo): declare sempre que souber, senão a régua chuta pelo título e a peça cai na gaveta errada da fila, list (o que está na fila, filtrável por status, por aba e por categoria ('sem' é a triagem), 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, assets, videoCoverUrl ou categoria (esta vale em peça postada também, e null devolve pra régua); é 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.",
235
235
  schema: distributionSchema,
236
236
  handler: distribution,
237
237
  },
@@ -266,27 +266,27 @@ export const TOOLS = {
266
266
  // É a "skill que anda junto com o pacote": escrevo uma vez, vale pra todos os clients,
267
267
  // sem instalar nada. Cobre os tropeços reais (fluxo do musicator, model no vídeo, o
268
268
  // disjuntor anti-loop). Mantém curto de propósito: viaja em todo handshake.
269
- export const SAPIENS_INSTRUCTIONS = `Você opera o Sapiens Sintéticos (sapiensinteticos.com) NA CONTA de um usuário logado. Cada tool age de verdade na conta dele e muitas COBRAM Sinapses (o crédito da casa). Aja como operador, não no chute.
270
-
271
- AS SKILLS DA CASA (leia ANTES de operar, não improvise o fluxo):
272
- O passo a passo travado de cada fluxo mora na tool sapiens_skill, servida por este mesmo servidor: sem login, sem custo, sem rede. Ler a skill é mais barato que errar uma geração que cobra.
273
- - sapiens_skill action=list -> o índice (slug + quando usar cada uma).
274
- - sapiens_skill action=get name=<slug> -> a skill inteira.
275
- Slugs: ${skillMenuLine()}
276
- 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), escrever código que chama a API da conta (sapiens-api). Perdido no começo: primeiros-passos.
277
- Cliente que lê resources MCP acha o MESMO conteúdo em skill://sapiens/<slug>/SKILL.md.
278
-
279
- REGRA DE OURO:
280
- - PRIMEIRO CONTATO ou "o que você faz?"/"como começo?"/"o que dá pra fazer?": chame sapiens_meta action=start e MOSTRE o resultado na sua voz. Sem login, ele ensina a conectar; logado, traz saldo + primeiros poderes com exemplos. É a porta de entrada: não despeje a lista inteira de tools, deixe o start guiar.
281
- - LOGO APÓS UM LOGIN BEM-SUCEDIDO (action=login retornou ok): chame action=start na sequência e mostre a porta de entrada. O recém-chegado não sabe o que pedir; não o deixe na tela em branco, guie a primeira jogada sem ele precisar perguntar.
282
- - Antes de gerar algo caro (imagem/música/vídeo), cheque saldo: sapiens_meta action=credits (ou subscription). Saldo baixo, avise o usuário antes. Vídeo é o mais caro da casa: confirme com ele antes de disparar.
283
- - DUAS PORTAS, lado a lado: Sinapse (sapiens_image, sapiens_video: nada pra configurar) ou a CHAVE DA PESSOA num provedor (fal, Kie, WaveSpeed, Replicate, OpenRouter, Sogni, a própria placa), que custa zero aqui. No MCP instalado, sapiens_pontes gera com a chave que mora na máquina dela (fal, Kie, WaveSpeed, Replicate, OpenRouter) e traz a peça pro acervo; no remoto, ela gera no harness dela e traz por sapiens_gallery action=ingest. sapiens_meta action=pontes diz o que ela já tem configurado: se tiver chave, ofereça as duas portas antes de gastar Sinapse. A chave NUNCA passa pelo Sapiens (nem em arg, nem no chat). Skill 'pontes'.
284
- - REGRA DO TIMEOUT: geração SÍNCRONA pode estourar o teto de ~120s do cliente e voltar 'Timeout' MESMO tendo gerado e COBRADO. Nunca repita às cegas: confira antes onde o resultado cairia (a tabela de onde conferir está na skill 'primeiros-passos').
285
- - "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
286
- - sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo. sapiens_image e sapiens_video action=models trazem o catálogo com o preço ATUAL: consulte em vez de chutar custo. Preço do App em Sinapses e da API em dólar (carteiras separadas, uma nunca vira a outra): sapiens_meta action=precos.
287
-
288
- MODO COMPANHIA: sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, você INCORPORA aquele Sintético (a voz dele, o avatar, o oi dele) continuando a operar na conta e nas Sinapses do USUÁRIO. Puxe a skill 'companhia' antes de fazer isso. Se vier 'characterOffer', siga o que ele manda: são personagens que o usuário escreveu e que podem entrar em cena, e quem OFERECE é você, na hora em que a conversa encostar num deles. Só personagem de autoria dele; a alma de personagem alheio não sai por aqui.
289
-
269
+ export const SAPIENS_INSTRUCTIONS = `Você opera o Sapiens Sintéticos (sapiensinteticos.com) NA CONTA de um usuário logado. Cada tool age de verdade na conta dele e muitas COBRAM Sinapses (o crédito da casa). Aja como operador, não no chute.
270
+
271
+ AS SKILLS DA CASA (leia ANTES de operar, não improvise o fluxo):
272
+ O passo a passo travado de cada fluxo mora na tool sapiens_skill, servida por este mesmo servidor: sem login, sem custo, sem rede. Ler a skill é mais barato que errar uma geração que cobra.
273
+ - sapiens_skill action=list -> o índice (slug + quando usar cada uma).
274
+ - sapiens_skill action=get name=<slug> -> a skill inteira.
275
+ Slugs: ${skillMenuLine()}
276
+ 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), escrever código que chama a API da conta (sapiens-api). Perdido no começo: primeiros-passos.
277
+ Cliente que lê resources MCP acha o MESMO conteúdo em skill://sapiens/<slug>/SKILL.md.
278
+
279
+ REGRA DE OURO:
280
+ - PRIMEIRO CONTATO ou "o que você faz?"/"como começo?"/"o que dá pra fazer?": chame sapiens_meta action=start e MOSTRE o resultado na sua voz. Sem login, ele ensina a conectar; logado, traz saldo + primeiros poderes com exemplos. É a porta de entrada: não despeje a lista inteira de tools, deixe o start guiar.
281
+ - LOGO APÓS UM LOGIN BEM-SUCEDIDO (action=login retornou ok): chame action=start na sequência e mostre a porta de entrada. O recém-chegado não sabe o que pedir; não o deixe na tela em branco, guie a primeira jogada sem ele precisar perguntar.
282
+ - Antes de gerar algo caro (imagem/música/vídeo), cheque saldo: sapiens_meta action=credits (ou subscription). Saldo baixo, avise o usuário antes. Vídeo é o mais caro da casa: confirme com ele antes de disparar.
283
+ - DUAS PORTAS, lado a lado: Sinapse (sapiens_image, sapiens_video: nada pra configurar) ou a CHAVE DA PESSOA num provedor (fal, Kie, WaveSpeed, Replicate, OpenRouter, Sogni, a própria placa), que custa zero aqui. No MCP instalado, sapiens_pontes gera com a chave que mora na máquina dela (fal, Kie, WaveSpeed, Replicate, OpenRouter) e traz a peça pro acervo; no remoto, ela gera no harness dela e traz por sapiens_gallery action=ingest. sapiens_meta action=pontes diz o que ela já tem configurado: se tiver chave, ofereça as duas portas antes de gastar Sinapse. A chave NUNCA passa pelo Sapiens (nem em arg, nem no chat). Skill 'pontes'.
284
+ - REGRA DO TIMEOUT: geração SÍNCRONA pode estourar o teto de ~120s do cliente e voltar 'Timeout' MESMO tendo gerado e COBRADO. Nunca repita às cegas: confira antes onde o resultado cairia. Imagem: sapiens_image action=status, que mostra até a peça que ainda está gerando (a galeria só mostra pronta). O resto está na tabela de onde conferir da skill 'primeiros-passos'.
285
+ - "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
286
+ - sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo. sapiens_image e sapiens_video action=models trazem o catálogo com o preço ATUAL: consulte em vez de chutar custo. Preço do App em Sinapses e da API em dólar (carteiras separadas, uma nunca vira a outra): sapiens_meta action=precos.
287
+
288
+ MODO COMPANHIA: sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, você INCORPORA aquele Sintético (a voz dele, o avatar, o oi dele) continuando a operar na conta e nas Sinapses do USUÁRIO. Puxe a skill 'companhia' antes de fazer isso. Se vier 'characterOffer', siga o que ele manda: são personagens que o usuário escreveu e que podem entrar em cena, e quem OFERECE é você, na hora em que a conversa encostar num deles. Só personagem de autoria dele; a alma de personagem alheio não sai por aqui.
289
+
290
290
  Voz da casa: 1ª pessoa, direto, anti-corporate, sem travessão. Pra bom entendedor, meia palavra basta. Texto que vai ser publicado pede a skill 'voz-da-casa' antes.`;
291
291
  // Annotations MCP: título humano + dica read-only. São HINTS (não-confiáveis por
292
292
  // spec): quem gateia de verdade continua o servidor (saldo, gate de admin,
package/dist/skills.js CHANGED
@@ -57,10 +57,12 @@ Não despeje a lista inteira de tools. O start guia.
57
57
 
58
58
  | O que gerou | Onde conferir |
59
59
  |---|---|
60
- | imagem | \`sapiens_gallery action=list\` |
60
+ | imagem (generate, upscale, sombra) | \`sapiens_image action=status\` |
61
61
  | artigo do perfil | \`sapiens_write action=list\` |
62
62
  | carrossel | \`sapiens_carrossel action=list\` |
63
63
 
64
+ Imagem tem leitura própria porque a galeria (\`sapiens_gallery action=list\`) só mostra peça PRONTA: a que ainda está gerando não aparece lá, parece que falhou, e repetir cobra de novo. O \`status\` lista as gerações recentes da conta com o estado de cada uma: \`gerando\` (já cobrou, NÃO gere de novo, leia de novo em 1 ou 2 minutos), \`pronta\` (mostre essa), \`falhou\` ou \`bloqueada\` (o débito voltou, aí sim gere de novo) e \`presa\` (passou de 15 minutos gerando, a varredura do servidor estorna).
65
+
64
66
  **2. Disjuntor anti-loop.** Três falhas seguidas no MESMO tool fazem o cliente marcar o servidor como "unreachable" por ~56s. Parece que "o MCP caiu", mas foi argumento faltando. Quando um tool volta erro de validação ("exige X", "falta Y"), LEIA o erro e refaça a chamada COM o que falta. Nunca repita a chamada idêntica que falhou.
65
67
 
66
68
  **3. Saldo.** Antes de gerar algo caro (imagem, música, vídeo), cheque com \`sapiens_meta action=credits\` ou \`action=subscription\`. Saldo baixo, avise ANTES de gastar. Vídeo é o mais caro da casa: confirme com a pessoa antes de disparar.
@@ -109,8 +111,10 @@ O modelo repete esses porque soam competentes. Todos caem.
109
111
  - **Frase vazia**: "vale destacar", "é importante notar", "no final das contas", "quando se trata de", "nos dias de hoje".
110
112
  - **Rodízio de sinônimo**: o agente, depois o assistente, depois a ferramenta, tudo pra mesma coisa. Repetir a palavra certa é precisão.
111
113
  - **Kicker de falsa profundidade**: a última linha "funda" que vira aforismo. Deleta, não reescreve numa metáfora melhor. Termina na frase concreta que já estava lá.
112
-
113
- Hedge não entra nessa lista: "ao meu ver", "por enquanto", "talvez" assinam a voz e ficam.
114
+ - **Muleta de hedge**: "ao meu ver", "na minha opinião", "tendo a achar", "talvez" que não carrega dúvida. Corta e afirma. Incerteza real fica, dita como fato: "testei só no plano grátis", "até o preço cair".
115
+ - **Palavra difícil**: "utilizar", "possuir", "visando", "a fim de", "devido ao fato de". Usar, ter, pra, porque.
116
+ - **Advérbio no lugar do número**: "melhorou significativamente", "caiu drasticamente". Fala o número.
117
+ - **Passiva com agente**: "foi lançado pela OpenAI" vira "a OpenAI lançou". Quem fez é o sujeito.
114
118
 
115
119
  ## Revisar sem apagar a pessoa
116
120
 
@@ -256,6 +260,7 @@ Duração é o que pesa aqui, não o modelo: um take de 30s em 720p passa de 40
256
260
  - \`sapiens-video-kling\`: Kling 3.0 Pro, anima imagem, 3 a 15s, som opcional.
257
261
  - \`sapiens-video-wan\`: WAN 2.5, imagem que fala ou canta, com lip-sync, 5 ou 10s.
258
262
  - \`sapiens-video-wan-3\`: WAN 3.0, texto ou imagem, som nativo, frame final e 1080p, 5 a 10s.
263
+ - \`sapiens-video-flux-3-max\`: FLUX 3 Max, texto ou imagem, 5 a 20s em \`720p\` ou \`1080p\`, som nativo e frame final (só junto do inicial). Segue o prompt de perto e volta rápido. Não aceita referência de personagem nem vídeo de movimento.
259
264
  - \`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.
260
265
  - \`sapiens-video-shot-mimic\`: recria o plano, a câmera e os cortes de um vídeo de referência como cena nova.
261
266
  - \`sapiens-video-omni-11\`: Gemini Omni 1.1, texto ou imagem vira clipe de 4, 6, 8 ou 10s (sem \`durationSec\`, 10s) com áudio nativo, de \`360p\` a \`4k\` (sem \`resolution\`, 720p). O preço é por segundo e por resolução: o take de 4s custa 40% do de 10s, o 360p custa 1/3 do 720p, o 1080p 1,5x e o 4k 3x. Aceita até 3 imagens suas (frame inicial, frame final ou referência de personagem e estilo); vídeo de movimento não (pra copiar coreografia, Seedance). Edita e estende um vídeo SEU: \`sourceVideoId\` (da galeria) ou \`sourceVideoUrl\` (link da casa), mp4 até 10 s, com \`sourceVideoMode\` \`edit\` (o padrão: a mesma cena com a mudança pedida, cobrada pelo tamanho do clipe; é como se troca a pessoa de um vídeo pelo seu personagem, com a ficha dele em \`referenceImageIds\`) ou \`extend\` (o pedaço seguinte, cobrado pelo \`durationSec\`). A proporção sai a do clipe. 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\`.
@@ -409,7 +414,7 @@ Peça que vai virar overlay, sticker, slide ou camada de vídeo nasce recortada:
409
414
 
410
415
  ## Cuidados
411
416
 
412
- - \`generate\` é SÍNCRONA e cobra ao concluir. Modelo pesado (Pro, gpt-image-2-high, Grok quality, Seedream 5.0 Pro, 2K/4K) cai na regra do timeout: cheque \`sapiens_gallery action=list\` antes de repetir, senão cobra duas vezes. O \`seedream-5-0-pro\` foi medido em ~140s, ACIMA do teto de 120s do cliente, então o Timeout nele é o esperado e a imagem está lá.
417
+ - \`generate\` é SÍNCRONA e cobra no disparo. Modelo pesado (Pro, gpt-image-2-high, GPT Image 2.5 Sunburst, Grok quality, Seedream 5.0 Pro, 2K/4K) cai na regra do timeout: leia \`action=status\` antes de repetir, senão cobra duas vezes. Ela lista as gerações recentes da conta, a mais nova primeiro, e é a única leitura que mostra a peça que AINDA está gerando (a galeria só mostra pronta). Ache a sua pelo model, pelo começo do prompt e pelo \`haMinutos\`: \`gerando\` = espere e leia de novo em 1 ou 2 minutos; \`pronta\` = mostre essa; \`falhou\`/\`bloqueada\` = o débito voltou, aí sim gere de novo (bloqueada pede outro prompt ou outro motor); \`presa\` = passou de 15 minutos e o servidor estorna sozinho. O \`seedream-5-0-pro\` foi medido em ~140s, ACIMA do teto de 120s do cliente, então o Timeout nele é o esperado e a imagem chega.
413
418
  - Uma imagem só vira pública (e ganha página indexável) com \`sapiens_gallery action=publish\`.
414
419
 
415
420
  ## Depois de pronta: resolução maior e sombra
@@ -419,7 +424,7 @@ Duas ações da ficha do site saem por aqui, sobre uma imagem SUA já pronta (\`
419
424
  - \`action=upscale\`: a mesma peça em resolução maior. Use quando a pessoa vai imprimir, recortar ou levar pra vídeo em tela grande.
420
425
  - \`action=sombra\`: o mapa de profundidade da foto (colorido, não em cinza), pra usar como referência de pose e volume numa geração seguinte.
421
426
 
422
- As duas cobram Sinapses, preço fixo igual ao da ficha. São síncronas e o upscale pode passar de 2 minutos: Timeout é o cliente desistindo, não o servidor. Olhe \`sapiens_gallery action=list\` antes de repetir, senão cobra duas vezes.
427
+ As duas cobram Sinapses, preço fixo igual ao da ficha. São síncronas e o upscale pode passar de 2 minutos: Timeout é o cliente desistindo, não o servidor. A peça nova não aparece enquanto trabalha: ela entra pronta em até uns 6 minutos, com o prompt começando por "Resolução ampliada:" ou "Sombra da foto:". Leia \`action=status\` antes de repetir, senão cobra duas vezes; passados 6 minutos sem ela, a ação falhou e as Sinapses voltaram.
423
428
 
424
429
  ## De qual saldo sai
425
430
 
@@ -25,6 +25,8 @@ import { convexQuery, convexMutation, convexAction, describeConvexError, getSess
25
25
  * categoria (o que a peça É; queue e edit também a declaram).
26
26
  * - voices: as abas que existem hoje, com a contagem de cada uma.
27
27
  * - status: move a peça de lane (fila, agendado, postado, descartado).
28
+ * Em agendado, volta com `aviso` quando a peça é capítulo de série e o
29
+ * anterior, no mesmo canal, não sai antes dela.
28
30
  * - edit: reescreve a peça que está na fila (copy, título, hashtags,
29
31
  * notas, mídia, língua, comentário). Só manda o que muda. Texto de peça
30
32
  * POSTADA não se reescreve: o post na rede não muda junto.
@@ -173,7 +175,7 @@ const CHANNELS = [
173
175
  * `apps/sapiens/convex/shared/categoriaDaPeca.ts`. O eixo é o ASSUNTO: quem
174
176
  * assina é a aba, a mídia é o canal. "sem" só existe no list (a triagem).
175
177
  */
176
- const CATEGORIAS = ["arte", "personagem", "tecnico", "novidade", "educativo", "mercado"];
178
+ const CATEGORIAS = ["arte", "personagem", "tecnico", "novidade", "educativo", "mercado", "pessoal"];
177
179
  export const distributionSchema = z.object({
178
180
  action: z.enum([
179
181
  "queue",
@@ -271,7 +273,8 @@ export const distributionSchema = z.object({
271
273
  "novidade: o que chegou (motor novo, feature da casa, lançamento).",
272
274
  "educativo: o porquê (aula, artigo, framework, carrossel que explica, quote).",
273
275
  "mercado: o dinheiro e a carreira (cripto, startup, vaga, oportunidade).",
274
- "Quando duas servem, vale a primeira desta ordem: novidade, tecnico, educativo, mercado, personagem, arte (o motor novo testado em páreo é novidade; o páreo com o Batkin no meio é técnico).",
276
+ "pessoal: a própria vida de quem assina (saúde, história, relato em primeira pessoa). Ganha das outras quando o assunto é a vida dele, mesmo que a peça ensine algo de passagem. A régua nunca chuta pessoal: declare.",
277
+ "Fora pessoal, quando duas servem, vale a primeira desta ordem: novidade, tecnico, educativo, mercado, personagem, arte (o motor novo testado em páreo é novidade; o páreo com o Batkin no meio é técnico).",
275
278
  "queue: declare SEMPRE que souber o que a peça é. Ausente, a régua chuta pelo título e pela 1a frase da copy, e a peça cai na gaveta errada ou na triagem; a declarada aparece na gaveta certa da fila sem toque do dono e desce pras filhas da teia.",
276
279
  "edit: troca a categoria (vale em peça já postada) e null devolve pra régua.",
277
280
  "list: filtra pela que vale (a declarada, senão a da régua); 'sem' lista a triagem, o que a régua não sabe ler. Cada item volta com categoria e categoriaDeclarada.",
@@ -454,6 +457,21 @@ function linhaDoJaSaiu(avisos) {
454
457
  const mais = resto.length ? ` e mais ${resto.length}` : "";
455
458
  return `JÁ SAIU no ${a.channel} com a mesma abertura: "${a.title}" (aba ${a.voice ?? "?"}${dia}, itemId ${a.itemId})${mais}. Confira com o dono antes de despachar. Se for repetição, descarte esta.`;
456
459
  }
460
+ /**
461
+ * A linha do "capítulo fora de ordem": a peça marcada é capítulo de série e o
462
+ * anterior, no mesmo canal, não sai antes dela. Aviso, não recusa: a hora fica
463
+ * marcada, mas na hora o tique devolve a peça pra fila em vez de soltar spoiler
464
+ * (17/10/2026, A Vó Roubou a Fila). Servidor anterior a 18/10/2026 não manda o
465
+ * campo, e aí não há linha.
466
+ */
467
+ function linhaDoForaDeOrdem(c) {
468
+ if (!c)
469
+ return null;
470
+ const onde = c.status === "fila" || c.scheduledFor === null
471
+ ? "está na fila sem hora"
472
+ : `está marcado pra ${new Date(c.scheduledFor).toISOString().slice(0, 16).replace("T", " ")} UTC, depois desta`;
473
+ return `FORA DE ORDEM: esta peça é o capítulo ${c.capitulo} e o capítulo ${c.anterior} ("${c.title}", itemId ${c.itemId}) ainda não saiu neste canal: ${onde}. Na hora marcada esta NÃO sai sozinha: volta pra fila com o motivo. Marque o capítulo ${c.anterior} pra antes desta, ou poste ele primeiro, e mostre isto ao dono.`;
474
+ }
457
475
  export async function distribution(args) {
458
476
  const sessionToken = getSessionToken();
459
477
  if ((args.action === "queue" || args.action === "edit") && args.categoria === "sem") {
@@ -613,14 +631,20 @@ export async function distribution(args) {
613
631
  throw new Error("action=status exige itemId.");
614
632
  if (!args.status)
615
633
  throw new Error("action=status exige status.");
616
- await convexMutation("distributionMcp:mcpSetStatus", {
634
+ const r = await convexMutation("distributionMcp:mcpSetStatus", {
617
635
  sessionToken,
618
636
  itemId: args.itemId,
619
637
  status: args.status,
620
638
  postUrl: args.postUrl,
621
639
  scheduledFor: args.scheduledFor,
622
640
  });
623
- return { ok: true, itemId: args.itemId, status: args.status };
641
+ const foraDeOrdem = linhaDoForaDeOrdem(r?.foraDeOrdem);
642
+ return {
643
+ ok: true,
644
+ itemId: args.itemId,
645
+ status: args.status,
646
+ ...(foraDeOrdem ? { aviso: foraDeOrdem, capituloAnterior: r.foraDeOrdem, instruction: foraDeOrdem } : {}),
647
+ };
624
648
  }
625
649
  if (args.action === "bio") {
626
650
  if (!args.channel)
@@ -491,8 +491,10 @@ export async function gallery(args) {
491
491
  includeBase64: args.includeBase64 ?? false,
492
492
  });
493
493
  }
494
- // publish: liga isPublic na própria imagem. Public = entra na galeria
495
- // pública + feed Pinterest (e /imagem/<id> se não for degen). Publicado não
494
+ // publish: liga isPublic na própria peça, imagem ou vídeo (o vídeo desde
495
+ // 20/10/2026, pelo servidor: este pacote só repassa, então versão antiga
496
+ // publica vídeo também). Imagem entra na galeria pública + feed Pinterest (e
497
+ // /imagem/<id> se não for degen); vídeo ganha a /video/<id>. Publicado não
496
498
  // despublica (decisão do dono, 22/08/2026): a action unpublish saiu daqui, e
497
499
  // pacote antigo que ainda mandar isPublic=false toma a recusa do servidor.
498
500
  if (args.action === "publish") {
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { httpUrl } from "../schema.js";
3
- import { convexAction, convexQuery, getSessionToken } from "../convexClient.js";
3
+ import { convexAction, convexQuery, describeConvexError, getSessionToken } from "../convexClient.js";
4
4
  // IDs canônicos do catálogo (apps/sapiens/convex/shared/imageModels.ts).
5
5
  // IDs fora dessa lista caem no fallback e o pricing vira 999. Sempre usar os
6
6
  // IDs canônicos.
@@ -112,8 +112,49 @@ const MAX_REFS_PELO_MCP = 5;
112
112
  function defaultSizeFor(model) {
113
113
  return model && DEFAULT_2K_MODELS.has(model) ? "2K" : undefined;
114
114
  }
115
+ /**
116
+ * Onde conferir quando o generate passa do teto do cliente (o fim da mensagem
117
+ * de Timeout). Antes a frase genérica mandava ler "o status do mesmo tool", que
118
+ * não existia aqui, e as instruções mandavam pra galeria, que só mostra peça
119
+ * pronta: a que ainda gerava sumia, o agente repetia e a conta pagava duas vezes.
120
+ */
121
+ export const ONDE_CONFERIR_GENERATE = "Leia sapiens_image action=status: ela lista as gerações recentes da conta com o estado de cada uma, inclusive a que ainda está gerando (a galeria só mostra peça pronta). gerando = ainda no servidor, volte em 1 ou 2 minutos; pronta = a peça está no acervo, mostre essa; falhou = o débito voltou, e só aí gere de novo.";
122
+ /**
123
+ * Upscale e sombra não abrem row antes de terminar: a peça nova nasce pronta,
124
+ * então durante o trabalho não há nada pra ver. Os prazos somam os tetos de
125
+ * imageUpscale.ts e depthFoto.ts (pedido, poll, download).
126
+ */
127
+ export const ONDE_CONFERIR_UPSCALE_SOMBRA = "A peça nova só aparece quando fica pronta, em até uns 6 minutos: leia sapiens_image action=status (ou sapiens_gallery action=list), onde ela entra pronta ao lado da original, com o prompt começando por 'Resolução ampliada:' (upscale) ou 'Sombra da foto:' (sombra). Passados 6 minutos sem ela, a ação falhou e as Sinapses voltaram: só aí repita.";
128
+ /**
129
+ * Gerando há mais que isto = presa. A régua é a da varredura do servidor
130
+ * (loadingAindaVale, LOADING_SEM_JOB_MS): 15 minutos contados do maior entre a
131
+ * criação e o claim do render, senão a row do site que o MCP renderizou depois
132
+ * viraria "presa" aqui com o render pago ainda vivo lá.
133
+ */
134
+ const PRESA_MS = 15 * 60 * 1000;
135
+ const LEITURA_STATUS = "As gerações de imagem mais recentes da conta, a mais nova primeiro. As que estão gerando vêm todas; o resto vem cortado. gerando: o servidor ainda está nela e ela JÁ cobrou; NÃO gere de novo, leia de novo em 1 ou 2 minutos. pronta: está no acervo (imageId, url, acervoUrl): mostre essa em vez de gerar outra. falhou: não virou peça e o que saiu em Sinapses volta sozinho; pode gerar de novo. bloqueada: o motor recusou o conteúdo e o que saiu em Sinapses volta sozinho; mude o prompt ou o motor antes de tentar de novo. presa: gerando há mais de 15 minutos, não termina mais; a varredura do servidor marca como falha e devolve as Sinapses, então pode gerar de novo. Pra achar a peça de um Timeout, case pelo model, pelo começo do prompt e pelo haMinutos. Upscale e sombra só aparecem quando ficam prontos.";
136
+ /**
137
+ * A leitura do action=status: o servidor devolve o estado cru e as horas da
138
+ * row (sem relógio nele), e a idade e o "presa" saem daqui.
139
+ */
140
+ export function lerGeracoesRecentes(items, agora, truncado = false) {
141
+ const lidas = items.map((i) => {
142
+ const idadeMs = Math.max(0, agora - Number(i.createdAt));
143
+ const desde = Math.max(Number(i.createdAt), Number(i.renderClaimedAt ?? 0));
144
+ const presa = i.estado === "gerando" && agora - desde >= PRESA_MS;
145
+ return { ...i, estado: presa ? "presa" : i.estado, haMinutos: Math.floor(idadeMs / 60000) };
146
+ });
147
+ return {
148
+ gerando: lidas.filter((i) => i.estado === "gerando").length,
149
+ count: lidas.length,
150
+ items: lidas,
151
+ // A leitura parou no teto de varredura: geração mais antiga que isso não entrou.
152
+ ...(truncado ? { truncado: true } : {}),
153
+ leitura: LEITURA_STATUS,
154
+ };
155
+ }
115
156
  export const imageSchema = z.object({
116
- action: z.enum(["generate", "request_generation", "compose", "models", "upscale", "sombra"]),
157
+ action: z.enum(["generate", "request_generation", "compose", "models", "upscale", "sombra", "status"]),
117
158
  prompt: z
118
159
  .string()
119
160
  .optional()
@@ -323,6 +364,21 @@ export async function image(args) {
323
364
  throw new Error("request_generation saiu de linha e não cobrou nada. Imagem: action=generate (gera e cobra num call só). Vídeo: sapiens_video action=create (cria a row de vídeo e renderiza).");
324
365
  }
325
366
  const sessionToken = getSessionToken();
367
+ // status: a leitura depois de um Timeout. Somente leitura, sem custo. Mostra
368
+ // a peça que AINDA está gerando, que a galeria não mostra.
369
+ if (args.action === "status") {
370
+ let r;
371
+ try {
372
+ r = await convexQuery("imagemRecentes:mcpGeracoesRecentes", { sessionToken });
373
+ }
374
+ catch (e) {
375
+ // Pacote na frente do deploy: o servidor ainda não tem a leitura.
376
+ if (!/Could not find public function/i.test(describeConvexError(e)))
377
+ throw e;
378
+ throw new Error("action=status ainda não chegou no servidor. Enquanto isso, sapiens_gallery action=list mostra só a peça PRONTA: a que ainda está gerando não aparece lá. Depois de um Timeout, espere uns minutos e olhe a galeria antes de gerar de novo.");
379
+ }
380
+ return lerGeracoesRecentes(r?.items ?? [], Date.now(), r?.truncado === true);
381
+ }
326
382
  // v1.8: compose tem args próprios, validação separada
327
383
  // Ações da ficha do site sobre uma imagem SUA pronta: a peça nova entra no
328
384
  // acervo como versão, e a de origem fica intacta. Síncronas e com custo fixo;
@@ -332,7 +388,7 @@ export async function image(args) {
332
388
  throw new Error(`action=${args.action} exige sourceImageId (uma imagem SUA pronta; ache em sapiens_gallery action=list).`);
333
389
  }
334
390
  const fn = args.action === "upscale" ? "imageUpscale:aumentarResolucao" : "depthFoto:extrairSombraDaFoto";
335
- return await convexAction(fn, { imageId: args.sourceImageId, sessionToken });
391
+ return await convexAction(fn, { imageId: args.sourceImageId, sessionToken }, { ondeConferir: ONDE_CONFERIR_UPSCALE_SOMBRA });
336
392
  }
337
393
  if (args.action === "compose") {
338
394
  if (!args.instruction || args.instruction.trim().length < 5) {
@@ -413,7 +469,7 @@ export async function image(args) {
413
469
  ...(args.maskRegions ? { maskRegions: args.maskRegions } : {}),
414
470
  ...(args.pagarCom === "dolar" ? { pagarCom: "dolar" } : {}),
415
471
  ...(args.transparentBackground === true ? { transparentBackground: true } : {}),
416
- });
472
+ }, { ondeConferir: ONDE_CONFERIR_GENERATE });
417
473
  // Backend de antes do campo não devolve motor nem ficha: cai no id pedido e
418
474
  // monta a ficha aqui. O nome bonito (modelName) só vem do servidor.
419
475
  const model = result?.model ?? genModel;
@@ -150,6 +150,11 @@ import { httpUrl } from "../schema.js";
150
150
  * final (role 'end'), 5/8/10s em 480/720/1080p. Sem imagem de
151
151
  * referência (o reference-to-video do provider é outro endpoint,
152
152
  * fora até o roteador saber escolher).
153
+ * - sapiens-video-flux-3-max FLUX 3 Max (fal + Black Forest Labs): texto OU imagem (t2v/i2v),
154
+ * 5 a 20s em 720p ou 1080p, som nativo com interruptor, frame final
155
+ * (role 'end', só junto do 'start'). Segue o prompt de perto e
156
+ * volta rápido. Sem referência de personagem nem vídeo de
157
+ * movimento: o servidor recusa e estorna.
153
158
  * - sapiens-video-kling-motion Kling Motion — transfere o movimento de um vídeo pra uma imagem
154
159
  * (PRECISA de pessoa com tronco visível na imagem E no vídeo;
155
160
  * vídeo de referência MÁX 10s — o provider recusa acima disso —
@@ -210,6 +215,7 @@ const VIDEO_MODELS = [
210
215
  "sapiens-video-ltx-spicy",
211
216
  "sapiens-video-wan",
212
217
  "sapiens-video-wan-3",
218
+ "sapiens-video-flux-3-max",
213
219
  "sapiens-video-kling-motion",
214
220
  "sapiens-video-shot-mimic",
215
221
  // Os três Veo 3.1 e o Omni 1.0 seguem no enum por retrocompat (cliente em
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapiens-mcp",
3
- "version": "1.102.1",
3
+ "version": "1.103.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. mcprush.com-bd2545268b8471cdb213c674",
6
6
  "type": "module",