sapiens-mcp 1.82.2 → 1.85.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 +10 -3
- package/dist/skills.js +43 -1
- package/dist/tools/carrossel.js +189 -0
- package/dist/tools/character.js +12 -2
- package/dist/tools/gallery.js +41 -2
- package/dist/tools/image.js +3 -2
- package/dist/tools/meta.js +8 -4
- package/dist/tools/pipeline.js +3 -3
- package/dist/tools/studios.js +3 -3
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ZodError } from "zod";
|
|
2
2
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
3
|
import { pipeline, pipelineSchema } from "./tools/pipeline.js";
|
|
4
|
+
import { carrossel, carrosselSchema } from "./tools/carrossel.js";
|
|
4
5
|
import { image, imageSchema } from "./tools/image.js";
|
|
5
6
|
import { meta, metaSchema } from "./tools/meta.js";
|
|
6
7
|
import { repertorio, repertorioSchema } from "./tools/repertorio.js";
|
|
@@ -58,10 +59,15 @@ import { skillMenuLine } from "./skills.js";
|
|
|
58
59
|
*/
|
|
59
60
|
export const TOOLS = {
|
|
60
61
|
sapiens_pipeline: {
|
|
61
|
-
description: "CRUD do content pipeline Sapiens (sources/productions/publishables). Sub-actions: list_sources, list_articles (use includeDrafts pra incluir drafts; onlyAvailable pra esconder os já virados em source), get_source, get_production, list_versions, add_article_as_source, create_draft_article_and_source (seed), create_production (sourceId+format → productionId draft), update_production (substitui payload, opcionalmente muda status), finalize_production (cria publishable v1, v2... com snapshot), remove_production, remove_source, set_source_done, update_source_notes, restore_version (volta payload duma versão antiga), set_publishable_title (renomeia um publishable), backfill_via (rotula em lote o campo 'via' das productions antigas; dryRun=true só lista), propose_mega_grafico_plan (granular: só gera plano via Gemini, devolve fullPrompt+spec), run_mega_grafico_full (ONE-SHOT, recomendado: cria production+propõe plano+gera imagem+aplica selo Sapiens+finaliza publishable numa chamada só), generate_carousel (gera um carrossel
|
|
62
|
+
description: "CRUD do content pipeline Sapiens (sources/productions/publishables). Sub-actions: list_sources, list_articles (use includeDrafts pra incluir drafts; onlyAvailable pra esconder os já virados em source), get_source, get_production, list_versions, add_article_as_source, create_draft_article_and_source (seed), create_production (sourceId+format → productionId draft), update_production (substitui payload, opcionalmente muda status), finalize_production (cria publishable v1, v2... com snapshot), remove_production, remove_source, set_source_done, update_source_notes, restore_version (volta payload duma versão antiga), set_publishable_title (renomeia um publishable), backfill_via (rotula em lote o campo 'via' das productions antigas; dryRun=true só lista), propose_mega_grafico_plan (granular: só gera plano via Gemini, devolve fullPrompt+spec), run_mega_grafico_full (ONE-SHOT, recomendado: cria production+propõe plano+gera imagem+aplica selo Sapiens+finaliza publishable numa chamada só), generate_carousel (gera um carrossel standalone a partir de brief OU articleId, com imagens do banco; devolve id + url do editor pro humano abrir, ajustar e exportar; cobra Sinapses, reembolsa se falhar; model é a FORMA: 'feed' (padrão), 'reflexao', 'case' ou 'editorial' (a IA escolhe os layouts); aspect é o TAMANHO da folha: '4:5' (padrão, o feed mostra inteira) ou '9:16' (tela cheia); dá pra trocar os dois depois no editor. O membro faz o mesmo pela sapiens_carrossel). generate_carousel_production (o IRMÃO PIPELINE do generate_carousel: recebe um sourceId de artigo, CRIA a production carrossel_ig e a preenche pelo MESMO motor da casa, já no shape editorial (templateId+slots) que o editor de pipeline renderiza — prefira ESTE a create_production+payload cru pro carrossel, que abre VAZIO no editor; devolve productionId + url do editor de pipeline; admin-only, cobra Sinapses, reembolsa se falhar; model opcional trava a folha registrada; beats opcional entrega copy PRONTO por beat da espinha, [{n, slots}], quando o agente JÁ escreveu e validou os blocos: com beats o Gemini de escrita NÃO roda e a rodada cobra só o picker de imagens, zero com autoPickImages=false; caption opcional vira a legenda do meta). CARROSSEL FINO (edição sem tela, admin-only): list_carousels (seus carrosséis standalone), get_carousel (payload completo + catálogo de templates com slots/limites + paletas + o formato da peça e os válidos — tudo pra VOCÊ escrever os slides), update_carousel (payload inteiro de volta, normalizado no servidor; preserve os campos image dos slides que não mexeu E o theme inteiro, com a folha (theme.sheet) e a assinatura (theme.signature): o que faltar volta pro padrão), carousel_auto_images (IA escolhe imagens do banco pros slides de foto, 60 Sinapses; aceita carouselId standalone OU productionId de carrossel da pipeline; makeVisual=true converte slides de texto pra layouts de foto antes — ritmo visual; generateMissing=true gera imagem nova pros que o banco não cobrir, ~450 Sinapses cada, até 4, avise o custo antes), carousel_generate_image (imagem nova pra UM slide, ~450 Sinapses, customPrompt opcional), capa_ia (A CAPA SEAMLESS: gera uma imagem 16:9 contínua com o TEXTO QUEIMADO dentro dela e o elemento vivo cruzando as letras, fatia em duas peças 3:4 no servidor e, com carouselId, já põe as duas na frente do carrossel. É a capa mais bonita da casa e a única em que o sujeito passa na frente e atrás do título, porque o texto é parte da imagem, não overlay. Args: capaHeadline (obrigatório), capaSubline, capaRightText (cai no 2º slide), capaElement e capaVibe (omitidos, a IA escolhe pela pauta), capaImageModel. O MOTOR é a decisão que mais muda o resultado, porque capa é tipografia: gpt-image-2-high (default, 1200, o único da casa que entrega letra pequena legível, sai em 1536x1024) contra nano-banana-max (900, cena mais fiel e 2K de verdade, letra erra mais). Cobra pelo catálogo, no motor que rodou, e a peça entra na sua galeria como qualquer geração. Depois de gerada, ANIMAR a capa (o elemento deriva e o texto fica congelado) é ato do editor, não do agente). Fluxo confortável (standalone): generate_carousel → get_carousel → update_carousel (afia os textos) → carousel_auto_images → humano abre a url pra exportar. Fluxo pipeline (carrossel atrelado a um artigo/source): generate_carousel_production (sourceId) → humano abre a url do editor de pipeline pra revisar e finalizar (finalize_production). Fluxo pipeline com copy do agente (a skill escreveu os blocos): generate_carousel_production (sourceId + model + beats) → carousel_auto_images (productionId) se faltar foto → humano revisa e finaliza. Pra mega_grafico, SEMPRE prefira run_mega_grafico_full em vez de sequenciar manualmente (menos drift). Idempotente só na production (passa productionId pra reusar a MESMA row), mas cada run RE-GERA a imagem e cobra de novo (~900 Sinapses): não é grátis re-rodar. OBRIGATÓRIO perguntar ao user antes se withHelen=true (cartoon Helen interage com tema, ~15-25% do poster) ou false (poster 100% diagramático). Custo ~900-1000 sinapses por geração. run_mega_grafico_full, generate_carousel, generate_carousel_production, carousel_auto_images (com generateMissing) e carousel_generate_image são SÍNCRONAS e pesadas: vale a REGRA DO TIMEOUT (podem cobrar mesmo voltando 'Timeout'; cheque get_carousel/dashboard antes de repetir). Use skipFinalize=true se quiser deixar production em 'ready' pro admin revisar antes de publishable. Payload livre por formato — chame sapiens_meta action=formats pra ver schemas sugeridos.",
|
|
62
63
|
schema: pipelineSchema,
|
|
63
64
|
handler: pipeline,
|
|
64
65
|
},
|
|
66
|
+
sapiens_carrossel: {
|
|
67
|
+
description: "O CARROSSEL do Instagram da pessoa, pelo agente (qualquer conta logada, só os carrosséis DELA). Puxe a skill 'carrossel' antes. Sub-actions: generate (gera do zero a partir de UMA fonte: brief, articleId de artigo publicado ou userArticleId de artigo dela; 350 Sinapses já com a escolha de fotos, estorna se falhar; model é a FORMA: feed (padrão, 9 slides), reflexao, case ou editorial; aspect é o TAMANHO: 4:5 (padrão, a folha que o feed mostra inteira) ou 9:16; devolve id + url do editor), list (os carrosséis dela, com id, título, nº de slides e url), get (payload inteiro + catálogo de layouts com os slots e limites de cada um, paletas, folhas e a assinatura: tudo pra VOCÊ escrever os slides), update (payload INTEIRO de volta, normalizado no servidor: mande o theme inteiro, com folha e assinatura, e o image de todo slide que não mexeu, senão volta pro padrão e a foto some), auto_images (a IA escolhe fotos do banco pros slides, 60 Sinapses, estorna se não tiver o que preencher; makeVisual converte slides de texto em layout de foto antes; generateMissing gera foto nova pros que o banco não cobrir, até 4, ~450 Sinapses cada, avise o custo antes), generate_image (foto nova pra UM slide, ~450 Sinapses, customPrompt opcional), set_image (põe no slide uma peça da pessoa ou pública pelo ID citável img_…, sem custo; é como ela usa as PRÓPRIAS fotos), cover (a Capa IA: capa 16:9 com a manchete QUEIMADA na imagem e um elemento vivo cruzando as letras; com carouselId fatia em duas e põe na frente do carrossel no lugar da capa IA anterior; cobra pelo motor da capa, confirme o custo antes). A ASSINATURA (theme.signature: o nome no topo, a marca no canto e o @ do fecho) nasce da marca da pessoa, ou do nome dela quando não tem marca; o @ é o dela no Instagram, não invente. O carrossel vai até 15 slides. generate, auto_images com generateMissing, generate_image e cover são SÍNCRONAS e pesadas: vale a REGRA DO TIMEOUT (confira em action=list antes de repetir). Baixar o arquivo é no editor (a url): aqui sai a receita pronta. O carrossel atrelado a uma jogada do Workflow segue pela sapiens_pipeline.",
|
|
68
|
+
schema: carrosselSchema,
|
|
69
|
+
handler: carrossel,
|
|
70
|
+
},
|
|
65
71
|
sapiens_image: {
|
|
66
72
|
description: "Operações de imagem via Sapiens (Gemini, GPT Image 2 e 2.5, Grok, Seedream/ByteDance). Sub-actions: 'generate' (gera imagem completa imediato — prompt+model+aspectRatio+size; suporta mode=edit/variation e MULTI-REFERÊNCIA: combine até 4 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); refs valem pros modelos robustos nano-banana-2/gpt-image-2-*/grok-2-image*/seedream-*), '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) 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. 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).",
|
|
67
73
|
schema: imageSchema,
|
|
@@ -83,7 +89,7 @@ export const TOOLS = {
|
|
|
83
89
|
handler: repertorio,
|
|
84
90
|
},
|
|
85
91
|
sapiens_gallery: {
|
|
86
|
-
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). 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.",
|
|
92
|
+
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). 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.",
|
|
87
93
|
schema: gallerySchema,
|
|
88
94
|
handler: gallery,
|
|
89
95
|
},
|
|
@@ -158,7 +164,7 @@ export const TOOLS = {
|
|
|
158
164
|
handler: brand,
|
|
159
165
|
},
|
|
160
166
|
sapiens_character: {
|
|
161
|
-
description: "Personagens (character sheets) do Sapiens — a tabela `influencers`: personagem reutilizável com imagens (pra character-lock em geração) + alma (systemPrompt), tudo amarrado à conta do dono do token (sem admin). Sub-actions: list_public (catálogo global de personagens públicos do Explorar; cada um traz mainImageUrl/imageUrls usáveis direto como referenceImageUrls em sapiens_image; sem custo, sem login), get (detalhe de 1 por characterId — público+ativo qualquer um vê, draft/privado só o dono; systemPrompt só volta pro dono), list_mine (os personagens do próprio user, inclui drafts/privados), create (cria rascunho na conta: name + gender + opcional form/title/systemPrompt), add_image (adiciona imagem ao próprio personagem via imageUrl público OU sourceImageId da galeria; 1ª vira principal), set_card (edita alma/título/lema em inglês/nome/nome por extenso/forma do próprio), set_presence (escreve onde o personagem existe FORA da casa: redes sociais por handle, Fanvue, site e o email dele, este último privado), set_passport (escreve o PASSAPORTE dele: como ACERTAR este ser, que é outra coisa de quem ele é. Guarda o `descriptor` de geração em inglês pra colar verbatim, o `negative` travado que fica sempre ligado, os `locks` (o que TRAVA nele, um por entrada, que é a lista que vira as perguntas da conferência), as `refs` por PAPEL (proporção, rosto, tatuagem: ref sem papel ninguém sabe usar), as `recipes` medidas por tipo de peça (com o prompt VERBATIM, porque o valor está na palavra exata que funcionou) e o `discarded`, o que já foi recusado. Esse último não é enfeite: o motor traz de volta o que ninguém proibiu, então ideia descartada sem negativo escrito volta sozinha na leva seguinte. É MERGE por campo, então mandar só o negative não apaga o descritor, e campo vazio apaga. Só o DONO lê: receita de produção não sai em personagem público. Em action=get ele volta em duas formas, `passport` (campo a campo, o que se reedita) e `passportPrompt` (o bloco já montado pra colar). Preencha sempre que uma rodada medir algo que a próxima não deve redescobrir: é o que faz a receita viajar pra fora do repo), activate (tira do rascunho e libera o personagem pra USAR nas gerações do dono; exige ≥1 imagem. NÃO torna público: quem publica é set_visibility, e ativar é gesto reversível e privado), set_visibility (isPublic true=Explorar+slug / false=privado), set_hidden (hidden true tira o personagem da TELA do dono: some da lista de personagens e as peças geradas com ele saem da galeria de fotos, vídeos e rascunhos do dono, voltando pelo filtro Ocultos; hidden false devolve. É o gesto de quem vai compartilhar tela. Não despublica, não apaga, não sai dos seletores de geração, e personagem oculto não publica até ser mostrado. Grátis. O list_mine traz `hidden` em cada personagem). GESTÃO de imagem (por url, pegue as urls atuais em action=get campo imageUrls): remove_image (tira uma), set_main_image (define a principal), reorder_images (nova ordem via orderedUrls, posição 0=principal), e delete (apaga o personagem, permanente). FORMA (`form`, o que tipo de CORPO ele tem: human default, humanoid, animal (bicho real), creature (ser inventado), object, abstract): não é enfeite de cadastro, é o que a ficha, as figurinhas e o vídeo leem pra decidir se descrevem rosto e mãos ou silhueta e postura, e é ele que impede uma criatura de voltar desenhada como pessoa. Mande no create sempre que o personagem não for gente; personagem que já existe sem ele conserta com set_card form=creature. Ausente = human, que é o que a casa desenhava antes do campo existir. NOME E NOME POR EXTENSO (`name` e `fullName`): `name` é como o personagem é CHAMADO e é o que toda tela desenha; `fullName` é o nome inteiro, pra quem tem apelido ('Crow Girl' na tela, 'Kaia Crowe' por extenso). Um não substitui o outro, e o extenso não mexe no slug da página nem no cartão de nome do vídeo: batizar personagem que já existe não muda endereço publicado nem assinatura de peça que já saiu. Vem em action=get e list_mine no campo `fullName` (null = ainda sem nome por extenso). TRAÇO (`style`, em que TÉCNICA ele é feito: auto default, realista, anime, manhwa, 3d, custom): irmão da forma, e a divisão é limpa, a forma diz que CORPO é esse e o traço diz como ele é DESENHADO. As mesmas três peças leem daqui. No 'auto' a peça não afirma técnica nenhuma e as imagens de referência mandam; 'realista' é fotografia, 'anime' é cel shading com contorno de tinta, 'manhwa' é pintura de webtoon, '3d' é render com material e oclusão, 'custom' usa a linha escrita em `styleNote` (até 140 caracteres, ex: aquarela sobre papel texturizado). Mande sempre que o personagem tiver técnica definida: até ago/2026 a ficha cravava vocabulário de desenho e devolvia personagem fotográfico virado em ilustração. Conserto sem custo em quem já existe: set_card style=realista. PRESENÇA (set_presence, de graça): o ENDEREÇO do personagem, o que faltava pra ele existir fora da ficha. `socials` é {rede: handle} nas redes instagram, tiktok, youtube, x, threads, bluesky, twitch, spotify, fanvue, patreon, onlyfans, telegram; `websiteUrl` é o site dele e `email` é o email do personagem, o que cadastra e recupera as contas dele nas redes. As redes e o site são PÚBLICOS; o email é PRIVADO e fica só com o dono, mesmo com o personagem publicado, porque email é chave de conta e isca de spam, não canal de contato. Em action=get e list_public de personagem de OUTRA pessoa, o campo simplesmente não vem. É MERGE: mandar {fanvue:'helen'} não apaga o instagram, e pra apagar uma rede se manda ela vazia. O que volta em action=get são as duas formas, `presence` (o handle cru, que é o que se reedita) e `presenceLinks` (o link já montado, pra mostrar sem remontar URL na mão). Vale a pena preencher quando o personagem TEM conta de verdade: é o que separa uma ficha de um ser com endereço, e a página pública dele desenha as redes e o site (nunca o email). FICHA (generate_sheet, COBRA 450 Sinapses): desenha a página-pôster do personagem no traço das imagens que ele já tem (exige pelo menos uma), em duas orientações (arg `orientation`): 'portrait' (default) é a página de processo, pose, expressões, trocas de roupa e adereços soltos na folha; 'landscape' é a prancha larga, com a volta completa à esquerda, a figura grande no meio, poses à direita, estudos de silhueta, expressão e detalhe embaixo e um painel CHARACTER ID na ponta. A personalidade sai da alma (systemPrompt) e é ela que escolhe roupa e objeto, então personagem com alma escrita rende ficha melhor. Cada geração é um estilo NOVO e elas acumulam no personagem (campo sheetUrls em action=get), nenhuma apaga a anterior, e a ficha já entra na galeria dele como referência das próximas gerações. É geração síncrona: se voltar Timeout, cheque action=get antes de repetir, senão cobra duas vezes. STICKERS (generate_stickers, COBRA 550 Sinapses): desenha 5 stickers do personagem DE UMA VEZ. Uma folha só, em 2K, com as cinco figuras separadas sobre um fundo verde chroma, recortada por código em peças 512x512 transparentes abaixo de 100KB (o teto do WhatsApp). É por isso que sai o preço de UMA imagem em 2K e não de cinco: quem paga é a folha. As peças entram no pack do personagem (um por personagem, os lotes acumulam) e já ficam no picker de expressão do dono, no chat e no Fórum. Arg `moods`: até 5 humores do vocabulário comum por slug (kkkkk, amei, isso, hmm, chega, que, aff, bora, socorro, seinao, valeu, ainao, seila, ideia, calma, contatudo, perfeito, euavisei, naovourir, zzz, somaisum, sextou, merecido, quedia, tudobem); faltando, a casa completa com os mais usados. Arg `hint`: direcionamento curto do autor (roupa, adereço, clima), até 140 caracteres. Arg `stickerTier`: 'folha' (default) é esse lote de cinco, desenhado no Gemini 3.1 Flash; 'unica' (COBRA 900 Sinapses) desenha UM sticker por vez no Gemini 3 Pro, o motor mais fiel da casa, com a figura sozinha no quadro e o dobro de pixel por peça, e leva só o PRIMEIRO mood da lista. Pra encher o pack, folha; pra traço difícil ou a reação que vira a cara do personagem, a unica. Ao oferecer a escolha, diga o NOME DO MOTOR e o que ele troca: adjetivo vago de acabamento não informa nada a quem vai pagar. Os dois caem no MESMO pack e acumulam. Sem legenda queimada na imagem, de propósito: modelo erra acento em português, então o rótulo fica na row e serve de busca no picker. Exige pelo menos uma imagem no personagem (é dela que sai a cara) e é geração síncrona: se voltar Timeout, cheque sapiens_gallery antes de repetir. Quando a resposta vem com ok=false, a folha foi gerada e paga mas o corte falhou; ela está na galeria e o recorte de novo é de graça, pela web. Publicar o pack na vitrine e o carimbo da casa (que é o que põe no picker de todo mundo) são gestos da web, não desta tool. PLACAS (generate_plates, COBRA 550 Sinapses): seis ângulos do mesmo rosto numa geração só, no Gemini 3.1 Flash em 2K, recortados por código em seis referências com PAPEL: perfil, camera-alta, camera-baixa, frontal, cabeca-baixa e outro-lado, cada um com uma expressão diferente. Não é vitrine (isso é a ficha): é a referência feita pra máquina. Referência trava o ângulo da câmera, então quando a cena pede perfil, passe a placa de perfil em referenceImageUrls. As placas ficam FORA de imageUrls de propósito, porque placa de perfil como referência genérica puxa toda peça pro perfil; elas voltam em action=get no campo `plates` ([{role, url}]). As placas ACUMULAM: cada geração soma seis, e a que não serve sai com remove_image. Em `plates` o lote mais novo vem primeiro, cada lote na ordem da grade, então a primeira placa de um papel é a mais nova. Sai das fotos do personagem (exige pelo menos uma) e, quando ele tem passaporte, o descritor dele entra no pedido. Só personagem com rosto de gente (form human ou humanoid): pra bicho, criatura, objeto ou forma abstrata o servidor recusa antes de cobrar. O perfil puro e a câmera alta às vezes voltam amolecidos pro frontal; quando esses dois ângulos importarem, confira as placas antes de usar. Geração síncrona: se voltar Timeout, cheque action=get antes de repetir. Resposta com ok=false quer dizer grade gerada e paga com o corte falho; o recorte de novo é de graça, pela web. CHARACTER VIDEO (a ficha que anda): o personagem atravessa 6 mundos em 12s, trocando de roupa em cada um, com som gerado junto, e o último plano fecha a peça com ele parando e encarando a câmera. A peça volta FECHADA pelas duas portas (tela e agente), sem ninguém pedir: o personagem se apresenta no cartão de nome por cima do fim do último plano, com o LEMA em inglês embaixo (o campo `titleEn`, escrito uma vez em set_card), e só depois a casa assina. Quem não tem lema recebe o subtítulo que o roteiro inventou naquele take, e ele muda no take seguinte. O fecho é asset, não geração: zero Sinapse a mais, e é fail-open, então a resposta traz `closed` e `nameCard` dizendo o que entrou de verdade em vez de prometer um cartão que não está no arquivo. Pra colocar esse cartão num vídeo que JÁ existe, o caminho é a ficha do take na web (gaveta do fecho, 'Apresentação do personagem'), também sem custo. Exige FICHA gerada (é dela que saem a cara e o guarda-roupa), não só imagem. Duas actions, nesta ordem: plan_video (COBRA 50 Sinapses) devolve os 6 planos que a alma do personagem escolheu, com ambiente, ato, enquadramento e roupa. Cada plano vem nas duas línguas: em inglês (setting/act/wardrobe, que é o que vai pro motor) e em português (settingPt/actPt/wardrobePt). MOSTRE a versão em português pro autor, o público da casa é brasileiro e roteiro que ele lê de través não é roteiro aprovado; peça de novo quantas vezes ele quiser, porque trocar sai por 50 e o take errado sai por milhares. replan_shot (COBRA 15 Sinapses) reescreve UM plano e não toca nos outros cinco: os seis são cenas independentes, então quando o autor gosta de quatro e implica com um, troque só aquele em vez de sortear tudo de novo (mande os 6 planos em `shots`, o número em `shotIndex`, e o que ele quer diferente em `shotHint`; volta só o plano trocado, e é você que remonta o roteiro). Depois generate_video (COBRA) renderiza, com os planos aprovados no arg `shots` e o MOTOR no arg `videoTier`: 'draft' (5.400 Sinapses) é o Seedance 2.0 Mini, metade do preço, que tropeça em mão, pouca luz e câmera rápida, e 'final' (8.640 Sinapses) é o Seedance 2.0 Fast, que segura o que o Mini erra. A peça é a MESMA nos dois (mesmos 6 planos, 12s, 720p, com som), então ofereça pelo nome do motor e pelo que ele troca, nunca por adjetivo vago de acabamento. Vertical ou horizontal pelo arg `orientation`. Chamar generate_video SEM `shots` funciona, mas escreve um roteiro novo às cegas e cobra igual: não faça isso sem o autor ter visto o que vai receber. É geração demorada: se voltar Timeout, cheque sapiens_gallery antes de repetir. Resposta com `pending: true` (sem `url`) quer dizer ACEITO E COBRADO: o servidor continua renderizando sozinho (até 25 min) e a peça chega na ficha já fechada; NÃO repita a chamada, isso cobraria de novo, confira depois em sapiens_gallery. Fluxo de criação: create → add_image (1+) → set_card (opcional) → activate. PARE AÍ. O personagem nasce e continua PRIVADO, e é assim que ele serve pro dono: dá pra gerar, referenciar e iterar sem ninguém ver. set_visibility isPublic=true é o gesto de PUBLICAR no Explorar, com slug público, e nÃO é passo de fluxo: só chame quando o dono pedir pra publicar aquele personagem, com essas palavras. Na dúvida, não publique e pergunte. Pra usar um personagem público como referência numa geração, pegue mainImageUrl em list_public/get e passe em sapiens_image referenceImageUrls.",
|
|
167
|
+
description: "Personagens (character sheets) do Sapiens — a tabela `influencers`: personagem reutilizável com imagens (pra character-lock em geração) + alma (systemPrompt), tudo amarrado à conta do dono do token (sem admin). Sub-actions: list_public (catálogo global de personagens públicos do Explorar; cada um traz mainImageUrl/imageUrls usáveis direto como referenceImageUrls em sapiens_image; sem custo, sem login), get (detalhe de 1 por characterId — público+ativo qualquer um vê, draft/privado só o dono; systemPrompt só volta pro dono), list_mine (os personagens do próprio user, inclui drafts/privados), create (cria rascunho na conta: name + gender + opcional form/title/systemPrompt), add_image (adiciona imagem ao próprio personagem via imageUrl público OU sourceImageId da galeria; 1ª vira principal), set_card (edita alma/título/lema em inglês/nome/nome por extenso/forma do próprio), set_presence (escreve onde o personagem existe FORA da casa: redes sociais por handle, Fanvue, site e o email dele, este último privado), set_passport (escreve o PASSAPORTE dele: como ACERTAR este ser, que é outra coisa de quem ele é. Guarda o `descriptor` de geração em inglês pra colar verbatim, o `negative` travado que fica sempre ligado, os `locks` (o que TRAVA nele, um por entrada, que é a lista que vira as perguntas da conferência), as `refs` por PAPEL (proporção, rosto, tatuagem: ref sem papel ninguém sabe usar), as `recipes` medidas por tipo de peça (com o prompt VERBATIM, porque o valor está na palavra exata que funcionou) e o `discarded`, o que já foi recusado. Esse último não é enfeite: o motor traz de volta o que ninguém proibiu, então ideia descartada sem negativo escrito volta sozinha na leva seguinte. É MERGE por campo, então mandar só o negative não apaga o descritor, e campo vazio apaga. Só o DONO lê: receita de produção não sai em personagem público. Em action=get ele volta em duas formas, `passport` (campo a campo, o que se reedita) e `passportPrompt` (o bloco já montado pra colar). Preencha sempre que uma rodada medir algo que a próxima não deve redescobrir: é o que faz a receita viajar pra fora do repo), activate (tira do rascunho e libera o personagem pra USAR nas gerações do dono; exige ≥1 imagem. NÃO torna público: quem publica é set_visibility, e ativar é gesto reversível e privado), set_visibility (isPublic true=Explorar+slug / false=privado), set_hidden (hidden true tira o personagem da TELA do dono: some da lista de personagens e as peças geradas com ele saem da galeria de fotos, vídeos e rascunhos do dono, voltando pelo filtro Ocultos; hidden false devolve. É o gesto de quem vai compartilhar tela. Não despublica, não apaga, não sai dos seletores de geração, e personagem oculto não publica até ser mostrado. Grátis. O list_mine traz `hidden` em cada personagem). GESTÃO de imagem (por url, pegue as urls atuais em action=get campo imageUrls): remove_image (tira uma), set_main_image (define a principal), reorder_images (nova ordem via orderedUrls, posição 0=principal), e delete (apaga o personagem, permanente). FORMA (`form`, o que tipo de CORPO ele tem: human default, humanoid, animal (bicho real), creature (ser inventado), object, abstract): não é enfeite de cadastro, é o que a ficha, as figurinhas e o vídeo leem pra decidir se descrevem rosto e mãos ou silhueta e postura, e é ele que impede uma criatura de voltar desenhada como pessoa. Mande no create sempre que o personagem não for gente; personagem que já existe sem ele conserta com set_card form=creature. Ausente = human, que é o que a casa desenhava antes do campo existir. NOME E NOME POR EXTENSO (`name` e `fullName`): `name` é como o personagem é CHAMADO e é o que toda tela desenha; `fullName` é o nome inteiro, pra quem tem apelido ('Crow Girl' na tela, 'Kaia Crowe' por extenso). Um não substitui o outro, e o extenso não mexe no slug da página nem no cartão de nome do vídeo: batizar personagem que já existe não muda endereço publicado nem assinatura de peça que já saiu. Vem em action=get e list_mine no campo `fullName` (null = ainda sem nome por extenso). TRAÇO (`style`, em que TÉCNICA ele é feito: auto default, realista, anime, manhwa, 3d, custom): irmão da forma, e a divisão é limpa, a forma diz que CORPO é esse e o traço diz como ele é DESENHADO. As mesmas três peças leem daqui. No 'auto' a peça não afirma técnica nenhuma e as imagens de referência mandam; 'realista' é fotografia, 'anime' é cel shading com contorno de tinta, 'manhwa' é pintura de webtoon, '3d' é render com material e oclusão, 'custom' usa a linha escrita em `styleNote` (até 140 caracteres, ex: aquarela sobre papel texturizado). Mande sempre que o personagem tiver técnica definida: até ago/2026 a ficha cravava vocabulário de desenho e devolvia personagem fotográfico virado em ilustração. Conserto sem custo em quem já existe: set_card style=realista. PRESENÇA (set_presence, de graça): o ENDEREÇO do personagem, o que faltava pra ele existir fora da ficha. `socials` é {rede: handle} nas redes instagram, tiktok, youtube, x, threads, bluesky, twitch, spotify, fanvue, patreon, onlyfans, telegram; `websiteUrl` é o site dele e `email` é o email do personagem, o que cadastra e recupera as contas dele nas redes. As redes e o site são PÚBLICOS; o email é PRIVADO e fica só com o dono, mesmo com o personagem publicado, porque email é chave de conta e isca de spam, não canal de contato. Em action=get e list_public de personagem de OUTRA pessoa, o campo simplesmente não vem. É MERGE: mandar {fanvue:'helen'} não apaga o instagram, e pra apagar uma rede se manda ela vazia. O que volta em action=get são as duas formas, `presence` (o handle cru, que é o que se reedita) e `presenceLinks` (o link já montado, pra mostrar sem remontar URL na mão). Vale a pena preencher quando o personagem TEM conta de verdade: é o que separa uma ficha de um ser com endereço, e a página pública dele desenha as redes e o site (nunca o email). FICHA (generate_sheet, COBRA 650 Sinapses, o preço do GPT Image 2.5 Sunburst, que desenha; se ele recusar, a ficha refaz no Gemini 3.1 Flash e cobra o preço dele, e o retorno diz em `model`, `modelLabel` e `fellBack` quem desenhou): desenha a página-pôster do personagem no traço das imagens que ele já tem (exige pelo menos uma), em duas orientações (arg `orientation`): 'portrait' (default) é a página de processo, pose, expressões, trocas de roupa e adereços soltos na folha; 'landscape' é a prancha larga, com a volta completa à esquerda, a figura grande no meio, poses à direita, estudos de silhueta, expressão e detalhe embaixo e um painel CHARACTER ID na ponta. A personalidade sai da alma (systemPrompt) e é ela que escolhe roupa e objeto, então personagem com alma escrita rende ficha melhor. Cada geração é um estilo NOVO e elas acumulam no personagem (campo sheetUrls em action=get), nenhuma apaga a anterior, e a ficha já entra na galeria dele como referência das próximas gerações. É geração síncrona: se voltar Timeout, cheque action=get antes de repetir, senão cobra duas vezes. STICKERS (generate_stickers, COBRA 550 Sinapses): desenha 5 stickers do personagem DE UMA VEZ. Uma folha só, em 2K, com as cinco figuras separadas sobre um fundo verde chroma, recortada por código em peças 512x512 transparentes abaixo de 100KB (o teto do WhatsApp). É por isso que sai o preço de UMA imagem em 2K e não de cinco: quem paga é a folha. As peças entram no pack do personagem (um por personagem, os lotes acumulam) e já ficam no picker de expressão do dono, no chat e no Fórum. Arg `moods`: até 5 humores do vocabulário comum por slug (kkkkk, amei, isso, hmm, chega, que, aff, bora, socorro, seinao, valeu, ainao, seila, ideia, calma, contatudo, perfeito, euavisei, naovourir, zzz, somaisum, sextou, merecido, quedia, tudobem); faltando, a casa completa com os mais usados. Arg `hint`: direcionamento curto do autor (roupa, adereço, clima), até 140 caracteres. Arg `stickerTier`: 'folha' (default) é esse lote de cinco, desenhado no Gemini 3.1 Flash; 'unica' (COBRA 900 Sinapses) desenha UM sticker por vez no Gemini 3 Pro, o motor mais fiel da casa, com a figura sozinha no quadro e o dobro de pixel por peça, e leva só o PRIMEIRO mood da lista. Pra encher o pack, folha; pra traço difícil ou a reação que vira a cara do personagem, a unica. Ao oferecer a escolha, diga o NOME DO MOTOR e o que ele troca: adjetivo vago de acabamento não informa nada a quem vai pagar. Os dois caem no MESMO pack e acumulam. Sem legenda queimada na imagem, de propósito: modelo erra acento em português, então o rótulo fica na row e serve de busca no picker. Exige pelo menos uma imagem no personagem (é dela que sai a cara) e é geração síncrona: se voltar Timeout, cheque sapiens_gallery antes de repetir. Quando a resposta vem com ok=false, a folha foi gerada e paga mas o corte falhou; ela está na galeria e o recorte de novo é de graça, pela web. Publicar o pack na vitrine e o carimbo da casa (que é o que põe no picker de todo mundo) são gestos da web, não desta tool. PLACAS (generate_plates, COBRA 550 Sinapses): seis ângulos do mesmo rosto numa geração só, no Gemini 3.1 Flash em 2K, recortados por código em seis referências com PAPEL: perfil, camera-alta, camera-baixa, frontal, cabeca-baixa e outro-lado, cada um com uma expressão diferente. Não é vitrine (isso é a ficha): é a referência feita pra máquina. Referência trava o ângulo da câmera, então quando a cena pede perfil, passe a placa de perfil em referenceImageUrls. As placas ficam FORA de imageUrls de propósito, porque placa de perfil como referência genérica puxa toda peça pro perfil; elas voltam em action=get no campo `plates` ([{role, url}]). As placas ACUMULAM: cada geração soma seis, e a que não serve sai com remove_image. Em `plates` o lote mais novo vem primeiro, cada lote na ordem da grade, então a primeira placa de um papel é a mais nova. Sai das fotos do personagem (exige pelo menos uma) e, quando ele tem passaporte, o descritor dele entra no pedido. Só personagem com rosto de gente (form human ou humanoid): pra bicho, criatura, objeto ou forma abstrata o servidor recusa antes de cobrar. O perfil puro e a câmera alta às vezes voltam amolecidos pro frontal; quando esses dois ângulos importarem, confira as placas antes de usar. Geração síncrona: se voltar Timeout, cheque action=get antes de repetir. Resposta com ok=false quer dizer grade gerada e paga com o corte falho; o recorte de novo é de graça, pela web. CHARACTER VIDEO (a ficha que anda): o personagem atravessa 6 mundos em 12s, trocando de roupa em cada um, com som gerado junto, e o último plano fecha a peça com ele parando e encarando a câmera. A peça volta FECHADA pelas duas portas (tela e agente), sem ninguém pedir: o personagem se apresenta no cartão de nome por cima do fim do último plano, com o LEMA em inglês embaixo (o campo `titleEn`, escrito uma vez em set_card), e só depois a casa assina. Quem não tem lema recebe o subtítulo que o roteiro inventou naquele take, e ele muda no take seguinte. O fecho é asset, não geração: zero Sinapse a mais, e é fail-open, então a resposta traz `closed` e `nameCard` dizendo o que entrou de verdade em vez de prometer um cartão que não está no arquivo. Pra colocar esse cartão num vídeo que JÁ existe, o caminho é a ficha do take na web (gaveta do fecho, 'Apresentação do personagem'), também sem custo. Exige FICHA gerada (é dela que saem a cara e o guarda-roupa), não só imagem. Duas actions, nesta ordem: plan_video (COBRA 50 Sinapses) devolve os 6 planos que a alma do personagem escolheu, com ambiente, ato, enquadramento e roupa. Cada plano vem nas duas línguas: em inglês (setting/act/wardrobe, que é o que vai pro motor) e em português (settingPt/actPt/wardrobePt). MOSTRE a versão em português pro autor, o público da casa é brasileiro e roteiro que ele lê de través não é roteiro aprovado; peça de novo quantas vezes ele quiser, porque trocar sai por 50 e o take errado sai por milhares. replan_shot (COBRA 15 Sinapses) reescreve UM plano e não toca nos outros cinco: os seis são cenas independentes, então quando o autor gosta de quatro e implica com um, troque só aquele em vez de sortear tudo de novo (mande os 6 planos em `shots`, o número em `shotIndex`, e o que ele quer diferente em `shotHint`; volta só o plano trocado, e é você que remonta o roteiro). Depois generate_video (COBRA) renderiza, com os planos aprovados no arg `shots` e o MOTOR no arg `videoTier`: 'draft' (5.400 Sinapses) é o Seedance 2.0 Mini, metade do preço, que tropeça em mão, pouca luz e câmera rápida, e 'final' (8.640 Sinapses) é o Seedance 2.0 Fast, que segura o que o Mini erra. A peça é a MESMA nos dois (mesmos 6 planos, 12s, 720p, com som), então ofereça pelo nome do motor e pelo que ele troca, nunca por adjetivo vago de acabamento. Vertical ou horizontal pelo arg `orientation`. Chamar generate_video SEM `shots` funciona, mas escreve um roteiro novo às cegas e cobra igual: não faça isso sem o autor ter visto o que vai receber. É geração demorada: se voltar Timeout, cheque sapiens_gallery antes de repetir. Resposta com `pending: true` (sem `url`) quer dizer ACEITO E COBRADO: o servidor continua renderizando sozinho (até 25 min) e a peça chega na ficha já fechada; NÃO repita a chamada, isso cobraria de novo, confira depois em sapiens_gallery. Fluxo de criação: create → add_image (1+) → set_card (opcional) → activate. PARE AÍ. O personagem nasce e continua PRIVADO, e é assim que ele serve pro dono: dá pra gerar, referenciar e iterar sem ninguém ver. set_visibility isPublic=true é o gesto de PUBLICAR no Explorar, com slug público, e nÃO é passo de fluxo: só chame quando o dono pedir pra publicar aquele personagem, com essas palavras. Na dúvida, não publique e pergunte. Pra usar um personagem público como referência numa geração, pegue mainImageUrl em list_public/get e passe em sapiens_image referenceImageUrls.",
|
|
162
168
|
schema: characterSchema,
|
|
163
169
|
handler: character,
|
|
164
170
|
},
|
|
@@ -292,6 +298,7 @@ const READ_ONLY_TOOLS = new Set([
|
|
|
292
298
|
const CLOSED_WORLD_TOOLS = new Set(["sapiens_skill", "sapiens_resume"]);
|
|
293
299
|
const TOOL_TITLES = {
|
|
294
300
|
sapiens_pipeline: "Pipeline de Conteúdo",
|
|
301
|
+
sapiens_carrossel: "Carrossel",
|
|
295
302
|
sapiens_image: "Gerar Imagem",
|
|
296
303
|
sapiens_meta: "Conta & Utilitários",
|
|
297
304
|
sapiens_voice_jp: "Voz Japonesa (local)",
|
package/dist/skills.js
CHANGED
|
@@ -59,7 +59,7 @@ Não despeje a lista inteira de tools. O start guia.
|
|
|
59
59
|
|---|---|
|
|
60
60
|
| imagem | \`sapiens_gallery action=list\` |
|
|
61
61
|
| artigo do perfil | \`sapiens_write action=list\` |
|
|
62
|
-
| carrossel | \`
|
|
62
|
+
| carrossel | \`sapiens_carrossel action=list\` |
|
|
63
63
|
|
|
64
64
|
**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
65
|
|
|
@@ -348,6 +348,12 @@ Nas Krea 2 da WaveSpeed a referência é a imagem-base (uma só), e \`refStrengt
|
|
|
348
348
|
- \`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á.
|
|
349
349
|
- Uma imagem só vira pública (e ganha página indexável) com \`sapiens_gallery action=publish\`.
|
|
350
350
|
|
|
351
|
+
## Peça reprovada ensina a próxima
|
|
352
|
+
|
|
353
|
+
Quando a pessoa condena uma peça ("mudou o rosto dela", "a mão está quebrada", "não é ela"), marque NO MESMO TURNO: \`sapiens_gallery action=reprovar imageId=<id> motivo='<o porquê numa frase concreta>'\`. O motivo bom diz a CAUSA, não só o sintoma: "trocou o rosto: gerada só com o personagem, sem as fotos de rosto do passaporte" ensina mais que "ficou feia". A reprovada não sai mais por porta nenhuma (fila de distribuição, publicar, canal) e some das sugestões do que postar; ela fica no acervo pra ensinar. Peça condenada e não marcada volta numa leva semanas depois, porque nada nela diz que foi condenada.
|
|
354
|
+
|
|
355
|
+
Antes de gerar de novo um personagem, leia o que já deu errado com ele: \`sapiens_gallery action=reprovadas characterId=<id>\` devolve cada peça vetada com o prompt que a gerou e o motivo. Cada motivo vira cuidado nesta geração: a referência que faltou entra, a palavra que puxou o erro sai do prompt. O erro que se repete vira regra do personagem: grave no passaporte (\`sapiens_character action=set_passport\`, campo \`discarded\`, com o negativo junto).
|
|
356
|
+
|
|
351
357
|
## Quando a pessoa quer "do jeito dela", com o personagem dela
|
|
352
358
|
|
|
353
359
|
O design system dela é quem veste a peça (\`sapiens_brand\`), e o personagem dela pode virar a cara fixa desse design system. Depois de plugado, ele entra em toda imagem daquela marca sem ninguém anexar referência de novo:
|
|
@@ -815,6 +821,42 @@ O que a peça vira: NATIVA, PRIVADA, publicável depois por \`action=publish\` (
|
|
|
815
821
|
- 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.
|
|
816
822
|
- Peça achada pronta na internet, sem direção dela: é \`action=upload\` (privada pra sempre), não ingest.`,
|
|
817
823
|
},
|
|
824
|
+
{
|
|
825
|
+
name: "carrossel",
|
|
826
|
+
title: "Carrossel: gerar, escrever, pôr foto e entregar",
|
|
827
|
+
description: "O carrossel do Instagram pelo agente: gerar do brief ou de um artigo, reescrever os slides direto no payload, pôr foto da galeria da pessoa, a capa IA, e onde ela baixa. Puxe ANTES de sapiens_carrossel.",
|
|
828
|
+
body: `## O que é
|
|
829
|
+
|
|
830
|
+
Um carrossel é uma RECEITA: tema (paleta, folha e assinatura) mais slides, cada um com um layout (\`templateId\`) e os textos dele (\`slots\`). O desenho sai dessa receita no editor da pessoa, que é também onde ela baixa os arquivos. Você escreve a receita; ela abre, confere e baixa.
|
|
831
|
+
|
|
832
|
+
## O fluxo
|
|
833
|
+
|
|
834
|
+
1. \`sapiens_carrossel action=generate\` com \`brief\` (o tema e o ângulo, um parágrafo) OU \`articleId\` (artigo publicado) OU \`userArticleId\` (artigo dela). Custa 350 Sinapses, já com a escolha de fotos, e estorna se falhar. Devolve o \`id\` e a \`url\` do editor.
|
|
835
|
+
2. \`action=get\` traz o payload inteiro e o catálogo: os layouts com os slots de cada um, as paletas, as folhas e a assinatura. Leia antes de mexer.
|
|
836
|
+
3. \`action=update\` grava o payload INTEIRO de volta. Reescreva os textos com a voz da pessoa (puxe a skill \`voz-da-casa\`). Mande o \`theme\` inteiro e o \`image\` de todo slide que você não mexeu: o que faltar volta pro padrão e a foto do slide some. Mande também \`baseUpdatedAt\` com o \`updatedAt\` do get: se o carrossel mudou depois (uma foto gerada, uma edição dela no editor), o update recusa em vez de apagar isso, e aí você faz get de novo. Foto nova não entra por URL no update, só pelo passo 4.
|
|
837
|
+
4. Foto: \`action=auto_images\` (60) deixa a IA escolher do banco; \`action=set_image\` põe uma peça DA PESSOA pelo ID citável (\`img_…\`, de \`sapiens_reference\` ou \`sapiens_gallery\`), de graça; \`action=generate_image\` gera uma nova pra um slide, ~450 cada.
|
|
838
|
+
5. Mande a \`url\` do editor. É lá que ela confere, ajusta e baixa.
|
|
839
|
+
|
|
840
|
+
## A forma e o tamanho
|
|
841
|
+
|
|
842
|
+
\`model\` é a FORMA: \`feed\` (o padrão, 9 slides que abrem numa dor, mostram o mecanismo e fecham em ação), \`reflexao\` (tema de comportamento sustentado por uma analogia), \`case\` (tendência a partir de link ou manchete, fecha numa keyword) e \`editorial\` (a IA escolhe os layouts, 7 a 9 slides).
|
|
843
|
+
|
|
844
|
+
\`aspect\` é o TAMANHO: \`4:5\` (o padrão, a folha que o feed do Instagram mostra inteira) ou \`9:16\` (tela cheia). Os dois trocam depois no editor sem perder texto.
|
|
845
|
+
|
|
846
|
+
## A assinatura
|
|
847
|
+
|
|
848
|
+
O nome no topo, a marca no canto da capa e o @ do fecho saem de \`theme.signature\` (\`label\`, \`handle\`, \`logoUrl\`). Nasce da marca da pessoa, ou do nome dela quando não tem marca. Se ela pedir pra mudar, mude ali, no update. O @ é o dela no Instagram: não invente, pergunte.
|
|
849
|
+
|
|
850
|
+
## A capa IA
|
|
851
|
+
|
|
852
|
+
\`action=cover\` gera uma capa 16:9 com a manchete QUEIMADA na imagem, um elemento vivo cruzando as letras, e com \`carouselId\` fatia em duas e põe na frente do carrossel, no lugar da capa IA anterior. Cobra pelo motor da capa (o preço sai de \`sapiens_image action=models\`). Confirme o custo com a pessoa antes. Animar a capa é no editor, não por aqui.
|
|
853
|
+
|
|
854
|
+
## Armadilhas
|
|
855
|
+
|
|
856
|
+
- \`generate\`, \`auto_images\` com \`generateMissing\` e \`generate_image\` são síncronas e pesadas: se voltar Timeout, confira em \`action=list\` antes de repetir. Pode ter gerado e cobrado.
|
|
857
|
+
- O carrossel vai até 15 slides. A capa IA entra com dois.
|
|
858
|
+
- Baixar é no editor (o arquivo sai do navegador dela). Aqui você entrega a receita pronta, não o arquivo.`,
|
|
859
|
+
},
|
|
818
860
|
];
|
|
819
861
|
export const SKILLS = Object.fromEntries(SKILL_LIST.map((s) => [s.name, s]));
|
|
820
862
|
/** Monta o SKILL.md completo (frontmatter do formato aberto + corpo). */
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexAction, convexMutation, convexQuery, getSessionToken, } from "../convexClient.js";
|
|
3
|
+
import { need } from "../schema.js";
|
|
4
|
+
/**
|
|
5
|
+
* O CARROSSEL PELO AGENTE, pra qualquer conta logada.
|
|
6
|
+
*
|
|
7
|
+
* Até out/2026 tudo de carrossel no MCP morava dentro da sapiens_pipeline, que
|
|
8
|
+
* é admin e some do tools/list do membro. A vitrine prometia ao membro o que o
|
|
9
|
+
* gate recusava. Esta tool é a porta do membro: opera os carrosséis do PRÓPRIO
|
|
10
|
+
* usuário (posse conferida no servidor, por createdBy), cobra pelo catálogo e
|
|
11
|
+
* estorna o que falhar. As mesmas funções Convex atendem a sapiens_pipeline do
|
|
12
|
+
* admin, então o contrato antigo segue de pé.
|
|
13
|
+
*
|
|
14
|
+
* O que fica de fora de propósito: o carrossel atrelado a uma jogada do
|
|
15
|
+
* Workflow (production), que segue pela sapiens_pipeline. Aqui é o Lab: o
|
|
16
|
+
* carrossel solto, que o membro abre no editor pra ajustar e baixar.
|
|
17
|
+
*/
|
|
18
|
+
const MODELS = ["feed", "reflexao", "case", "editorial"];
|
|
19
|
+
export const carrosselSchema = z.object({
|
|
20
|
+
action: z
|
|
21
|
+
.enum([
|
|
22
|
+
"generate",
|
|
23
|
+
"list",
|
|
24
|
+
"get",
|
|
25
|
+
"update",
|
|
26
|
+
"auto_images",
|
|
27
|
+
"generate_image",
|
|
28
|
+
"set_image",
|
|
29
|
+
"cover",
|
|
30
|
+
])
|
|
31
|
+
.describe("generate (gera um carrossel do zero a partir de brief OU artigo, 350 Sinapses, estorna se falhar) · list (seus carrosséis) · get (payload inteiro + catálogo de layouts, paletas, folhas e a assinatura, tudo pra você escrever os slides) · update (grava o payload inteiro de volta, normalizado no servidor) · auto_images (a IA escolhe fotos do banco pros slides, 60 Sinapses; generateMissing gera as que faltarem, ~450 cada) · generate_image (foto nova pra UM slide, ~450) · set_image (põe no slide uma peça SUA ou pública, pelo ID citável img_…, sem custo) · cover (a Capa IA: capa 16:9 com o texto queimado, fatiada em duas e posta na frente do carrossel, cobra pelo motor da capa)."),
|
|
32
|
+
// generate
|
|
33
|
+
brief: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("generate: o tema e o ângulo do carrossel, em um parágrafo. Use brief OU articleId OU userArticleId."),
|
|
37
|
+
articleId: z
|
|
38
|
+
.string()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("generate: id de um artigo PUBLICADO do blog da casa, usado como fonte (o carrossel fica fiel ao argumento dele)."),
|
|
41
|
+
userArticleId: z
|
|
42
|
+
.string()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("generate: id de um artigo SEU do perfil (sapiens_write), usado como fonte."),
|
|
45
|
+
model: z
|
|
46
|
+
.enum(MODELS)
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("generate: a FORMA. 'feed' (padrão: 9 slides, abre numa dor, mostra o mecanismo, fecha em ação), 'reflexao' (tema existencial sustentado por uma analogia), 'case' (análise de tendência a partir de link ou manchete, fecha em keyword), 'editorial' (a IA escolhe os layouts livremente, 7 a 9 slides)."),
|
|
49
|
+
aspect: z
|
|
50
|
+
.enum(["4:5", "9:16"])
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("generate: o TAMANHO da folha. '4:5' (padrão, o feed do Instagram mostra inteira) ou '9:16' (tela cheia). Dá pra trocar depois no editor."),
|
|
53
|
+
useSintetico: z
|
|
54
|
+
.boolean()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("generate: true = a voz do seu Sintético escreve o texto por cima da voz da sua marca."),
|
|
57
|
+
autoPickImages: z
|
|
58
|
+
.boolean()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("generate: false = só o texto, sem escolher fotos (default true, incluso no preço)."),
|
|
61
|
+
// por carrossel
|
|
62
|
+
carouselId: z
|
|
63
|
+
.string()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("O id do carrossel (vem do generate e do list). Obrigatório em get, update, auto_images, generate_image, set_image; opcional no cover (sem ele a capa só é gerada)."),
|
|
66
|
+
payload: z
|
|
67
|
+
.any()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("update: o payload INTEIRO, no shape do get: { theme: { palette, sheet, signature }, slides: [{ id, templateId, slots, image }], meta }. Preserve image dos slides que você não mexeu e o theme inteiro (folha e assinatura): o que faltar volta pro padrão. Foto NOVA não entra por URL aqui: use set_image (ID da peça) ou generate_image."),
|
|
70
|
+
title: z.string().optional().describe("update: novo título do carrossel (opcional)."),
|
|
71
|
+
baseUpdatedAt: z
|
|
72
|
+
.number()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe("update: o updatedAt que o get devolveu. Mande sempre: se o carrossel mudou depois do get (uma foto gerada, uma edição no editor), o update recusa em vez de apagar isso com o payload velho. Aí faça get de novo e reaplique."),
|
|
75
|
+
force: z.boolean().optional().describe("auto_images: true troca também as fotos que já estão nos slides."),
|
|
76
|
+
makeVisual: z
|
|
77
|
+
.boolean()
|
|
78
|
+
.optional()
|
|
79
|
+
.describe("auto_images: true converte slides só de texto em layouts com foto antes de escolher (dá ritmo a carrossel texto-pesado)."),
|
|
80
|
+
generateMissing: z
|
|
81
|
+
.boolean()
|
|
82
|
+
.optional()
|
|
83
|
+
.describe("auto_images: true gera foto nova pros slides que o banco não cobriu (até 4, ~450 Sinapses cada). Avise o custo antes."),
|
|
84
|
+
slideId: z.string().optional().describe("generate_image e set_image: o id do slide (vem do get)."),
|
|
85
|
+
customPrompt: z.string().optional().describe("generate_image: direção da cena (opcional; sem ela a cena sai do texto do slide)."),
|
|
86
|
+
handle: z
|
|
87
|
+
.string()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("set_image: o ID citável da peça (img_…), que o usuário copia no detalhe dela ou vem de sapiens_reference/sapiens_gallery. Peça sua ou pública."),
|
|
90
|
+
focalX: z.number().min(0).max(1).optional().describe("set_image: ponto focal horizontal (0 a 1, default 0.5)."),
|
|
91
|
+
focalY: z.number().min(0).max(1).optional().describe("set_image: ponto focal vertical (0 a 1, default 0.5)."),
|
|
92
|
+
// cover
|
|
93
|
+
capaHeadline: z.string().optional().describe("cover: a manchete que vai queimada na capa (obrigatória)."),
|
|
94
|
+
capaSubline: z.string().optional().describe("cover: linha de apoio (opcional)."),
|
|
95
|
+
capaRightText: z.string().optional().describe("cover: o texto que cai no 2º slide (opcional)."),
|
|
96
|
+
capaElement: z.string().optional().describe("cover: o elemento vivo que cruza as letras (omita e a IA escolhe pela pauta)."),
|
|
97
|
+
capaVibe: z.string().optional().describe("cover: o cenário (omita e a IA escolhe)."),
|
|
98
|
+
capaImageModel: z
|
|
99
|
+
.string()
|
|
100
|
+
.optional()
|
|
101
|
+
.describe("cover: o motor da capa. Default o que escreve letra pequena legível; veja o preço em sapiens_image action=models."),
|
|
102
|
+
});
|
|
103
|
+
// O payload pode chegar serializado como string JSON (cliente que serializa v.any()).
|
|
104
|
+
function coercePayload(raw) {
|
|
105
|
+
if (typeof raw !== "string")
|
|
106
|
+
return raw;
|
|
107
|
+
try {
|
|
108
|
+
return JSON.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
throw new Error("update: payload chegou como string que não é JSON. Mande o objeto do get_carousel.");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function carrossel(args) {
|
|
115
|
+
const sessionToken = getSessionToken();
|
|
116
|
+
switch (args.action) {
|
|
117
|
+
case "generate": {
|
|
118
|
+
const brief = args.brief?.trim();
|
|
119
|
+
const fontes = [brief, args.articleId, args.userArticleId].filter(Boolean).length;
|
|
120
|
+
if (fontes !== 1) {
|
|
121
|
+
throw new Error("generate: passe UMA fonte, brief OU articleId OU userArticleId.");
|
|
122
|
+
}
|
|
123
|
+
const sourceKind = brief ? "brief" : args.articleId ? "published_article" : "user_article";
|
|
124
|
+
// SÍNCRONA e pesada (texto + fotos): vale a REGRA DO TIMEOUT. Se voltar
|
|
125
|
+
// Timeout, confira em action=list antes de repetir.
|
|
126
|
+
return await convexAction("carouselAutofill:mcpCreateCarousel", {
|
|
127
|
+
sessionToken,
|
|
128
|
+
sourceKind,
|
|
129
|
+
...(brief ? { brief } : {}),
|
|
130
|
+
...(args.articleId ? { publishedArticleId: args.articleId } : {}),
|
|
131
|
+
...(args.userArticleId ? { sourceUserArticleId: args.userArticleId } : {}),
|
|
132
|
+
...(args.model ? { model: args.model } : {}),
|
|
133
|
+
...(args.aspect ? { aspect: args.aspect } : {}),
|
|
134
|
+
...(args.useSintetico !== undefined ? { useSintetico: args.useSintetico } : {}),
|
|
135
|
+
...(args.autoPickImages !== undefined ? { autoPickImages: args.autoPickImages } : {}),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
case "list":
|
|
139
|
+
return await convexQuery("carouselMcp:mcpListCarousels", { sessionToken });
|
|
140
|
+
case "get":
|
|
141
|
+
return await convexQuery("carouselMcp:mcpGetCarousel", {
|
|
142
|
+
sessionToken,
|
|
143
|
+
carouselId: need(args.carouselId, "carouselId"),
|
|
144
|
+
});
|
|
145
|
+
case "update":
|
|
146
|
+
return await convexMutation("carouselMcp:mcpUpdateCarousel", {
|
|
147
|
+
sessionToken,
|
|
148
|
+
carouselId: need(args.carouselId, "carouselId"),
|
|
149
|
+
payload: coercePayload(need(args.payload, "payload")),
|
|
150
|
+
...(args.title ? { title: args.title } : {}),
|
|
151
|
+
...(typeof args.baseUpdatedAt === "number" ? { baseUpdatedAt: args.baseUpdatedAt } : {}),
|
|
152
|
+
});
|
|
153
|
+
case "auto_images":
|
|
154
|
+
return await convexAction("carouselAutofill:mcpCarouselAutoImages", {
|
|
155
|
+
sessionToken,
|
|
156
|
+
carouselId: need(args.carouselId, "carouselId"),
|
|
157
|
+
...(args.force !== undefined ? { force: args.force } : {}),
|
|
158
|
+
...(args.makeVisual !== undefined ? { makeVisual: args.makeVisual } : {}),
|
|
159
|
+
...(args.generateMissing !== undefined ? { generateMissing: args.generateMissing } : {}),
|
|
160
|
+
});
|
|
161
|
+
case "generate_image":
|
|
162
|
+
return await convexAction("carouselAutofill:mcpCarouselGenerateImage", {
|
|
163
|
+
sessionToken,
|
|
164
|
+
carouselId: need(args.carouselId, "carouselId"),
|
|
165
|
+
slideId: need(args.slideId, "slideId"),
|
|
166
|
+
...(args.customPrompt ? { customPrompt: args.customPrompt } : {}),
|
|
167
|
+
});
|
|
168
|
+
case "set_image":
|
|
169
|
+
return await convexMutation("carouselMcp:mcpSetSlideImage", {
|
|
170
|
+
sessionToken,
|
|
171
|
+
carouselId: need(args.carouselId, "carouselId"),
|
|
172
|
+
slideId: need(args.slideId, "slideId"),
|
|
173
|
+
handle: need(args.handle, "handle"),
|
|
174
|
+
...(args.focalX !== undefined ? { focalX: args.focalX } : {}),
|
|
175
|
+
...(args.focalY !== undefined ? { focalY: args.focalY } : {}),
|
|
176
|
+
});
|
|
177
|
+
case "cover":
|
|
178
|
+
return await convexAction("capaIa:mcpCapaIa", {
|
|
179
|
+
sessionToken,
|
|
180
|
+
headline: need(args.capaHeadline, "capaHeadline"),
|
|
181
|
+
...(args.capaSubline ? { subline: args.capaSubline } : {}),
|
|
182
|
+
...(args.capaRightText ? { rightText: args.capaRightText } : {}),
|
|
183
|
+
...(args.capaElement ? { element: args.capaElement } : {}),
|
|
184
|
+
...(args.capaVibe ? { vibe: args.capaVibe } : {}),
|
|
185
|
+
...(args.capaImageModel ? { imageModel: args.capaImageModel } : {}),
|
|
186
|
+
...(args.carouselId ? { carouselId: args.carouselId } : {}),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
package/dist/tools/character.js
CHANGED
|
@@ -228,6 +228,14 @@ export const characterSchema = z.object({
|
|
|
228
228
|
"mandar {fanvue:'helen'} não apaga o instagram que já estava lá, e pra " +
|
|
229
229
|
"apagar uma rede se manda ela vazia ({instagram:''}). Rede fora da lista " +
|
|
230
230
|
"é ignorada em silêncio."),
|
|
231
|
+
hashtag: z
|
|
232
|
+
.string()
|
|
233
|
+
.optional()
|
|
234
|
+
.describe("Pra set_presence: a HASHTAG do personagem, sem #, numa palavra ('AriaMaiven'). " +
|
|
235
|
+
"É o fio que junta as peças dele na rede: o Distribution põe essa tag " +
|
|
236
|
+
"sozinha nos posts do personagem. Sem ela a tag sai do nome, então " +
|
|
237
|
+
"preencha quando o nome é comum demais pra ser dele (#Aria é de todo " +
|
|
238
|
+
"mundo). Espaço e pontuação o servidor tira. String vazia apaga."),
|
|
231
239
|
imageUrl: httpUrl()
|
|
232
240
|
.optional()
|
|
233
241
|
.describe("Pra add_image: URL pública da imagem (Bunny CDN / Convex storage). Use a `url` que sapiens_image/sapiens_gallery devolvem. Pra remove_image/set_main_image: a url da imagem JÁ no personagem (pegue via action=get, campo imageUrls, ou sheetUrls pra apagar uma ficha, ou plates[].url pra apagar uma placa)."),
|
|
@@ -408,8 +416,9 @@ export async function character(args) {
|
|
|
408
416
|
throw new Error("action=set_presence exige characterId.");
|
|
409
417
|
if (args.email === undefined &&
|
|
410
418
|
args.websiteUrl === undefined &&
|
|
411
|
-
args.socials === undefined
|
|
412
|
-
|
|
419
|
+
args.socials === undefined &&
|
|
420
|
+
args.hashtag === undefined) {
|
|
421
|
+
throw new Error("action=set_presence precisa de pelo menos um: email, websiteUrl, socials ou hashtag.");
|
|
413
422
|
}
|
|
414
423
|
const sessionToken = getSessionToken();
|
|
415
424
|
return await convexMutation("influencers:mcpSetCharacterPresence", {
|
|
@@ -418,6 +427,7 @@ export async function character(args) {
|
|
|
418
427
|
email: args.email,
|
|
419
428
|
websiteUrl: args.websiteUrl,
|
|
420
429
|
socials: args.socials,
|
|
430
|
+
hashtag: args.hashtag,
|
|
421
431
|
});
|
|
422
432
|
}
|
|
423
433
|
// -------- set_passport: como ACERTAR ele (a receita que ja foi medida) --------
|
package/dist/tools/gallery.js
CHANGED
|
@@ -42,6 +42,8 @@ export const gallerySchema = z.object({
|
|
|
42
42
|
"cast",
|
|
43
43
|
"parts",
|
|
44
44
|
"link_parts",
|
|
45
|
+
"reprovar",
|
|
46
|
+
"reprovadas",
|
|
45
47
|
]),
|
|
46
48
|
processo: z
|
|
47
49
|
.array(z.object({
|
|
@@ -63,7 +65,7 @@ export const gallerySchema = z.object({
|
|
|
63
65
|
.positive()
|
|
64
66
|
.max(100)
|
|
65
67
|
.optional()
|
|
66
|
-
.describe("Default 20. Max 100.
|
|
68
|
+
.describe("Default 20. Max 100. Pra action=list (e action=reprovadas, teto 60). Sem offset: com filtro de model ou skill a busca varre só as últimas 200 peças. Pra achar o imageId de peça que não é de hoje, use sapiens_reference action=browse bucket=history term=<palavra> (paginado, devolve o imageId) ou sapiens_reference action=resolve handle=img_xxx."),
|
|
67
69
|
model: z
|
|
68
70
|
.string()
|
|
69
71
|
.optional()
|
|
@@ -137,7 +139,7 @@ export const gallerySchema = z.object({
|
|
|
137
139
|
characterId: z
|
|
138
140
|
.string()
|
|
139
141
|
.optional()
|
|
140
|
-
.describe("action=ingest: o personagem de quem é a peça (influencers:_id, ache com sapiens_character action=list_mine). A peça nasce ligada à ficha, igual ao que sai dos motores da casa: conta no personagem e resolve a miniatura dele. PODE OMITIR quando as referenceImageIds já são peças da casa feitas com aquele personagem (folha de storyboard, ficha): o servidor deduz o personagem da primeira ref que tem um. O que você diz aqui manda sobre o que ele deduz. Re-ingerir a mesma sourceUrl com characterId AMARRA uma peça que já entrou sem personagem, sem trocar o id. Aceita personagem seu ou público."),
|
|
142
|
+
.describe("action=ingest: o personagem de quem é a peça (influencers:_id, ache com sapiens_character action=list_mine). A peça nasce ligada à ficha, igual ao que sai dos motores da casa: conta no personagem e resolve a miniatura dele. PODE OMITIR quando as referenceImageIds já são peças da casa feitas com aquele personagem (folha de storyboard, ficha): o servidor deduz o personagem da primeira ref que tem um. O que você diz aqui manda sobre o que ele deduz. Re-ingerir a mesma sourceUrl com characterId AMARRA uma peça que já entrou sem personagem, sem trocar o id. Aceita personagem seu ou público. Em action=reprovadas, FILTRA as vetadas daquele personagem."),
|
|
141
143
|
characterIds: z
|
|
142
144
|
.union([z.array(z.string()), z.string()])
|
|
143
145
|
.optional()
|
|
@@ -163,6 +165,16 @@ export const gallerySchema = z.object({
|
|
|
163
165
|
.string()
|
|
164
166
|
.optional()
|
|
165
167
|
.describe("action=upload: de onde veio ('magnific', 'suno', 'camera'). Fica registrado na peça e no aviso do Discord."),
|
|
168
|
+
// --- action=reprovar: o veto do dono ---
|
|
169
|
+
motivo: z
|
|
170
|
+
.string()
|
|
171
|
+
.max(500)
|
|
172
|
+
.optional()
|
|
173
|
+
.describe("action=reprovar: O PORQUÊ do veto, numa frase concreta que a próxima geração consegue usar ('trocou o rosto da Helen: gerada só com influencerId, sem as refs do passaporte'; 'mão esquerda com seis dedos'). É a lição que fica na peça: sem ele, reprovar só esconde e não ensina. Até 500 caracteres. Reprovar de novo sem motivo mantém o que já estava escrito."),
|
|
174
|
+
desfazer: z
|
|
175
|
+
.boolean()
|
|
176
|
+
.optional()
|
|
177
|
+
.describe("action=reprovar: true TIRA o veto (a peça volta a poder sair e a entrar nas levas), e o motivo vai junto. Ausente/false reprova."),
|
|
166
178
|
});
|
|
167
179
|
// Teto igual ao do servidor (convex/galleryImport.ts): falha aqui é mais barata
|
|
168
180
|
// que falhar depois de trafegar o base64 inteiro.
|
|
@@ -661,6 +673,33 @@ export async function gallery(args) {
|
|
|
661
673
|
// uma peça nova, sem nenhum laço com os takes que a formaram. O juntador da
|
|
662
674
|
// casa (o "compilado") e o ingest com refs de vídeo já gravam o laço
|
|
663
675
|
// sozinhos; esta porta é pro resto, e pra corrigir ligação errada.
|
|
676
|
+
// reprovar: o VETO do dono. A peça errou (rosto trocado, mão quebrada) e
|
|
677
|
+
// não sai mais por porta nenhuma (fila do Distribution, publicar, Telegram,
|
|
678
|
+
// teia) nem volta numa leva do garimpo. Fica no acervo, com o porquê, pra
|
|
679
|
+
// ensinar: é o que action=reprovadas devolve antes da próxima geração.
|
|
680
|
+
if (args.action === "reprovar") {
|
|
681
|
+
if (!args.imageId) {
|
|
682
|
+
throw new Error("action=reprovar exige imageId: a peça vetada (imagem ou vídeo, o id da galeria).");
|
|
683
|
+
}
|
|
684
|
+
if (!args.desfazer && !args.motivo?.trim()) {
|
|
685
|
+
throw new Error("action=reprovar exige motivo: o porquê do veto numa frase concreta. É ele que ensina a próxima geração a não repetir o erro.");
|
|
686
|
+
}
|
|
687
|
+
return await convexAction("desktopMcp:galleryReprovar", {
|
|
688
|
+
sessionToken,
|
|
689
|
+
imageId: args.imageId,
|
|
690
|
+
reprovada: !args.desfazer,
|
|
691
|
+
motivo: args.desfazer ? undefined : args.motivo?.trim(),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
// reprovadas: as peças vetadas da conta, com o prompt que gerou e o porquê,
|
|
695
|
+
// a mais recente primeiro. Leia ANTES de gerar de novo o mesmo personagem.
|
|
696
|
+
if (args.action === "reprovadas") {
|
|
697
|
+
return await convexAction("desktopMcp:galleryReprovadas", {
|
|
698
|
+
sessionToken,
|
|
699
|
+
characterId: args.characterId,
|
|
700
|
+
limit: args.limit,
|
|
701
|
+
});
|
|
702
|
+
}
|
|
664
703
|
if (args.action === "link_parts") {
|
|
665
704
|
if (!args.imageId) {
|
|
666
705
|
throw new Error("action=link_parts exige imageId: o vídeo INTEIRO, o clipe montado. Use action=parts SEM imageId pra ver os pares de take que ainda não viraram um inteiro.");
|
package/dist/tools/image.js
CHANGED
|
@@ -19,6 +19,7 @@ const MODELS = [
|
|
|
19
19
|
"gpt-image-2-5-sunburst", // GPT Image 2.5 Sunburst quality=high · o 2.5 de precisão e edição em várias voltas · COM refs
|
|
20
20
|
"mai-image-2-6", // MAI Image 2.6 (Microsoft), no mesmo recurso Foundry do gpt-image-2 · foto rápida · cobra por ÁREA, então o adder de resolução é real · teto 2K (1536²) · SEM refs
|
|
21
21
|
"muse-image", // Meta Muse Image · barato na edição por referência (10 refs no catálogo, 5 pelo MCP) · sem escada de resolução · moderação apertada, não é +18
|
|
22
|
+
"flux-3", // FLUX 3 (Black Forest Labs) · texto e composição precisos · COM refs (10 no catálogo, 5 pelo MCP) · adder até 2K · moderado, não é +18
|
|
22
23
|
// ByteDance via ModelArk direto. Corp/censurado, 2K nativo, COM refs (até 4).
|
|
23
24
|
// (O "nova-canvas" ficava aqui e saiu: a AWS matou o modelo. Pedido antigo
|
|
24
25
|
// ainda funciona, o backend faz o alias pro gpt-image-2-low.)
|
|
@@ -115,7 +116,7 @@ export const imageSchema = z.object({
|
|
|
115
116
|
model: z
|
|
116
117
|
.enum(MODELS)
|
|
117
118
|
.optional()
|
|
118
|
-
.describe("Default 'nano-banana-2' (Flash 3.1 com refs). 'nano-banana-max' (Pro 3) = qualidade alta. 'gpt-image-2-low/high' = GPT Image 2 nos tiers low e high. 'gpt-image-2-5-flare'/'gpt-image-2-5-sunburst' = GPT Image 2.5, a geração de set/2026, os dois em quality high e com referência: o Flare é o rápido, pra volume; o Sunburst é o de precisão, pra composição complexa e edição em várias voltas. 'mai-image-2-6' (MAI Image 2.6, da Microsoft) = foto rápida no mesmo recurso do gpt-image-2, e o único da casa que cobra por ÁREA: o adder de resolução aqui é real, o teto é 2K (1536², porque acima disso o provider recusa por total de pixels) e ele não aceita referência. 'muse-image' (Muse Image, da Meta) = barato na edição por referência e bom pra segurar personagem (10 refs no catálogo; pelo MCP vale o teto de 5 do campo referenceImageUrls); sem escada de resolução (o motor decide o tamanho e cobra o mesmo) e moderação apertada, NÃO serve pra +18. 'seedream-4-5'/'seedream-5-0'/'seedream-5-0-pro' = ByteDance 2K nativo, cinematográfico, aceita até 4 referências (o 5.0 é a geração nova, entende prompt complexo melhor; o 5.0-pro é o topo da linha). 'grok-2-image'/'grok-2-image-quality' = xAI Grok Imagine da geração anterior (moderação frouxa +18, aceita refs e aspect; quality é mais fiel pra character lock); 'grok-imagine-2' = Grok Imagine Image 2.0, a geração nova de ago/2026, que é a melhor da linha integrando desenho e foto na mesma peça. DEGEN (uncensored, gate +18). NUDEZ É NÍVEL, NÃO MOTOR: três escolhas têm um par com nudez, e o par vem no campo `ousadia` de action=models. Sem nudez = o id da escolha; com nudez = o id do par + loraIntensity. Não existe motor '+18', 'Nu' ou 'Livre' separado pra procurar. 'wavespeed-chroma' (fotorrealista rápido, sem referência), 'wavespeed-flux2' (Flux.2 Klein Base: foto rápida, até 4 referências, segura o rosto) · com nudez = 'wavespeed-klein-nu' (o mesmo Klein com a LoRA de nudez no registro de foto; a identidade continua vindo da referência), 'wavespeed-klein-anime' (Flux.2 Klein + LoRA anime, inteligente e controlável) · com nudez = 'wavespeed-klein-anime-plus', 'wavespeed-flux-nsfw' (Flux dev + LoRA NSFW, sem par: a Ousadia é dele mesmo, via loraIntensity), 'wavespeed-klein-celular' (o MESMO Klein 9B com a LoRA Phone Photography por cima: foto de celular, candid, luz de janela; no edit com a referência da personagem o rosto fica quase idêntico, e é a receita de conteúdo de perfil de criadora pra personagem FOTOGRÁFICA. Em personagem cel-shaded o edit troca o traço, então não use com a Aria. Comece o prompt com 'This is a candid photograph taken with a smartphone of' e enumere 'same face, same hair' antes da cena; sem Ousadia), 'wavespeed-klein-transparencia' (o MESMO Klein 9B com a LoRA de tecido transparente: o efeito vem da LoRA e não da descrição; segura o rosto da ref; sem Ousadia), 'wavespeed-krea2-realism' (Krea 2 Realism: base 12B com LoRA de realismo, pele crua, hospedada na WaveSpeed SEM o classificador de entrada da fal, que devolve 422 até em prompt sem palavra de nudez; img2img de verdade com 1 referência, força regulável em refStrength, e 2K) · com nudez = 'wavespeed-krea2' (o mesmo realismo + LoRA NSFW; é a antiga 'Krea 2 Livre'), 'wavespeed-krea2-transparencia' (a mesma LoRA de transparência na base Krea 2: fotografia mais rica, identidade mais frouxa que a irmã Klein; 1 referência; sem Ousadia) = WaveSpeed rápido. LEGADO, fora da escolha da tela e ainda gerando pelo id (não ofereça): 'wavespeed-klein-plus' (a escolha virou 'wavespeed-klein-nu'), 'wavespeed-krea2-base' (Krea 2 sem LoRA nenhuma; a escolha virou 'wavespeed-krea2-realism'), 'fal-krea2-realism-v2' (Krea 2 Realism pela fal, ~4s: aceita até 3 referências de ESTILO, paleta/luz/textura de uma série, não character lock, e com referência a LoRA não vai junto; a escolha virou 'wavespeed-krea2-realism'). 'civitai-wai-illustrious'/'civitai-nova-anime-xl' (anime), 'civitai-pony-v6' (Pony V6 XL, base nº1) = Civitai sdcpp rápido. 'civitai-anima' (Anima: 2B da CircleStone com a Comfy Org, base própria e não SDXL; entrega anime de PRODUÇÃO, linha fechada e sombra chapada, em vez do registro de ilustração dos Illustrious. O encoder é um LLM, então escreva a cena em FRASE e não em tag booru, e não cole score_9/masterpiece aqui)."),
|
|
119
|
+
.describe("Default 'nano-banana-2' (Flash 3.1 com refs). 'nano-banana-max' (Pro 3) = qualidade alta. 'gpt-image-2-low/high' = GPT Image 2 nos tiers low e high. 'gpt-image-2-5-flare'/'gpt-image-2-5-sunburst' = GPT Image 2.5, a geração de set/2026, os dois em quality high e com referência: o Flare é o rápido, pra volume; o Sunburst é o de precisão, pra composição complexa e edição em várias voltas. 'mai-image-2-6' (MAI Image 2.6, da Microsoft) = foto rápida no mesmo recurso do gpt-image-2, e o único da casa que cobra por ÁREA: o adder de resolução aqui é real, o teto é 2K (1536², porque acima disso o provider recusa por total de pixels) e ele não aceita referência. 'muse-image' (Muse Image, da Meta) = barato na edição por referência e bom pra segurar personagem (10 refs no catálogo; pelo MCP vale o teto de 5 do campo referenceImageUrls); sem escada de resolução (o motor decide o tamanho e cobra o mesmo) e moderação apertada, NÃO serve pra +18. 'flux-3' (FLUX 3, da Black Forest Labs) = texto na arte e composição precisos, aceita referência (10 no catálogo; pelo MCP vale o teto de 5 do campo referenceImageUrls), resolução até 2K; com referência a proporção segue a primeira imagem; moderado, NÃO serve pra +18. 'seedream-4-5'/'seedream-5-0'/'seedream-5-0-pro' = ByteDance 2K nativo, cinematográfico, aceita até 4 referências (o 5.0 é a geração nova, entende prompt complexo melhor; o 5.0-pro é o topo da linha). 'grok-2-image'/'grok-2-image-quality' = xAI Grok Imagine da geração anterior (moderação frouxa +18, aceita refs e aspect; quality é mais fiel pra character lock); 'grok-imagine-2' = Grok Imagine Image 2.0, a geração nova de ago/2026, que é a melhor da linha integrando desenho e foto na mesma peça. DEGEN (uncensored, gate +18). NUDEZ É NÍVEL, NÃO MOTOR: três escolhas têm um par com nudez, e o par vem no campo `ousadia` de action=models. Sem nudez = o id da escolha; com nudez = o id do par + loraIntensity. Não existe motor '+18', 'Nu' ou 'Livre' separado pra procurar. 'wavespeed-chroma' (fotorrealista rápido, sem referência), 'wavespeed-flux2' (Flux.2 Klein Base: foto rápida, até 4 referências, segura o rosto) · com nudez = 'wavespeed-klein-nu' (o mesmo Klein com a LoRA de nudez no registro de foto; a identidade continua vindo da referência), 'wavespeed-klein-anime' (Flux.2 Klein + LoRA anime, inteligente e controlável) · com nudez = 'wavespeed-klein-anime-plus', 'wavespeed-flux-nsfw' (Flux dev + LoRA NSFW, sem par: a Ousadia é dele mesmo, via loraIntensity), 'wavespeed-klein-celular' (o MESMO Klein 9B com a LoRA Phone Photography por cima: foto de celular, candid, luz de janela; no edit com a referência da personagem o rosto fica quase idêntico, e é a receita de conteúdo de perfil de criadora pra personagem FOTOGRÁFICA. Em personagem cel-shaded o edit troca o traço, então não use com a Aria. Comece o prompt com 'This is a candid photograph taken with a smartphone of' e enumere 'same face, same hair' antes da cena; sem Ousadia), 'wavespeed-klein-transparencia' (o MESMO Klein 9B com a LoRA de tecido transparente: o efeito vem da LoRA e não da descrição; segura o rosto da ref; sem Ousadia), 'wavespeed-krea2-realism' (Krea 2 Realism: base 12B com LoRA de realismo, pele crua, hospedada na WaveSpeed SEM o classificador de entrada da fal, que devolve 422 até em prompt sem palavra de nudez; img2img de verdade com 1 referência, força regulável em refStrength, e 2K) · com nudez = 'wavespeed-krea2' (o mesmo realismo + LoRA NSFW; é a antiga 'Krea 2 Livre'), 'wavespeed-krea2-transparencia' (a mesma LoRA de transparência na base Krea 2: fotografia mais rica, identidade mais frouxa que a irmã Klein; 1 referência; sem Ousadia) = WaveSpeed rápido. LEGADO, fora da escolha da tela e ainda gerando pelo id (não ofereça): 'wavespeed-klein-plus' (a escolha virou 'wavespeed-klein-nu'), 'wavespeed-krea2-base' (Krea 2 sem LoRA nenhuma; a escolha virou 'wavespeed-krea2-realism'), 'fal-krea2-realism-v2' (Krea 2 Realism pela fal, ~4s: aceita até 3 referências de ESTILO, paleta/luz/textura de uma série, não character lock, e com referência a LoRA não vai junto; a escolha virou 'wavespeed-krea2-realism'). 'civitai-wai-illustrious'/'civitai-nova-anime-xl' (anime), 'civitai-pony-v6' (Pony V6 XL, base nº1) = Civitai sdcpp rápido. 'civitai-anima' (Anima: 2B da CircleStone com a Comfy Org, base própria e não SDXL; entrega anime de PRODUÇÃO, linha fechada e sombra chapada, em vez do registro de ilustração dos Illustrious. O encoder é um LLM, então escreva a cena em FRASE e não em tag booru, e não cole score_9/masterpiece aqui)."),
|
|
119
120
|
aspectRatio: z
|
|
120
121
|
.enum(["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"])
|
|
121
122
|
.optional()
|
|
@@ -132,7 +133,7 @@ export const imageSchema = z.object({
|
|
|
132
133
|
referenceImageUrls: z
|
|
133
134
|
.array(httpUrl())
|
|
134
135
|
.optional()
|
|
135
|
-
.describe("URLs públicas de referência pra combinar numa geração só (character/style lock), igual ao modal 'Selecionar Referência' do gerador web. Fontes: sua galeria (sapiens_gallery, campo url), o Acervo, e personagens públicos (sapiens_character action=list_public → mainImageUrl/imageUrls). Restrito a hosts do Sapiens (Bunny CDN / Convex) + Wikimedia. Requer model com refs (o campo supportsReferences em action=models é a fonte): nano-banana-*, gpt-image-2-*, muse-image, seedream-*, grok-* (até 3), a família Klein (wavespeed-flux2 e wavespeed-klein-*, até 4), wavespeed-flux-nsfw (1), a família Krea 2 da WaveSpeed (wavespeed-krea2-realism, wavespeed-krea2 e wavespeed-krea2-transparencia; img2img: a primeira referência vira a imagem-base, 1 ref, e refStrength diz quanto dela fica) ou fal-krea2-* (referência de ESTILO, teto de 3). Soma com sourceImageIds: até 5 no total (acima disso o servidor recusa a chamada), e cada motor corta no seu teto quando ele é menor (Seedream 4, Klein 4, Grok 3, Krea 2 e Flux NSFW 1; o campo maxReferences em action=models é a fonte)."),
|
|
136
|
+
.describe("URLs públicas de referência pra combinar numa geração só (character/style lock), igual ao modal 'Selecionar Referência' do gerador web. Fontes: sua galeria (sapiens_gallery, campo url), o Acervo, e personagens públicos (sapiens_character action=list_public → mainImageUrl/imageUrls). Restrito a hosts do Sapiens (Bunny CDN / Convex) + Wikimedia. Requer model com refs (o campo supportsReferences em action=models é a fonte): nano-banana-*, gpt-image-2-*, muse-image, flux-3, seedream-*, grok-* (até 3), a família Klein (wavespeed-flux2 e wavespeed-klein-*, até 4), wavespeed-flux-nsfw (1), a família Krea 2 da WaveSpeed (wavespeed-krea2-realism, wavespeed-krea2 e wavespeed-krea2-transparencia; img2img: a primeira referência vira a imagem-base, 1 ref, e refStrength diz quanto dela fica) ou fal-krea2-* (referência de ESTILO, teto de 3). Soma com sourceImageIds: até 5 no total (acima disso o servidor recusa a chamada), e cada motor corta no seu teto quando ele é menor (Seedream 4, Klein 4, Grok 3, Krea 2 e Flux NSFW 1; o campo maxReferences em action=models é a fonte)."),
|
|
136
137
|
sourceImageIds: z
|
|
137
138
|
.array(z.string())
|
|
138
139
|
.optional()
|
package/dist/tools/meta.js
CHANGED
|
@@ -76,20 +76,24 @@ const FORMAT_GUIDE = {
|
|
|
76
76
|
},
|
|
77
77
|
},
|
|
78
78
|
carrossel_ig: {
|
|
79
|
-
description: "Carrossel Instagram
|
|
79
|
+
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
80
|
payloadHint: {
|
|
81
81
|
meta: {
|
|
82
82
|
caption: "string (legenda do post)",
|
|
83
83
|
hashtags: ["string"],
|
|
84
84
|
keyword: "string MAIÚSCULA (gatilho do comment-to-DM, ex: QUERO)",
|
|
85
85
|
},
|
|
86
|
-
theme: {
|
|
86
|
+
theme: {
|
|
87
|
+
palette: "editorial-ink | editorial-dark | editorial-cream | editorial-bone | feed-preto | feed-floresta | feed-sage (as feed-* são da família de templates *-feed-c)",
|
|
88
|
+
sheet: "4:5 (padrão, o feed mostra inteira) | 9:16 (tela cheia)",
|
|
89
|
+
signature: "{ label, handle, logoUrl } de quem assina a peça; ausente = a casa",
|
|
90
|
+
},
|
|
87
91
|
slides: [
|
|
88
92
|
{
|
|
89
93
|
id: "slide-1",
|
|
90
94
|
templateId: "capa-tipografica-b | corpo-texto-puro-a | corpo-citacao-a | corpo-lista-a | corpo-dado-a | corpo-versus-a | corpo-foto-metade-a | cta-artigo-a (catálogo completo + slots por template vem de get_carousel)",
|
|
91
95
|
slots: { "...": "slots do template escolhido (ex: kicker, title, body)" },
|
|
92
|
-
image: "null, ou objeto { url,
|
|
96
|
+
image: "null, ou objeto { url, focal, zoom } nos templates de foto (url da casa; pra foto da galeria da pessoa, sapiens_carrossel action=set_image)",
|
|
93
97
|
},
|
|
94
98
|
],
|
|
95
99
|
},
|
|
@@ -442,7 +446,7 @@ export async function meta(args) {
|
|
|
442
446
|
if (args.action === "formats") {
|
|
443
447
|
return {
|
|
444
448
|
formats: FORMAT_GUIDE,
|
|
445
|
-
note: "Payload é livre (v.any() no schema)
|
|
449
|
+
note: "Payload é livre (v.any() no schema) e o hint é guia, MENOS no carrossel_ig: ele passa pelo normalizador da casa, e o que estiver fora do shape some.",
|
|
446
450
|
};
|
|
447
451
|
}
|
|
448
452
|
if (args.action === "app_url") {
|
package/dist/tools/pipeline.js
CHANGED
|
@@ -130,11 +130,11 @@ export const pipelineSchema = z.object({
|
|
|
130
130
|
model: z
|
|
131
131
|
.string()
|
|
132
132
|
.optional()
|
|
133
|
-
.describe("generate_carousel / generate_carousel_production:
|
|
133
|
+
.describe("generate_carousel / generate_carousel_production: a FORMA. Folha travada da casa ('feed', o padrão; 'reflexao'; 'case'), em que a espinha de slides vem do servidor e a IA (ou seus beats) só escreve a prosa, ou 'editorial' (a IA escolhe os layouts livremente). Ausente = o Feed."),
|
|
134
134
|
aspect: z
|
|
135
|
-
.enum(["
|
|
135
|
+
.enum(["4:5", "9:16"])
|
|
136
136
|
.optional()
|
|
137
|
-
.describe("generate_carousel: PROPORÇÃO da peça. Não confunda com `format` (que é o tipo da production: carrossel_ig, reels...) nem com `model` (que é a FORMA: quais beats, quais layouts). Aqui é o TAMANHO da folha: '
|
|
137
|
+
.describe("generate_carousel: PROPORÇÃO da peça. Não confunda com `format` (que é o tipo da production: carrossel_ig, reels...) nem com `model` (que é a FORMA: quais beats, quais layouts). Aqui é o TAMANHO da folha: '4:5' (default) é a folha que o feed do Instagram, o LinkedIn e o X mostram inteira; '9:16' ocupa a tela inteira do celular. Dá pra trocar depois no editor ou por update_carousel (theme.sheet)."),
|
|
138
138
|
beats: z
|
|
139
139
|
.union([
|
|
140
140
|
z.array(z.object({
|
package/dist/tools/studios.js
CHANGED
|
@@ -121,13 +121,13 @@ const STUDIOS = {
|
|
|
121
121
|
// tirinhas publicadas seguem de pé (/tirinha/<id>, cards na Comunidade).
|
|
122
122
|
"carrosel-editorial": {
|
|
123
123
|
name: "Carrossel Editorial",
|
|
124
|
-
description: "
|
|
124
|
+
description: "Carrossel do Instagram com layouts travados: modelos Feed, Reflexão e Case (9 slides) ou editorial livre, folha 4:5 ou 9:16, assinado com a marca de quem faz. O arquivo sai do navegador, no editor.",
|
|
125
125
|
url: `${APP}/experimentos/carrosel-editorial`,
|
|
126
126
|
status: "stable",
|
|
127
|
-
tags: ["carrossel", "instagram", "editorial"
|
|
127
|
+
tags: ["carrossel", "instagram", "editorial"],
|
|
128
128
|
convex: "carouselStandalone",
|
|
129
129
|
mcpReady: true,
|
|
130
|
-
mcpNote: "Coberto via
|
|
130
|
+
mcpNote: "Coberto via sapiens_carrossel (gerar, escrever os slides, pôr foto da galeria, capa IA), pra qualquer conta. Baixar é no editor.",
|
|
131
131
|
},
|
|
132
132
|
comunidade: {
|
|
133
133
|
name: "Comunidade Sapiens",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.85.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",
|