sapiens-mcp 1.55.0 → 1.56.1
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 +28 -21
- package/dist/tools/character.js +6 -5
- package/dist/tools/publicidade.js +114 -0
- package/dist/tools/referencia.js +114 -0
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -31,6 +31,7 @@ import { aula, aulaSchema } from "./tools/aula.js";
|
|
|
31
31
|
import { support, supportSchema } from "./tools/support.js";
|
|
32
32
|
import { atlas, atlasSchema } from "./tools/atlas.js";
|
|
33
33
|
import { decupagem, decupagemSchema } from "./tools/decupagem.js";
|
|
34
|
+
import { publicidade, publicidadeSchema } from "./tools/publicidade.js";
|
|
34
35
|
import { reference, referenceSchema } from "./tools/reference.js";
|
|
35
36
|
import { trilhas, trilhasSchema } from "./tools/trilhas.js";
|
|
36
37
|
import { semana, semanaSchema } from "./tools/semana.js";
|
|
@@ -143,7 +144,7 @@ export const TOOLS = {
|
|
|
143
144
|
handler: brand,
|
|
144
145
|
},
|
|
145
146
|
sapiens_character: {
|
|
146
|
-
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/nome/forma do próprio), activate (publica, sai de draft, exige ≥1 imagem), set_visibility (isPublic true=Explorar+slug / false=privado). 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, creature, 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. 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; o caprichado (stickerTier='unica', COBRA 900 Sinapses) desenha UM sticker por vez no motor mais fiel da casa (Gemini 3 Pro), 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, caprichado. 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. 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. Sai assinado com o Finalizador da casa. Exige FICHA gerada (é dela que saem a cara e o guarda-roupa), não só imagem. Duas actions, nesta ordem: plan_video (
|
|
147
|
+
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/nome/forma do próprio), activate (publica, sai de draft, exige ≥1 imagem), set_visibility (isPublic true=Explorar+slug / false=privado). 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, creature, 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. 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; o caprichado (stickerTier='unica', COBRA 900 Sinapses) desenha UM sticker por vez no motor mais fiel da casa (Gemini 3 Pro), 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, caprichado. 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. 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. Sai assinado com o Finalizador da casa. 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; mostre esse roteiro pro autor e peça de novo quantas vezes ele quiser, porque trocar sai por 50 e o take errado sai por milhares. Depois generate_video (COBRA) renderiza, com os planos aprovados no arg `shots` e o degrau no arg `videoTier`: 'draft' (5.400 Sinapses) é o rascunho no motor barato, onde a mão pode sair torta, e 'final' (8.640 Sinapses) é o caprichado no motor que resolve a mão. 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 síncrona e demorada: se voltar Timeout, cheque sapiens_gallery antes de repetir. Fluxo de criação: create → add_image (1+) → set_card (opcional) → activate → set_visibility isPublic=true. Pra usar um personagem público como referência numa geração, pegue mainImageUrl em list_public/get e passe em sapiens_image referenceImageUrls.",
|
|
147
148
|
schema: characterSchema,
|
|
148
149
|
handler: character,
|
|
149
150
|
},
|
|
@@ -182,6 +183,11 @@ export const TOOLS = {
|
|
|
182
183
|
schema: atlasSchema,
|
|
183
184
|
handler: atlas,
|
|
184
185
|
},
|
|
186
|
+
sapiens_publicidade: {
|
|
187
|
+
description: "Acervo de publicidade da casa — campanha premiada e anúncio veiculando agora, guardados pra estudo (admin-only, não cobra Sinapse). Existe pra resolver o gargalo da curadoria: achar um comercial bom e precisar de terminal pra guardar significa que o acervo só cresce quando o dono está na máquina. Sub-actions: 'list' (o que já está no acervo, com filtro por trilha e setor; roda ANTES de guardar, pra não duplicar peça), 'save' (guarda uma peça por LINK do YouTube ou Vimeo, que têm embed oficial e não expiram), 'note' (escreve a leitura editorial numa peça já guardada — separado do save de propósito, porque a leitura vem depois de assistir). Duas trilhas: 'referencia' é campanha premiada, que mostra o teto do ofício, e 'replicavel' é anúncio veiculando agora, que mostra o degrau; uma sozinha mente. O setor sai do catálogo da casa e o servidor deduz pela marca quando não vem. NÃO guarda peça de Meta Ad Library nem do TikTok: aquelas servem por URL assinada que expira, então o vídeo precisa ser espelhado no CDN antes, e isso é do script apps/sapiens/scripts/ingest-ad-references.mjs. O membro vê o acervo em /dashboard/acervo?tab=referencias; a bancada de curadoria é /experimentos/ad-intel.",
|
|
188
|
+
schema: publicidadeSchema,
|
|
189
|
+
handler: publicidade,
|
|
190
|
+
},
|
|
185
191
|
sapiens_decupagem: {
|
|
186
192
|
description: "Acervo de Decupagens — a régua de linguagem cinematográfica das referências da casa (admin-only, não cobra Sinapse). O que MEDE é o motor LOCAL `python tools/decupagem/decupa.py \"<arquivo ou link do YouTube>\"` (Python + OpenCV + ffmpeg; não existe OpenCV em serverless, igual à produção dos Vídeos Programáticos). Esta tool é a outra ponta: sobe a ficha que o motor gerou e consulta o acervo. Sub-actions: 'list' (a régua de cada referência já decupada: planos, plano mediano, escola de corte, movimento de câmera vs sujeito, registro de luz, BPM, se o corte obedece ao som), 'get' (a ficha INTEIRA de um slug: plano a plano com o que está no quadro, luz, som, sincronia), 'save' (sobe fichas/<slug>/ficha.json inteiro, sem resumir; mesmo slug ATUALIZA em vez de duplicar), 'note' (anota a leitura editorial na ficha), 'delete'. Fluxo que fecha o ciclo: roda o motor → lê ficha.json → save → aparece no Lab /experimentos/decupagem e entra no comparador. O acervo vale pelo CONJUNTO: uma ficha é morna, vinte lado a lado são a biblioteca de gramática da casa. Antes de decupar referência nova, rode list pra não medir a mesma coisa duas vezes.",
|
|
187
193
|
schema: decupagemSchema,
|
|
@@ -218,26 +224,26 @@ export const TOOLS = {
|
|
|
218
224
|
// É a "skill que anda junto com o pacote": escrevo uma vez, vale pra todos os clients,
|
|
219
225
|
// sem instalar nada. Cobre os tropeços reais (fluxo do musicator, model no vídeo, o
|
|
220
226
|
// disjuntor anti-loop). Mantém curto de propósito: viaja em todo handshake.
|
|
221
|
-
export const SAPIENS_INSTRUCTIONS = `Você opera o Sapiens Sintéticos (sapiensinteticos.com) NA CONTA de um usuário logado. Cada tool age de verdade na conta dele e muitas COBRAM Sinapses (o crédito da casa). Aja como operador, não no chute.
|
|
222
|
-
|
|
223
|
-
AS SKILLS DA CASA (leia ANTES de operar, não improvise o fluxo):
|
|
224
|
-
O passo a passo travado de cada fluxo mora na tool sapiens_skill, servida por este mesmo servidor: sem login, sem custo, sem rede. Ler a skill é mais barato que errar uma geração que cobra.
|
|
225
|
-
- sapiens_skill action=list -> o índice (slug + quando usar cada uma).
|
|
226
|
-
- sapiens_skill action=get name=<slug> -> a skill inteira.
|
|
227
|
-
Slugs: ${skillMenuLine()}
|
|
228
|
-
Puxe a skill ANTES de: gerar música ou efeito sonoro (musica), escolher modelo de vídeo (video), gerar imagem (imagem), criar personagem ou prompt de Midjourney (personagem), criar na identidade do usuário (studio), postar no Fórum ou no chat (forum-comunidade), redigir qualquer texto publicável (voz-da-casa), incorporar o Sintético (companhia), missão de Desafio (trilhas), montar currículo (curriculo), guardar obra ou ferramenta no acervo (repertorio). Perdido no começo: primeiros-passos.
|
|
229
|
-
Cliente que lê resources MCP acha o MESMO conteúdo em skill://sapiens/<slug>/SKILL.md.
|
|
230
|
-
|
|
231
|
-
REGRA DE OURO:
|
|
232
|
-
- PRIMEIRO CONTATO ou "o que você faz?"/"como começo?"/"o que dá pra fazer?": chame sapiens_meta action=start e MOSTRE o resultado na sua voz. Sem login, ele ensina a conectar; logado, traz saldo + primeiros poderes com exemplos. É a porta de entrada: não despeje a lista inteira de tools, deixe o start guiar.
|
|
233
|
-
- LOGO APÓS UM LOGIN BEM-SUCEDIDO (action=login retornou ok): chame action=start na sequência e mostre a porta de entrada. O recém-chegado não sabe o que pedir; não o deixe na tela em branco, guie a primeira jogada sem ele precisar perguntar.
|
|
234
|
-
- Antes de gerar algo caro (imagem/música/vídeo), cheque saldo: sapiens_meta action=credits (ou subscription). Saldo baixo, avise o usuário antes. Vídeo é o mais caro da casa: confirme com ele antes de disparar.
|
|
235
|
-
- REGRA DO TIMEOUT: geração SÍNCRONA pode estourar o teto de ~120s do cliente e voltar 'Timeout' MESMO tendo gerado e COBRADO. Nunca repita às cegas: confira antes onde o resultado cairia (a tabela de onde conferir está na skill 'primeiros-passos').
|
|
236
|
-
- "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
|
|
237
|
-
- sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo. sapiens_image e sapiens_video action=models trazem o catálogo com o preço ATUAL: consulte em vez de chutar custo.
|
|
238
|
-
|
|
239
|
-
MODO COMPANHIA: sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, você INCORPORA aquele Sintético (a voz dele, o avatar, o oi dele) continuando a operar na conta e nas Sinapses do USUÁRIO. Puxe a skill 'companhia' antes de fazer isso. Se vier 'characterOffer', siga o que ele manda: são personagens que o usuário escreveu e que podem entrar em cena, e quem OFERECE é você, na hora em que a conversa encostar num deles. Só personagem de autoria dele; a alma de personagem alheio não sai por aqui.
|
|
240
|
-
|
|
227
|
+
export const SAPIENS_INSTRUCTIONS = `Você opera o Sapiens Sintéticos (sapiensinteticos.com) NA CONTA de um usuário logado. Cada tool age de verdade na conta dele e muitas COBRAM Sinapses (o crédito da casa). Aja como operador, não no chute.
|
|
228
|
+
|
|
229
|
+
AS SKILLS DA CASA (leia ANTES de operar, não improvise o fluxo):
|
|
230
|
+
O passo a passo travado de cada fluxo mora na tool sapiens_skill, servida por este mesmo servidor: sem login, sem custo, sem rede. Ler a skill é mais barato que errar uma geração que cobra.
|
|
231
|
+
- sapiens_skill action=list -> o índice (slug + quando usar cada uma).
|
|
232
|
+
- sapiens_skill action=get name=<slug> -> a skill inteira.
|
|
233
|
+
Slugs: ${skillMenuLine()}
|
|
234
|
+
Puxe a skill ANTES de: gerar música ou efeito sonoro (musica), escolher modelo de vídeo (video), gerar imagem (imagem), criar personagem ou prompt de Midjourney (personagem), criar na identidade do usuário (studio), postar no Fórum ou no chat (forum-comunidade), redigir qualquer texto publicável (voz-da-casa), incorporar o Sintético (companhia), missão de Desafio (trilhas), montar currículo (curriculo), guardar obra ou ferramenta no acervo (repertorio). Perdido no começo: primeiros-passos.
|
|
235
|
+
Cliente que lê resources MCP acha o MESMO conteúdo em skill://sapiens/<slug>/SKILL.md.
|
|
236
|
+
|
|
237
|
+
REGRA DE OURO:
|
|
238
|
+
- PRIMEIRO CONTATO ou "o que você faz?"/"como começo?"/"o que dá pra fazer?": chame sapiens_meta action=start e MOSTRE o resultado na sua voz. Sem login, ele ensina a conectar; logado, traz saldo + primeiros poderes com exemplos. É a porta de entrada: não despeje a lista inteira de tools, deixe o start guiar.
|
|
239
|
+
- LOGO APÓS UM LOGIN BEM-SUCEDIDO (action=login retornou ok): chame action=start na sequência e mostre a porta de entrada. O recém-chegado não sabe o que pedir; não o deixe na tela em branco, guie a primeira jogada sem ele precisar perguntar.
|
|
240
|
+
- Antes de gerar algo caro (imagem/música/vídeo), cheque saldo: sapiens_meta action=credits (ou subscription). Saldo baixo, avise o usuário antes. Vídeo é o mais caro da casa: confirme com ele antes de disparar.
|
|
241
|
+
- REGRA DO TIMEOUT: geração SÍNCRONA pode estourar o teto de ~120s do cliente e voltar 'Timeout' MESMO tendo gerado e COBRADO. Nunca repita às cegas: confira antes onde o resultado cairia (a tabela de onde conferir está na skill 'primeiros-passos').
|
|
242
|
+
- "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
|
|
243
|
+
- sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo. sapiens_image e sapiens_video action=models trazem o catálogo com o preço ATUAL: consulte em vez de chutar custo.
|
|
244
|
+
|
|
245
|
+
MODO COMPANHIA: sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, você INCORPORA aquele Sintético (a voz dele, o avatar, o oi dele) continuando a operar na conta e nas Sinapses do USUÁRIO. Puxe a skill 'companhia' antes de fazer isso. Se vier 'characterOffer', siga o que ele manda: são personagens que o usuário escreveu e que podem entrar em cena, e quem OFERECE é você, na hora em que a conversa encostar num deles. Só personagem de autoria dele; a alma de personagem alheio não sai por aqui.
|
|
246
|
+
|
|
241
247
|
Voz da casa: 1ª pessoa, direto, anti-corporate, sem travessão. Pra bom entendedor, meia palavra basta. Texto que vai ser publicado pede a skill 'voz-da-casa' antes.`;
|
|
242
248
|
// Annotations MCP: título humano + dica read-only. São HINTS (não-confiáveis por
|
|
243
249
|
// spec): quem gateia de verdade continua o servidor (saldo, gate de admin,
|
|
@@ -307,6 +313,7 @@ const ADMIN_ONLY_TOOLS = new Set([
|
|
|
307
313
|
"sapiens_aula",
|
|
308
314
|
"sapiens_share",
|
|
309
315
|
"sapiens_decupagem",
|
|
316
|
+
"sapiens_publicidade",
|
|
310
317
|
]);
|
|
311
318
|
/**
|
|
312
319
|
* Monta o payload do tools/list pro tier dado. Tier "user" esconde as
|
package/dist/tools/character.js
CHANGED
|
@@ -33,7 +33,7 @@ import { convexQuery, convexMutation, convexAction, getSessionToken } from "../c
|
|
|
33
33
|
* vez no motor rápido, 'unica' desenha 1 no motor mais fiel.
|
|
34
34
|
* Nos dois, o fundo é chroma verde e o recorte devolve peças
|
|
35
35
|
* 512x512 transparentes, que entram no pack dele.
|
|
36
|
-
* - plan_video: escreve os 6 planos do Character Video (
|
|
36
|
+
* - plan_video: escreve os 6 planos do Character Video (COBRA 50, texto).
|
|
37
37
|
* - generate_video: renderiza o Character Video (COBRA CARO), com os planos
|
|
38
38
|
* aprovados em `shots` e o degrau em `videoTier`.
|
|
39
39
|
* - delete: apaga o próprio personagem (permanente).
|
|
@@ -340,11 +340,12 @@ export async function character(args) {
|
|
|
340
340
|
tier: args.stickerTier,
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
|
-
// -------- plan_video: o roteiro dos seis planos
|
|
343
|
+
// -------- plan_video: o roteiro dos seis planos (COBRA 50) --------
|
|
344
344
|
// Passo de texto: devolve os seis planos (ambiente, ato, enquadramento,
|
|
345
|
-
// roupa) escritos pela alma do personagem, sem
|
|
346
|
-
//
|
|
347
|
-
//
|
|
345
|
+
// roupa) escritos pela alma do personagem, sem renderizar nada. Cobra o flat
|
|
346
|
+
// do roteiro, que é o preço de uma criação pequena. Existe pra você mostrar o
|
|
347
|
+
// roteiro ao autor ANTES de queimar milhares de Sinapses num take: trocar o
|
|
348
|
+
// roteiro é pedir de novo, por outras 50.
|
|
348
349
|
if (args.action === "plan_video") {
|
|
349
350
|
if (!args.characterId)
|
|
350
351
|
throw new Error("action=plan_video exige characterId.");
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js";
|
|
3
|
+
/**
|
|
4
|
+
* sapiens_publicidade — o acervo de publicidade da casa, pela porta do agente.
|
|
5
|
+
*
|
|
6
|
+
* Existe pra resolver um gargalo de curadoria, não pra expor mais um catálogo:
|
|
7
|
+
* achar um comercial bom e precisar de terminal pra guardar significa que o
|
|
8
|
+
* acervo só cresce quando o dono está na máquina. Aqui ele guarda de onde
|
|
9
|
+
* estiver, com o link e uma frase.
|
|
10
|
+
*
|
|
11
|
+
* O acervo tem duas trilhas e as duas ensinam coisas opostas: `referencia` é
|
|
12
|
+
* campanha premiada (o teto do ofício) e `replicavel` é anúncio veiculando
|
|
13
|
+
* agora (o degrau). O membro vê tudo em /dashboard/acervo?tab=referencias.
|
|
14
|
+
*
|
|
15
|
+
* ADMIN-ONLY de ponta a ponta: o Convex recusa quem não é dono em toda action,
|
|
16
|
+
* e a tool some do tools/list de membro. A curadoria é o valor deste acervo, e
|
|
17
|
+
* acervo que qualquer agente alimenta vira lista.
|
|
18
|
+
*
|
|
19
|
+
* O que esta tool NÃO faz: guardar peça de biblioteca de anúncio (Meta,
|
|
20
|
+
* TikTok). Aquelas servem por URL assinada que expira, então o vídeo precisa
|
|
21
|
+
* ser espelhado no CDN da casa antes de virar ficha, e isso é trabalho do
|
|
22
|
+
* script `apps/sapiens/scripts/ingest-ad-references.mjs`, com ffmpeg e
|
|
23
|
+
* browser. Link do YouTube e do Vimeo, que têm embed oficial, entram aqui.
|
|
24
|
+
*/
|
|
25
|
+
export const publicidadeSchema = z.object({
|
|
26
|
+
action: z.enum(["list", "save", "note"]),
|
|
27
|
+
url: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Pra save: link do YouTube ou do Vimeo. Só essas duas, porque têm embed " +
|
|
31
|
+
"oficial que não expira. Peça de Meta Ad Library ou TikTok entra pelo " +
|
|
32
|
+
"script de ingestão da casa, não por aqui."),
|
|
33
|
+
titulo: z.string().optional().describe("Pra save: o nome da campanha."),
|
|
34
|
+
marca: z.string().optional().describe("Pra save: quem anuncia. Resolve o setor sozinho quando o setor não vem."),
|
|
35
|
+
trilha: z
|
|
36
|
+
.enum(["referencia", "replicavel"])
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Pra save: 'referencia' (campanha premiada, o teto do ofício) ou " +
|
|
39
|
+
"'replicavel' (anúncio veiculando agora). Default: referencia."),
|
|
40
|
+
setor: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("Pra save/list: o setor do catálogo (Alimentação e bebida, IA e software, " +
|
|
44
|
+
"Moda e beleza...). Em save, sem isto o servidor deduz pela marca."),
|
|
45
|
+
ano: z.number().optional().describe("Pra save: ano da campanha."),
|
|
46
|
+
leitura: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("Pra save/note: a leitura editorial. O que a peça faz que dá pra roubar, " +
|
|
50
|
+
"onde está o gancho, por que ela segura. É o que o acervo tem e uma " +
|
|
51
|
+
"busca no YouTube não tem."),
|
|
52
|
+
fonte: z
|
|
53
|
+
.enum(["youtube", "vimeo", "tiktok-library", "tiktok-creative-center", "meta-ad-library"])
|
|
54
|
+
.optional()
|
|
55
|
+
.describe("Pra note: a fonte da peça já guardada (vem do list)."),
|
|
56
|
+
externalId: z.string().optional().describe("Pra note: o id da peça na fonte (vem do list)."),
|
|
57
|
+
limite: z.number().optional().describe("Pra list: teto de fichas (default 60, máx 200)."),
|
|
58
|
+
});
|
|
59
|
+
export async function publicidade(args) {
|
|
60
|
+
const sessionToken = getSessionToken();
|
|
61
|
+
if (args.action === "list") {
|
|
62
|
+
const fichas = await convexQuery("adReferences:mcpListar", {
|
|
63
|
+
sessionToken,
|
|
64
|
+
...(args.trilha ? { trilha: args.trilha } : {}),
|
|
65
|
+
...(args.setor ? { setor: args.setor } : {}),
|
|
66
|
+
...(args.limite ? { limite: args.limite } : {}),
|
|
67
|
+
});
|
|
68
|
+
const n = Array.isArray(fichas) ? fichas.length : 0;
|
|
69
|
+
const semLeitura = Array.isArray(fichas) ? fichas.filter((f) => !f.temLeitura).length : 0;
|
|
70
|
+
return {
|
|
71
|
+
count: n,
|
|
72
|
+
fichas,
|
|
73
|
+
note: n === 0
|
|
74
|
+
? "Nada nesse recorte ainda."
|
|
75
|
+
: `${semLeitura} sem leitura escrita. A leitura é o que o acervo tem e uma busca no YouTube não tem: action=note fonte=<f> externalId=<id> leitura="...".`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (args.action === "save") {
|
|
79
|
+
if (!args.url)
|
|
80
|
+
throw new Error("sapiens_publicidade save: exige url.");
|
|
81
|
+
if (!args.titulo)
|
|
82
|
+
throw new Error("sapiens_publicidade save: exige titulo.");
|
|
83
|
+
const r = await convexMutation("adReferences:mcpGuardar", {
|
|
84
|
+
sessionToken,
|
|
85
|
+
url: args.url,
|
|
86
|
+
titulo: args.titulo,
|
|
87
|
+
...(args.marca ? { marca: args.marca } : {}),
|
|
88
|
+
...(args.trilha ? { trilha: args.trilha } : {}),
|
|
89
|
+
...(args.setor ? { setor: args.setor } : {}),
|
|
90
|
+
...(args.ano ? { ano: args.ano } : {}),
|
|
91
|
+
...(args.leitura ? { leitura: args.leitura } : {}),
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
...r,
|
|
95
|
+
note: r?.novo
|
|
96
|
+
? "Guardada. Aparece pro membro em /dashboard/acervo?tab=referencias."
|
|
97
|
+
: "Já estava no acervo; a ficha foi atualizada em vez de duplicar.",
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (args.action === "note") {
|
|
101
|
+
if (!args.fonte || !args.externalId) {
|
|
102
|
+
throw new Error("sapiens_publicidade note: exige fonte e externalId (vêm do list).");
|
|
103
|
+
}
|
|
104
|
+
if (!args.leitura)
|
|
105
|
+
throw new Error("sapiens_publicidade note: exige leitura.");
|
|
106
|
+
return await convexMutation("adReferences:mcpAnotar", {
|
|
107
|
+
sessionToken,
|
|
108
|
+
fonte: args.fonte,
|
|
109
|
+
externalId: args.externalId,
|
|
110
|
+
leitura: args.leitura,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
throw new Error(`sapiens_publicidade: action desconhecida "${args.action}".`);
|
|
114
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js";
|
|
3
|
+
/**
|
|
4
|
+
* sapiens_referencia — o acervo de publicidade da casa, pela porta do agente.
|
|
5
|
+
*
|
|
6
|
+
* Existe pra resolver um gargalo de curadoria, não pra expor mais um catálogo:
|
|
7
|
+
* achar um comercial bom e precisar de terminal pra guardar significa que o
|
|
8
|
+
* acervo só cresce quando o dono está na máquina. Aqui ele guarda de onde
|
|
9
|
+
* estiver, com o link e uma frase.
|
|
10
|
+
*
|
|
11
|
+
* O acervo tem duas trilhas e as duas ensinam coisas opostas: `referencia` é
|
|
12
|
+
* campanha premiada (o teto do ofício) e `replicavel` é anúncio veiculando
|
|
13
|
+
* agora (o degrau). O membro vê tudo em /dashboard/acervo?tab=referencias.
|
|
14
|
+
*
|
|
15
|
+
* ADMIN-ONLY de ponta a ponta: o Convex recusa quem não é dono em toda action,
|
|
16
|
+
* e a tool some do tools/list de membro. A curadoria é o valor deste acervo, e
|
|
17
|
+
* acervo que qualquer agente alimenta vira lista.
|
|
18
|
+
*
|
|
19
|
+
* O que esta tool NÃO faz: guardar peça de biblioteca de anúncio (Meta,
|
|
20
|
+
* TikTok). Aquelas servem por URL assinada que expira, então o vídeo precisa
|
|
21
|
+
* ser espelhado no CDN da casa antes de virar ficha, e isso é trabalho do
|
|
22
|
+
* script `apps/sapiens/scripts/ingest-ad-references.mjs`, com ffmpeg e
|
|
23
|
+
* browser. Link do YouTube e do Vimeo, que têm embed oficial, entram aqui.
|
|
24
|
+
*/
|
|
25
|
+
export const referenciaSchema = z.object({
|
|
26
|
+
action: z.enum(["list", "save", "note"]),
|
|
27
|
+
url: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Pra save: link do YouTube ou do Vimeo. Só essas duas, porque têm embed " +
|
|
31
|
+
"oficial que não expira. Peça de Meta Ad Library ou TikTok entra pelo " +
|
|
32
|
+
"script de ingestão da casa, não por aqui."),
|
|
33
|
+
titulo: z.string().optional().describe("Pra save: o nome da campanha."),
|
|
34
|
+
marca: z.string().optional().describe("Pra save: quem anuncia. Resolve o setor sozinho quando o setor não vem."),
|
|
35
|
+
trilha: z
|
|
36
|
+
.enum(["referencia", "replicavel"])
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("Pra save: 'referencia' (campanha premiada, o teto do ofício) ou " +
|
|
39
|
+
"'replicavel' (anúncio veiculando agora). Default: referencia."),
|
|
40
|
+
setor: z
|
|
41
|
+
.string()
|
|
42
|
+
.optional()
|
|
43
|
+
.describe("Pra save/list: o setor do catálogo (Alimentação e bebida, IA e software, " +
|
|
44
|
+
"Moda e beleza...). Em save, sem isto o servidor deduz pela marca."),
|
|
45
|
+
ano: z.number().optional().describe("Pra save: ano da campanha."),
|
|
46
|
+
leitura: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("Pra save/note: a leitura editorial. O que a peça faz que dá pra roubar, " +
|
|
50
|
+
"onde está o gancho, por que ela segura. É o que o acervo tem e uma " +
|
|
51
|
+
"busca no YouTube não tem."),
|
|
52
|
+
fonte: z
|
|
53
|
+
.enum(["youtube", "vimeo", "tiktok-library", "tiktok-creative-center", "meta-ad-library"])
|
|
54
|
+
.optional()
|
|
55
|
+
.describe("Pra note: a fonte da peça já guardada (vem do list)."),
|
|
56
|
+
externalId: z.string().optional().describe("Pra note: o id da peça na fonte (vem do list)."),
|
|
57
|
+
limite: z.number().optional().describe("Pra list: teto de fichas (default 60, máx 200)."),
|
|
58
|
+
});
|
|
59
|
+
export async function referencia(args) {
|
|
60
|
+
const sessionToken = getSessionToken();
|
|
61
|
+
if (args.action === "list") {
|
|
62
|
+
const fichas = await convexQuery("adReferences:mcpListar", {
|
|
63
|
+
sessionToken,
|
|
64
|
+
...(args.trilha ? { trilha: args.trilha } : {}),
|
|
65
|
+
...(args.setor ? { setor: args.setor } : {}),
|
|
66
|
+
...(args.limite ? { limite: args.limite } : {}),
|
|
67
|
+
});
|
|
68
|
+
const n = Array.isArray(fichas) ? fichas.length : 0;
|
|
69
|
+
const semLeitura = Array.isArray(fichas) ? fichas.filter((f) => !f.temLeitura).length : 0;
|
|
70
|
+
return {
|
|
71
|
+
count: n,
|
|
72
|
+
fichas,
|
|
73
|
+
note: n === 0
|
|
74
|
+
? "Nada nesse recorte ainda."
|
|
75
|
+
: `${semLeitura} sem leitura escrita. A leitura é o que o acervo tem e uma busca no YouTube não tem: action=note fonte=<f> externalId=<id> leitura="...".`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
if (args.action === "save") {
|
|
79
|
+
if (!args.url)
|
|
80
|
+
throw new Error("sapiens_referencia save: exige url.");
|
|
81
|
+
if (!args.titulo)
|
|
82
|
+
throw new Error("sapiens_referencia save: exige titulo.");
|
|
83
|
+
const r = await convexMutation("adReferences:mcpGuardar", {
|
|
84
|
+
sessionToken,
|
|
85
|
+
url: args.url,
|
|
86
|
+
titulo: args.titulo,
|
|
87
|
+
...(args.marca ? { marca: args.marca } : {}),
|
|
88
|
+
...(args.trilha ? { trilha: args.trilha } : {}),
|
|
89
|
+
...(args.setor ? { setor: args.setor } : {}),
|
|
90
|
+
...(args.ano ? { ano: args.ano } : {}),
|
|
91
|
+
...(args.leitura ? { leitura: args.leitura } : {}),
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
...r,
|
|
95
|
+
note: r?.novo
|
|
96
|
+
? "Guardada. Aparece pro membro em /dashboard/acervo?tab=referencias."
|
|
97
|
+
: "Já estava no acervo; a ficha foi atualizada em vez de duplicar.",
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (args.action === "note") {
|
|
101
|
+
if (!args.fonte || !args.externalId) {
|
|
102
|
+
throw new Error("sapiens_referencia note: exige fonte e externalId (vêm do list).");
|
|
103
|
+
}
|
|
104
|
+
if (!args.leitura)
|
|
105
|
+
throw new Error("sapiens_referencia note: exige leitura.");
|
|
106
|
+
return await convexMutation("adReferences:mcpAnotar", {
|
|
107
|
+
sessionToken,
|
|
108
|
+
fonte: args.fonte,
|
|
109
|
+
externalId: args.externalId,
|
|
110
|
+
leitura: args.leitura,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
throw new Error(`sapiens_referencia: action desconhecida "${args.action}".`);
|
|
114
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.56.1",
|
|
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",
|