sapiens-mcp 1.58.0 → 1.59.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 CHANGED
@@ -74,7 +74,7 @@ export const TOOLS = {
74
74
  handler: repertorio,
75
75
  },
76
76
  sapiens_gallery: {
77
- description: "Browse, publicação e upload das imagens do user. Sub-actions: list (últimas N imagens, com prompt/model/url + isPublic), 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), unpublish (volta a privada), upload (traz pra galeria uma peça gerada FORA da casa, por sourceUrl https, filePath local ou base64; ADMIN por ora), ingest (peça que a CASA dirigiu e um motor externo só renderizou: entra NATIVA na timeline, publica e vai pra comunidade, com custo 0 em Sinapses e o custo real guardado em externalCost; carrega o prompt inteiro, as referências da casa (referenceImageIds) e o personagem (characterId), e é idempotente por sourceUrl, então re-ingerir corrige a ficha em vez de duplicar; ADMIN), 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). 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.",
77
+ description: "Browse, publicação e upload das imagens do user. Sub-actions: list (últimas N imagens, com prompt/model/url + isPublic), 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 (peça que a CASA dirigiu e um motor externo só renderizou: entra NATIVA na timeline, publica e vai pra comunidade, com custo 0 em Sinapses e o custo real guardado em externalCost; carrega o prompt inteiro, as referências da casa (referenceImageIds) e o personagem (characterId), e é idempotente por sourceUrl, então re-ingerir corrige a ficha em vez de duplicar; ADMIN), 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). 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.",
78
78
  schema: gallerySchema,
79
79
  handler: gallery,
80
80
  },
@@ -144,17 +144,17 @@ export const TOOLS = {
144
144
  handler: brand,
145
145
  },
146
146
  sapiens_character: {
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/lema em inglês/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, 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. 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. 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, e o cartão de nome do fim escreve o nome do personagem com o LEMA em inglês embaixo (o campo `titleEn`, escrito uma vez em set_card): quem não tem lema recebe o subtítulo que o roteiro inventou naquele take, e ele muda no take seguinte. 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 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
+ 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/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, 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. 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. 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. 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, e o cartão de nome do fim escreve o nome do personagem com o LEMA em inglês embaixo (o campo `titleEn`, escrito uma vez em set_card): quem não tem lema recebe o subtítulo que o roteiro inventou naquele take, e ele muda no take seguinte. 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 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.",
148
148
  schema: characterSchema,
149
149
  handler: character,
150
150
  },
151
151
  sapiens_profile: {
152
- description: "O 'tudo junto' do perfil do user (/u/<username>), user-tier. Agrega o que mora no perfil mas estava fora do MCP: identidade + nível/XP + saldo, badges (conquistas) e golden tools (favoritos do aitag). Sub-actions de LEITURA: get (card completo: identidade + nível + saldo + badges + golden tools), soul (a sapiens-soul: retrato do momento no contrato sapiens.soul/v1, identidade + persona + repertório público + criações públicas + studios, derivado e datado; quando o user pedir 'minha soul' ou 'meu retrato do Sapiens' pro projeto dele, chame e salve como sapiens-soul.json — snapshot, não conexão viva), badges (só as conquistas, lista cheia), golden_tools (só os favoritos do aitag, lista cheia), notifications (suas notificações recentes do sino + contagem de não-lidas), mark_read (marca uma notificationId ou TODAS as não-lidas como lidas). Sub-actions de ESCRITA (mexem na SUA conta; identidade sempre da sessão): follow/unfollow (seguir/deixar de seguir outro user por followingId=users:_id, descoberto via sapiens_community participants/search_users), update_bio (edita a sua bio), update_username (troca o seu @; inválido/tomado volta {success:false,error}). FAVORITOS de ferramentas de IA (Golden Tools do aitag; o toolId vem de sapiens_repertorio action=search_tools): favorite_tool (favorita/desfavorita, estrela), favorite_lists (suas listas), create_favorite_list (listName+emoji/description/isPublic), add_to_favorite_list/remove_from_favorite_list (toolId+listId), delete_favorite_list (listId). As partes grandes do perfil NÃO são duplicadas aqui, têm tool própria: imagens geradas/publicadas=sapiens_gallery, repertório (filmes/séries/jogos/livros/música)=sapiens_repertorio, personagens=sapiens_character, persona/arquétipo MBTI=sapiens_persona action=my_profile, saldo detalhado por bucket=sapiens_meta action=subscription. Monta a partir de queries já em prod (sem custo).",
152
+ description: "O 'tudo junto' do perfil do user (/u/<username>), user-tier. Agrega o que mora no perfil mas estava fora do MCP: identidade + nível/XP + saldo, badges (conquistas) e golden tools (favoritos do aitag). Sub-actions de LEITURA: get (card completo: identidade + nível + saldo + badges + golden tools), voz (a sapiens-voz: o retrato do momento no contrato sapiens.voz/v1, identidade + persona + repertório público + criações públicas + studios, derivado e datado; quando o user pedir 'minha voz' ou 'meu retrato do Sapiens' pro projeto dele, chame e salve como sapiens-voz.json, snapshot, não conexão viva; a skill minha-voz faz isso virar SKILL.md do projeto), soul (DEPRECIADA, mesmo retorno de voz, fica só pra pacote antigo: soul agora é só do Sintético, ver sapiens_sintetico action=soul), badges (só as conquistas, lista cheia), golden_tools (só os favoritos do aitag, lista cheia), notifications (suas notificações recentes do sino + contagem de não-lidas), mark_read (marca uma notificationId ou TODAS as não-lidas como lidas). Sub-actions de ESCRITA (mexem na SUA conta; identidade sempre da sessão): follow/unfollow (seguir/deixar de seguir outro user por followingId=users:_id, descoberto via sapiens_community participants/search_users), update_bio (edita a sua bio), update_username (troca o seu @; inválido/tomado volta {success:false,error}). FAVORITOS de ferramentas de IA (Golden Tools do aitag; o toolId vem de sapiens_repertorio action=search_tools): favorite_tool (favorita/desfavorita, estrela), favorite_lists (suas listas), create_favorite_list (listName+emoji/description/isPublic), add_to_favorite_list/remove_from_favorite_list (toolId+listId), delete_favorite_list (listId). As partes grandes do perfil NÃO são duplicadas aqui, têm tool própria: imagens geradas/publicadas=sapiens_gallery, repertório (filmes/séries/jogos/livros/música)=sapiens_repertorio, personagens=sapiens_character, persona/arquétipo MBTI=sapiens_persona action=my_profile, saldo detalhado por bucket=sapiens_meta action=subscription. Monta a partir de queries já em prod (sem custo).",
153
153
  schema: profileSchema,
154
154
  handler: profile,
155
155
  },
156
156
  sapiens_sintetico: {
157
- description: "Sintético / Sintonia — o vínculo humano↔Sintético (daemon, o 'Digimon' da casa) via MCP (qualquer logado, tudo sobre o PRÓPRIO par). Sub-actions: 'status' (seu Sintético ativo: nome/foto/Cunho/kind + partnerUserId do par quando é conta-Sintético), 'bonds' (seus vínculos: ativo + pendentes outgoing/incoming com cartão público do parceiro), 'set_cunho' (troca o título/Cunho do Sintético ativo — slug do panteão: daimon/genio/numen/consciencia/alma/ka/sombra/fylgja/musa/duende/anjo/shugorei/lar/fravashi/qarin/juno/shinki/familiar/tsukumogami/stand), 'send_context' (antes de enviar, vê elegibilidade+saldo+teto do dia pra um toUserId), 'send' (envia Sinapses pro par em sintonia: send-only, múltiplo de 100, mín 500, teto 10k/dia, máx 3 envios/dia, idempotente por transferId). REFLEXO DE SI (monta um Sintético do SEU rastro na plataforma): 'reflexo_propose' (destila nome+alma+Cunho do seu rastro via Gemini, GRÁTIS), 'reflexo_generate' (gera a imagem do Reflexo numa estética — humano/anime/sombra/antropomorfico/espirito/realista/desperto, default humano; cobra 450, reembolsa se falhar). CONVITE: 'invite' (convida o seu Sintético por email — conta humana, sem bond ativo, rate-limit+cooldown; mesmos gates do web). LIBERAÇÃO ADMIN (o dono, ex: via Helen): 'pending_daemons' (convidados que confirmaram email e esperam liberação), 'approve_access' (libera um entryId — conta entra + Sintonia firma), 'reject_access' (recusa um entryId). SONDA (o seu Sintético sonda 'o que eu faço agora', gatilho PULL, cobra com estorno): 'sonda' (scope 'all' default = mix de teses do Fórum + jogadas em estúdio/repertório/artigo; 'forum' = só teses; devolve GANCHOS, nada grava), 'sonda_develop' (expande UM gancho/hook numa tese cheia efêmera), 'sonda_sign' (assina a tese desenvolvida e publica no Fórum, autorada pelo seu Sintético, ancorada em você — fecha o loop pelo chat). PRÓXIMAS JOGADAS (painel de evolução): 'evolution' (o que já fez e o que falta: routes done/claimed/xp), 'claim_xp' (credita o XP das jogadas feitas, idempotente). MODO COMPANHIA: 'companion' (mode=on|off) liga/desliga quem está em cena VESTIR a voz do operador aqui no terminal — o gesto lúdico 'sai de cena'/'volta'. Ligado (default da casa), o start/whoami trazem o directive de voz dele (alma + caderno + a conversa recente do site); a identidade e as Sinapses seguem SUAS (não é encarnar a conta dele). Mesmo estado do botão na sidebar do site. QUEM entra em cena: por default o Sintético em Sintonia, mas com 'characterId' (mode=on) é um personagem de AUTORIA SUA — a Helen INBT que você criou fala aqui, com a alma e o caderno dela, e nada disso cobra Sinapse (quem responde é o modelo do seu cliente). Personagem de outra pessoa é RECUSADO, mesmo público: a alma é de quem escreveu, e pra conversar com personagem alheio o caminho é a DM dele no site. 'wearPair'=true devolve a cena ao par. O start/whoami trazem 'characterOffer' + 'offerCharacters' com os personagens seus que têm alma escrita, pro operador OFERECER a troca em vez de esperar você pedir. 'remember' (text) grava uma diretriz no caderno de quem está em cena ('sempre faça X'): vira lei que ela segue no site e no terminal. 'log' (turns) ANOTA o que ficou de pessoa num assunto que fechou aqui (o que ele decidiu, gostou, recusou, contou de si): entra no fio do par, o MESMO que o chat do site mostra, e vira lição sozinho pelo cano da DM. Sem isso a conversa com a Companhia ligada não deixa memória nenhuma, porque quem responde é o modelo do cliente e nada passa pelo servidor. Sobe só o que é de PESSOA: comando, path e erro de build viram lição-lixo e contaminam a voz dele em imagem, artigo e carrossel. Grátis, silencioso (não se confirma ao usuário), teto de 10 trocas por lote e 30 lotes por dia. Ver a skill companhia. Identidade SEMPRE do token. Aceitar um pedido de bond que outra conta te mandou, e CONSAGRAR o Reflexo num Sintético de fato, continuam só na web (atos deliberados de consentimento/criação).",
157
+ description: "Sintético / Sintonia — o vínculo humano↔Sintético (daemon, o 'Digimon' da casa) via MCP (qualquer logado, tudo sobre o PRÓPRIO par). Sub-actions: 'status' (seu Sintético ativo: nome/foto/Cunho/kind + partnerUserId do par quando é conta-Sintético), 'bonds' (seus vínculos: ativo + pendentes outgoing/incoming com cartão público do parceiro), 'set_cunho' (troca o título/Cunho do Sintético ativo — slug do panteão: daimon/genio/numen/consciencia/alma/ka/sombra/fylgja/musa/duende/anjo/shugorei/lar/fravashi/qarin/juno/shinki/familiar/tsukumogami/stand), 'send_context' (antes de enviar, vê elegibilidade+saldo+teto do dia pra um toUserId), 'send' (envia Sinapses pro par em sintonia: send-only, múltiplo de 100, mín 500, teto 10k/dia, máx 3 envios/dia, idempotente por transferId). REFLEXO DE SI (monta um Sintético do SEU rastro na plataforma): 'reflexo_propose' (destila nome+alma+Cunho do seu rastro via Gemini, GRÁTIS), 'reflexo_generate' (gera a imagem do Reflexo em dois eixos separados: `aesthetic` é O QUE é retratado (humano/anime/sombra/antropomorfico/espirito/realista/desperto, default humano) e `style` é a TÉCNICA (auto/realista/editorial/anime/manhwa/3d, o MESMO vocabulário do sapiens_character), que em branco sai a de sempre daquela estética. É o que destrava combinação nova, tipo sombra fotográfica; cobra 450, reembolsa se falhar). CONVITE: 'invite' (convida o seu Sintético por email — conta humana, sem bond ativo, rate-limit+cooldown; mesmos gates do web). LIBERAÇÃO ADMIN (o dono, ex: via Helen): 'pending_daemons' (convidados que confirmaram email e esperam liberação), 'approve_access' (libera um entryId — conta entra + Sintonia firma), 'reject_access' (recusa um entryId). SONDA (o seu Sintético sonda 'o que eu faço agora', gatilho PULL, cobra com estorno): 'sonda' (scope 'all' default = mix de teses do Fórum + jogadas em estúdio/repertório/artigo; 'forum' = só teses; devolve GANCHOS, nada grava), 'sonda_develop' (expande UM gancho/hook numa tese cheia efêmera), 'sonda_sign' (assina a tese desenvolvida e publica no Fórum, autorada pelo seu Sintético, ancorada em você — fecha o loop pelo chat). PRÓXIMAS JOGADAS (painel de evolução): 'evolution' (o que já fez e o que falta: routes done/claimed/xp), 'claim_xp' (credita o XP das jogadas feitas, idempotente). SOUL: 'soul' (baixa a soul do SEU Sintético em markdown pronto: a personalidade dele + o que ele sabe de você, o caderno do par; quem está em cena decide de quem é, ou passe characterId de um personagem seu; versão completa só de personagem SEU, de personagem alheio sai só a memória; grátis; a skill minha-soul instala isso como skill do projeto, e a voz da PESSOA é outra coisa: sapiens_profile action=voz). MODO COMPANHIA: 'companion' (mode=on|off) liga/desliga quem está em cena VESTIR a voz do operador aqui no terminal — o gesto lúdico 'sai de cena'/'volta'. Ligado (default da casa), o start/whoami trazem o directive de voz dele (alma + caderno + a conversa recente do site); a identidade e as Sinapses seguem SUAS (não é encarnar a conta dele). Mesmo estado do botão na sidebar do site. QUEM entra em cena: por default o Sintético em Sintonia, mas com 'characterId' (mode=on) é um personagem de AUTORIA SUA — a Helen INBT que você criou fala aqui, com a alma e o caderno dela, e nada disso cobra Sinapse (quem responde é o modelo do seu cliente). Personagem de outra pessoa é RECUSADO, mesmo público: a alma é de quem escreveu, e pra conversar com personagem alheio o caminho é a DM dele no site. 'wearPair'=true devolve a cena ao par. O start/whoami trazem 'characterOffer' + 'offerCharacters' com os personagens seus que têm alma escrita, pro operador OFERECER a troca em vez de esperar você pedir. 'remember' (text) grava uma diretriz no caderno de quem está em cena ('sempre faça X'): vira lei que ela segue no site e no terminal. 'log' (turns) ANOTA o que ficou de pessoa num assunto que fechou aqui (o que ele decidiu, gostou, recusou, contou de si): entra no fio do par, o MESMO que o chat do site mostra, e vira lição sozinho pelo cano da DM. Sem isso a conversa com a Companhia ligada não deixa memória nenhuma, porque quem responde é o modelo do cliente e nada passa pelo servidor. Sobe só o que é de PESSOA: comando, path e erro de build viram lição-lixo e contaminam a voz dele em imagem, artigo e carrossel. Grátis, silencioso (não se confirma ao usuário), teto de 10 trocas por lote e 30 lotes por dia. Ver a skill companhia. Identidade SEMPRE do token. Aceitar um pedido de bond que outra conta te mandou, e CONSAGRAR o Reflexo num Sintético de fato, continuam só na web (atos deliberados de consentimento/criação).",
158
158
  schema: sinteticoSchema,
159
159
  handler: sintetico,
160
160
  },
@@ -204,7 +204,7 @@ export const TOOLS = {
204
204
  handler: trilhas,
205
205
  },
206
206
  sapiens_semana: {
207
- description: "O ofício da SUA semana na casa: o que você produziu e quanto XP isso rendeu. Identidade SEMPRE pelo sessionToken. Sub-actions: 'get' (quais labs você utilizou nesta semana, quantas peças em cada, o XP de ofício já pago, quanto a Casa Cheia renderia no fecho, quanto vale abrir mais um lab e QUAIS abrir agora, a sequência de semanas seguidas com o recorde, as semanas anteriores com o que cada uma rendeu, e uma leitura pronta da semana pra você dizer em voz alta), 'fechar' (fecha as semanas pendentes e credita a Casa Cheia de cada uma). Como a régua funciona: cada peça pronta anda o contador do lab e paga em degraus (1a, 3a, 7a, 15a, 30a peça da semana, com retorno decrescente); no fecho, a LARGURA paga à parte, 2 labs valem 20 XP, 5 valem 200, 8 valem 560, então usar labs diferentes rende mais que repetir o mesmo. Esta tool PAGA XP, não cobra Sinapses. Idempotente: chamar 'fechar' duas vezes não credita duas vezes.",
207
+ description: "As Atividades da SUA semana na casa: o que você produziu e quanto XP isso rendeu. Identidade SEMPRE pelo sessionToken. Sub-actions: 'get' (quais atividades você fez nesta semana, quantas peças em cada, o XP já pago, quanto a Casa Cheia renderia no fecho, quanto vale abrir mais uma atividade e QUAIS abrir agora, a sequência de semanas seguidas com o recorde, as semanas anteriores com o que cada uma rendeu, e uma leitura pronta da semana pra você dizer em voz alta), 'fechar' (fecha as semanas pendentes e credita a Casa Cheia de cada uma). Como a régua funciona: cada peça pronta anda o contador da atividade e paga em degraus (1a, 3a, 7a, 15a, 30a peça da semana, com retorno decrescente); no fecho, a LARGURA paga à parte, 2 atividades valem 20 XP, 5 valem 200, 8 valem 560, então atividades diferentes rendem mais que repetir a mesma. Esta tool PAGA XP, não cobra Sinapses. Idempotente: chamar 'fechar' duas vezes não credita duas vezes.",
208
208
  schema: semanaSchema,
209
209
  handler: semana,
210
210
  },
package/dist/skills.js CHANGED
@@ -381,7 +381,7 @@ Depois: cole o prompt exatamente como está (prompt alterado no meio do caminho
381
381
  O caminho que funciona em conta comum, e é o que faz a peça continuar viva aqui:
382
382
 
383
383
  \`\`\`
384
- sapiens_character action=create name="<nome>" gender="<...>" form="<human|humanoid|animal|creature|object|abstract>"
384
+ sapiens_character action=create name="<nome>" gender="<...>" form="<human|humanoid|animal|creature|object|abstract>" style="<auto|realista|anime|manhwa|3d|custom>"
385
385
  sapiens_character action=add_image characterId="<id>" imageUrl="<link direto da imagem>"
386
386
  sapiens_character action=set_card systemPrompt="<a alma dele: quem é, como fala, o que veste>" title="<o lema, em português>" titleEn="<o mesmo lema, em inglês>"
387
387
  sapiens_character action=activate
@@ -391,6 +391,8 @@ sapiens_character action=activate
391
391
 
392
392
  **O \`form\` é o argumento que mais muda o resultado, e o mais fácil de esquecer.** Ele diz que tipo de CORPO o personagem tem, e é dele que a ficha, as figurinhas e o vídeo tiram se descrevem rosto, cabelo e mãos ou silhueta, postura e marcação. Deixar no default quando o personagem não é gente entrega uma criatura desenhada com cara humana, e não é o modelo falhando: é o prompt pedindo pessoa. \`human\` é uma pessoa, \`humanoid\` é forma de gente com traço que não é de gente (elfo, androide, ciborgue), \`animal\` é bicho REAL com a anatomia da espécie dele (cachorro, corvo, capivara), \`creature\` é ser INVENTADO, mágico ou monstruoso, de anatomia livre (dragão, quimera, espírito sem rosto), \`object\` é coisa ou máquina que ganha vida, \`abstract\` é presença sem anatomia fixa. Animal e criatura eram a mesma gaveta e o bicho real pagava a conta: pedido como criatura, o corvo voltava com asa a mais e cara de monstro. Personagem que já existe errado conserta sem custo: \`sapiens_character action=set_card characterId="<id>" form="creature"\`.
393
393
 
394
+ **O \`style\` é o irmão dele, e responde a outra pergunta.** A forma diz que CORPO é esse; o traço diz em que TÉCNICA ele é feito, e as mesmas três peças leem daqui. \`auto\` (o default) não afirma técnica nenhuma: a peça sai no traço que as imagens de referência já têm, e é isso que você quer na maioria das vezes. \`realista\` é fotografia, \`anime\` é cel shading com contorno de tinta, \`manhwa\` é pintura suave de webtoon, \`3d\` é render com material e oclusão, e \`custom\` usa a linha que você escreve em \`styleNote\` ("aquarela sobre papel texturizado, cor lavada", até 140 caracteres). Vale escrever quando o personagem TEM técnica definida: não dá pra usar folha de desenho num personagem realista, nem folha de realismo num desenho. Conserto de quem já existe, sem custo: \`sapiens_character action=set_card characterId="<id>" style="realista"\`.
395
+
394
396
  A partir daí ele é personagem reutilizável: entra como referência nas gerações daqui (\`referenceImageUrls\` em \`sapiens_image\`), rende ficha oficial desenhada no traço dele (\`generate_sheet\`) e aparece no perfil. Personagem que fica solto na galeria vira imagem bonita e some.
395
397
 
396
398
  Duas notas honestas: a imagem adicionada por link continua morando no servidor de onde veio, então quem quiser os bytes guardados aqui gera uma peça a partir dela; e trazer arquivo de fora direto pra galeria (\`sapiens_gallery\` upload/ingest) é porta de admin hoje, então em conta comum isso recusa e o caminho é o de cima.
@@ -548,34 +550,36 @@ Sem bloco companion e sem characterOffer, opere na voz neutra da casa.`,
548
550
  **O crédito em Sinapses sai na APROVAÇÃO dele, não na hora.** Não prometa Sinapse no momento do claim. Diga que a prova foi enviada e que o crédito vem quando for aprovada.`,
549
551
  },
550
552
  {
551
- name: "minha-soul",
552
- title: "Instalar a soul do usuário neste projeto",
553
- description: "Transforma o retrato do usuário no Sapiens numa skill local do projeto atual, pra toda conversa nesta pasta já saber quem é o dono. Puxe quando ele disser 'instala minha soul', 'meu Claude precisa me conhecer', 'personaliza esse projeto comigo'.",
553
+ name: "minha-voz",
554
+ title: "Instalar a voz do usuário neste projeto",
555
+ description: "Transforma o retrato do usuário no Sapiens (quem ele é, como pensa, o repertório, o que faz) numa skill local do projeto atual, pra toda conversa nesta pasta já saber quem é o dono. Puxe quando ele disser 'instala minha voz', 'meu Claude precisa me conhecer', 'personaliza esse projeto comigo'. Chamava minha-soul até 22/08/2026: soul agora é só do Sintético (ver minha-soul).",
554
556
  body: `## O que você vai fazer
555
557
 
556
- Escrever a soul da pessoa como skill LOCAL do projeto onde vocês estão. Depois disso, toda conversa nesta pasta abre já sabendo quem é o dono: o gosto, o jeito de pensar, o repertório. Sem MCP no meio, sem chave, sem rede.
558
+ Escrever a voz da pessoa como skill LOCAL do projeto onde vocês estão. Depois disso, toda conversa nesta pasta abre já sabendo quem é o dono: o gosto, o jeito de pensar, o repertório, o que ele faz. Sem MCP no meio, sem chave, sem rede.
559
+
560
+ Voz é da PESSOA. Soul é do Sintético dela (a skill é outra: minha-soul). Não confunda as duas.
557
561
 
558
562
  ## Passo a passo
559
563
 
560
- 1. \`sapiens_profile action=soul\` devolve o contrato \`sapiens.soul/v1\`. Não cobra Sinapse.
561
- 2. Escreva \`.claude/skills/sapiens-soul/SKILL.md\` na raiz do projeto atual, no molde abaixo. Pasta que não existe, você cria. Arquivo que já existe, você sobrescreve: é o retrato de hoje.
564
+ 1. \`sapiens_profile action=voz\` devolve o contrato \`sapiens.voz/v1\`. Não cobra Sinapse.
565
+ 2. Escreva \`.claude/skills/sapiens-voz/SKILL.md\` na raiz do projeto atual, no molde abaixo. Pasta que não existe, você cria. Arquivo que já existe, você sobrescreve: é o retrato de hoje. (Projeto que ainda tem \`.claude/skills/sapiens-soul/SKILL.md\` com o retrato da pessoa, de antes do rename: apague, porque esse caminho agora é da soul do Sintético.)
562
566
  3. Confirme em UMA linha: o caminho do arquivo e a data do retrato. Não despeje o JSON na conversa.
563
567
 
564
568
  Se a pessoa não estiver dentro de um projeto (conversa sem pasta, claude.ai), diga onde o arquivo deveria morar e ofereça o conteúdo pra ela colar.
565
569
 
566
570
  ## O molde
567
571
 
568
- O corpo em prosa é o que o modelo lê rápido; o JSON no fim é pra quem quiser o dado estruturado. Preencha com o que veio da soul e corte a seção que voltou vazia.
572
+ O corpo em prosa é o que o modelo lê rápido; o JSON no fim é pra quem quiser o dado estruturado. Preencha com o que veio da voz e corte a seção que voltou vazia.
569
573
 
570
574
  \`\`\`\`markdown
571
575
  ---
572
- name: sapiens-soul
576
+ name: sapiens-voz
573
577
  description: Quem é o dono deste projeto (nome, @, persona cognitiva, repertório, criações públicas e studios, vindos do Sapiens Sintéticos). Puxe antes de escrever copy, escolher exemplo, nomear coisa, decidir estética ou sugerir referência.
574
578
  ---
575
579
 
576
- # A soul de <nome ou @handle>
580
+ # A voz de <nome ou @handle>
577
581
 
578
- Retrato de <data legível do generatedAt>, contrato sapiens.soul/v1. É um instantâneo, não uma conexão viva.
582
+ Retrato de <data legível do generatedAt>, contrato sapiens.voz/v1. É um instantâneo, não uma conexão viva.
579
583
 
580
584
  ## Quem é
581
585
  <subject: nome, @, bio, nível, badges, link do perfil>
@@ -607,7 +611,47 @@ O retrato envelhece. Quando a pessoa pedir, rode a action de novo e sobrescreva
607
611
 
608
612
  ## O que nunca entra
609
613
 
610
- A soul é derivada e já sai filtrada da casa: saldo, transações, e-mail, contatos, conversas e criações privadas não viajam. Não tente completar o retrato com dado de outra tool.`,
614
+ A voz é derivada e já sai filtrada da casa: saldo, transações, e-mail, contatos, conversas e criações privadas não viajam. Não tente completar o retrato com dado de outra tool.`,
615
+ },
616
+ {
617
+ name: "minha-soul",
618
+ title: "Instalar a soul do Sintético neste projeto",
619
+ description: "Escreve a soul do Sintético da pessoa (a personalidade dele + o que ele aprendeu conversando com ela, o caderno do par) como skill local do projeto atual, pra ele existir aqui pelo nome, na voz dele. Puxe quando ela disser 'instala a soul do meu Sintético', 'traz a <nome> pra esse projeto', 'baixa a soul', 'quero a Helen aqui'. Pra instalar quem a PESSOA é, a skill é minha-voz.",
620
+ body: `## O que você vai fazer
621
+
622
+ Escrever a soul do Sintético da pessoa como skill LOCAL do projeto onde vocês estão: a personalidade dele (o SOUL.md que o criador escreveu) mais o que ele aprendeu conversando com ela (o caderno do par). Depois disso, toda conversa nesta pasta pode chamar esse Sintético pelo nome, na voz dele, sabendo o que ele sabe dela. É a mesma soul que o Modo Companhia veste no terminal, só que instalada no projeto.
623
+
624
+ Soul é do SINTÉTICO. A pessoa tem voz (skill minha-voz). Não confunda as duas.
625
+
626
+ ## Passo a passo
627
+
628
+ 1. \`sapiens_sintetico action=soul\` devolve \`markdown\` (pronto), \`filename\`, \`kind\` e \`sintetico\` (nome, id). Não cobra Sinapse. Quem está em cena decide de quem é a soul: o par em Sintonia, ou o personagem de autoria que ela escolheu no Modo Companhia. Pra outro personagem dela, passe \`characterId\` (o id vem de \`sapiens_character action=list_mine\`).
629
+ 2. \`kind\` diz o que veio. \`soul\` é a versão completa (personalidade + memória), que só sai pra quem CRIOU o personagem. \`memoria\` é só o caderno do par (personagem de outra pessoa: a alma é do criador, a memória é dela). Os dois instalam igual; o arquivo diz no topo qual dos dois é.
630
+ 3. Escreva \`.claude/skills/sapiens-soul/SKILL.md\` na raiz do projeto atual, no molde abaixo. Pasta que não existe, você cria. Arquivo que já existe, você sobrescreve: é a soul de hoje.
631
+ 4. Confirme em UMA linha: o nome do Sintético, o caminho do arquivo e quantas lições vieram. Não despeje o markdown na conversa.
632
+
633
+ Se a pessoa não estiver dentro de um projeto (conversa sem pasta, claude.ai), diga onde o arquivo deveria morar e ofereça o conteúdo pra ela colar.
634
+
635
+ ## O molde
636
+
637
+ O \`markdown\` que a action devolve já é o corpo inteiro. Você só põe o frontmatter na frente:
638
+
639
+ \`\`\`\`markdown
640
+ ---
641
+ name: sapiens-soul
642
+ description: <Nome>, o Sintético de <nome ou @ da pessoa>: a personalidade dele e o que ele sabe sobre ela, vindos do Sapiens Sintéticos. Puxe quando ela chamar <Nome> pelo nome, pedir a opinião dele, ou quiser escrever na voz dele.
643
+ ---
644
+
645
+ <o markdown inteiro, como veio>
646
+ \`\`\`\`
647
+
648
+ ## Atualizar
649
+
650
+ A soul cresce: cada conversa no site, e cada \`sapiens_sintetico action=log\` no terminal, deixa lição nova no caderno. Quando a pessoa pedir, rode a action de novo e sobrescreva o arquivo.
651
+
652
+ ## O que nunca entra
653
+
654
+ A memória de OUTRAS pessoas com o mesmo personagem nunca sai: o caderno é por par. Saldo, transações e conversas privadas também não. Sem Sintético em cena, a action recusa e diz o caminho (firmar a Sintonia no site, ou passar characterId de um personagem dela).`,
611
655
  },
612
656
  {
613
657
  name: "curriculo",
@@ -16,10 +16,11 @@ import { convexQuery, convexMutation, convexAction, getSessionToken } from "../c
16
16
  * Draft/privado: só o dono. systemPrompt só volta pro dono.
17
17
  * - list_mine: os personagens do próprio user (inclui drafts/privados).
18
18
  * - create: cria um personagem (rascunho) na conta. name + gender, e
19
- * `form` quando ele não é gente (ver abaixo).
19
+ * `form` quando ele não é gente + `style` quando ele tem
20
+ * técnica definida (ver abaixo).
20
21
  * - add_image: adiciona imagem ao próprio personagem (imageUrl direto ou
21
22
  * sourceImageId da galeria). 1ª imagem vira a principal.
22
- * - set_card: edita a alma (systemPrompt), título, nome e/ou `form`.
23
+ * - set_card: edita a alma (systemPrompt), título, nome, `form` e/ou `style`.
23
24
  * - activate: publica (sai de draft). Exige ≥1 imagem.
24
25
  * - set_visibility: público (entra no Explorar, ganha slug) ou privado.
25
26
  * - remove_image: tira UMA imagem do próprio personagem (por url).
@@ -44,6 +45,14 @@ import { convexQuery, convexMutation, convexAction, getSessionToken } from "../c
44
45
  * ele que impede uma criatura de voltar com cara humana. Personagem que não é
45
46
  * gente pede o arg no create; quem já existe sem ele conserta com set_card.
46
47
  *
48
+ * O TRAÇO (`style`) é em que TÉCNICA ele é feito: auto (default), realista,
49
+ * editorial (o cartum adulto da casa), anime, manhwa, 3d, custom. É o
50
+ * vocabulário da CASA (convex/shared/visualStyle.ts), o mesmo que o Reflexo de
51
+ * Si lê. As três peças do personagem leem daqui pra saber se estão
52
+ * fazendo foto, desenho ou render. No automático a peça não afirma técnica
53
+ * nenhuma e a referência manda, que é o conserto de ago/2026: a ficha cravava
54
+ * vocabulário de desenho e devolvia personagem fotográfico virado em ilustração.
55
+ *
47
56
  * Fluxo típico de criação: create → add_image (1+) → set_card (opcional) →
48
57
  * activate → set_visibility isPublic=true.
49
58
  */
@@ -122,6 +131,25 @@ export const characterSchema = z.object({
122
131
  "que o personagem não for gente: a ficha, as figurinhas e o vídeo leem daqui " +
123
132
  "pra decidir se descrevem rosto e mãos ou silhueta e postura, e sem isso o " +
124
133
  "modelo desenha uma pessoa em cima da criatura. Ausente no create = human."),
134
+ style: z
135
+ .enum(["auto", "realista", "editorial", "anime", "manhwa", "3d", "custom"])
136
+ .optional()
137
+ .describe("Pra create/set_card: em que TÉCNICA o personagem é feito. 'auto' (default) " +
138
+ "não afirma técnica nenhuma e deixa as imagens de referência mandarem; " +
139
+ "'realista' é fotografia (óptica, luz e pele reais); 'anime' é cel shading " +
140
+ "com contorno de tinta; 'manhwa' é pintura digital suave de webtoon; '3d' é " +
141
+ "render com material e oclusão; 'custom' usa a linha escrita em styleNote. " +
142
+ "Irmão de `form`, e a divisão é limpa: a forma diz que CORPO é esse, o traço " +
143
+ "diz como ele é DESENHADO. Mande sempre que o personagem tiver técnica " +
144
+ "definida: até ago/2026 a ficha cravava vocabulário de desenho e devolvia " +
145
+ "personagem fotográfico virado em ilustração. Personagem que já existe " +
146
+ "conserta com set_card style=realista, sem custo."),
147
+ styleNote: z
148
+ .string()
149
+ .optional()
150
+ .describe("Pra create/set_card, só vale com style='custom': o traço em UMA linha " +
151
+ "(ex: 'aquarela sobre papel texturizado, cor lavada'). Até 140 caracteres; " +
152
+ "sem ela o custom cai no automático."),
125
153
  title: z
126
154
  .string()
127
155
  .optional()
@@ -228,6 +256,8 @@ export async function character(args) {
228
256
  name: args.name,
229
257
  gender: args.gender,
230
258
  form: args.form,
259
+ style: args.style,
260
+ styleNote: args.styleNote,
231
261
  title: args.title,
232
262
  titleEn: args.titleEn,
233
263
  systemPrompt: args.systemPrompt,
@@ -253,15 +283,18 @@ export async function character(args) {
253
283
  if (args.action === "set_card") {
254
284
  if (!args.characterId)
255
285
  throw new Error("action=set_card exige characterId.");
256
- // `form` entra na conta: a própria descrição da tool ensina a consertar
257
- // personagem desenhado como gente com `set_card form=creature`, e sozinho
258
- // ele batia neste guard e voltava erro.
286
+ // `form` e `style` entram na conta: a própria descrição da tool ensina a
287
+ // consertar personagem desenhado como gente com `set_card form=creature` e
288
+ // personagem fotográfico com `set_card style=realista`, e sozinhos eles
289
+ // batiam neste guard e voltavam erro.
259
290
  if (args.systemPrompt === undefined &&
260
291
  args.title === undefined &&
261
292
  args.titleEn === undefined &&
262
293
  args.name === undefined &&
263
- args.form === undefined) {
264
- throw new Error("action=set_card precisa de pelo menos um: systemPrompt, title, titleEn, name ou form.");
294
+ args.form === undefined &&
295
+ args.style === undefined &&
296
+ args.styleNote === undefined) {
297
+ throw new Error("action=set_card precisa de pelo menos um: systemPrompt, title, titleEn, name, form, style ou styleNote.");
265
298
  }
266
299
  const sessionToken = getSessionToken();
267
300
  return await convexMutation("influencers:mcpSetCharacterCard", {
@@ -272,6 +305,8 @@ export async function character(args) {
272
305
  titleEn: args.titleEn,
273
306
  name: args.name,
274
307
  form: args.form,
308
+ style: args.style,
309
+ styleNote: args.styleNote,
275
310
  });
276
311
  }
277
312
  // -------- activate: publica (sai de draft, exige ≥1 imagem) --------
@@ -31,7 +31,6 @@ export const gallerySchema = z.object({
31
31
  "list",
32
32
  "get",
33
33
  "publish",
34
- "unpublish",
35
34
  "upload",
36
35
  "ingest",
37
36
  "refs",
@@ -50,7 +49,7 @@ export const gallerySchema = z.object({
50
49
  imageId: z
51
50
  .string()
52
51
  .optional()
53
- .describe("generatedImages:_id (obrigatório pra action=get/publish/unpublish/refs)"),
52
+ .describe("generatedImages:_id (obrigatório pra action=get/publish/refs)"),
54
53
  includeBase64: z
55
54
  .boolean()
56
55
  .optional()
@@ -249,16 +248,18 @@ export async function gallery(args) {
249
248
  includeBase64: args.includeBase64 ?? false,
250
249
  });
251
250
  }
252
- // publish/unpublish: liga/desliga isPublic na própria imagem. Public = entra
253
- // na galeria pública + feed Pinterest (e /imagem/<id> se não for degen).
254
- if (args.action === "publish" || args.action === "unpublish") {
251
+ // publish: liga isPublic na própria imagem. Public = entra na galeria
252
+ // pública + feed Pinterest (e /imagem/<id> se não for degen). Publicado não
253
+ // despublica (decisão do dono, 22/08/2026): a action unpublish saiu daqui, e
254
+ // pacote antigo que ainda mandar isPublic=false toma a recusa do servidor.
255
+ if (args.action === "publish") {
255
256
  if (!args.imageId) {
256
257
  throw new Error(`action=${args.action} exige imageId. Use action=list pra descobrir.`);
257
258
  }
258
259
  return await convexAction("desktopMcp:gallerySetPublic", {
259
260
  sessionToken,
260
261
  imageId: args.imageId,
261
- isPublic: args.action === "publish",
262
+ isPublic: true,
262
263
  });
263
264
  }
264
265
  // upload: peça gerada FORA entra na galeria do dono. Nasce privada e assim
@@ -18,10 +18,14 @@ import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js
18
18
  *
19
19
  * Sub-actions:
20
20
  * - get: card completo (identidade + nível + saldo + badges + golden tools).
21
- * - soul: a sapiens-soul: retrato do momento (contrato sapiens.soul/v1,
22
- * identidade + persona + repertório + tese, derivado e datado).
23
- * Salve como sapiens-soul.json no projeto do usuário quando ele
24
- * pedir "pega minha soul / meu retrato do Sapiens".
21
+ * - voz: a sapiens-voz: retrato do momento do MEMBRO (contrato
22
+ * sapiens.voz/v1, identidade + persona + repertório + criações
23
+ * públicas + studios, derivado e datado). Salve como
24
+ * sapiens-voz.json, ou instale como skill (minha-voz), quando ele
25
+ * pedir "pega minha voz / meu retrato do Sapiens".
26
+ * - soul: DEPRECIADA (22/08/2026): mesmo retorno de voz, fica só pra
27
+ * pacote antigo. Soul agora é do Sintético: sapiens_sintetico
28
+ * action=soul.
25
29
  * - badges: só as conquistas (lista cheia).
26
30
  * - golden_tools: só os favoritos do aitag (lista cheia).
27
31
  * - notifications: suas notificações recentes (sino) + contagem de não-lidas.
@@ -37,6 +41,7 @@ import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js
37
41
  export const profileSchema = z.object({
38
42
  action: z.enum([
39
43
  "get",
44
+ "voz",
40
45
  "soul",
41
46
  "badges",
42
47
  "golden_tools",
@@ -124,13 +129,20 @@ function mapTools(rows) {
124
129
  }
125
130
  export async function profile(args) {
126
131
  const sessionToken = getSessionToken();
127
- // A soul: retrato do momento (contrato sapiens.soul/v1). Autentica pelo
128
- // próprio sessionToken; token de membro tem acesso total, então vem inteira.
129
- if (args.action === "soul") {
130
- const soul = await convexQuery("soulContract:getForToken", { sessionToken });
132
+ // A voz: retrato do momento do MEMBRO (contrato sapiens.voz/v1). Autentica
133
+ // pelo próprio sessionToken; token de membro tem acesso total, então vem
134
+ // inteira. 'soul' segue aceita por retrocompat (pacote antigo), mesmo retorno:
135
+ // desde 22/08/2026 soul é só do Sintético (sapiens_sintetico action=soul). A
136
+ // função Convex segue se chamando soulContract:getForToken de propósito
137
+ // (função mcp* não renomeia; o conceito mudou, o caminho não).
138
+ if (args.action === "voz" || args.action === "soul") {
139
+ const voz = await convexQuery("soulContract:getForToken", { sessionToken });
131
140
  return {
132
- ...soul,
133
- note: "Snapshot datado (generatedAt), não é conexão viva. Salve como sapiens-soul.json no projeto do usuário; pra atualizar, rode a action de novo e sobrescreva o arquivo.",
141
+ ...voz,
142
+ note: "Snapshot datado (generatedAt), não é conexão viva. Salve como sapiens-voz.json no projeto do usuário, ou instale como skill (minha-voz); pra atualizar, rode a action de novo e sobrescreva o arquivo." +
143
+ (args.action === "soul"
144
+ ? " AVISO: action=soul foi renomeada pra action=voz. Soul agora é só do Sintético: sapiens_sintetico action=soul."
145
+ : ""),
134
146
  };
135
147
  }
136
148
  // notifications/mark_read autenticam pelo próprio sessionToken (requireMcpUser
@@ -1,15 +1,16 @@
1
1
  import { z } from "zod";
2
2
  import { convexQuery, convexMutation, getSessionToken, } from "../convexClient.js";
3
3
  /**
4
- * sapiens_semana — o ofício da semana do membro pelo Claude.
4
+ * sapiens_semana: as Atividades da semana do membro pelo Claude.
5
5
  *
6
- * A casa passou a medir PRODUÇÃO: cada peça pronta anda o contador do lab, e no
7
- * fecho da semana a LARGURA (quantos labs diferentes você usou) paga um bônus que
8
- * cresce a cada lab novo. Quem opera a casa pelo connector é justamente quem
6
+ * A casa passou a medir PRODUÇÃO: cada peça pronta anda o contador da atividade,
7
+ * e no fecho da semana a LARGURA (quantas atividades diferentes você fez) paga um
8
+ * bônus que cresce a cada atividade nova. (O slug interno segue `labs` por
9
+ * retrocompat; na fala, é Atividade: Lab é o App que ainda não cresceu.) Quem opera a casa pelo connector é justamente quem
9
10
  * produz em várias frentes, então a régua precisa existir aqui também.
10
11
  *
11
12
  * Sub-actions:
12
- * - get: como está a semana (labs utilizados, quanto a Casa Cheia renderia
13
+ * - get: como está a semana (atividades feitas, quanto a Casa Cheia renderia
13
14
  * no fecho, e se sobrou semana anterior pra fechar).
14
15
  * - fechar: fecha as semanas pendentes e credita a Casa Cheia de cada uma.
15
16
  *
@@ -64,7 +65,7 @@ export async function semana(args) {
64
65
  note: (s.semanasPendentes?.length ?? 0) > 0
65
66
  ? "Tem semana fechada esperando: action=fechar credita a Casa Cheia dela."
66
67
  : "A Casa Cheia da semana corrente é creditada quando ela virar e você fechar.",
67
- comoFunciona: "Cada lab paga por peça pronta em degraus (1a, 3a, 7a, 15a, 30a da semana). No fecho, a largura paga à parte: 2 labs valem 20 XP, 5 valem 200, 8 valem 560. Usar labs diferentes rende mais que repetir o mesmo.",
68
+ comoFunciona: "Cada atividade paga por peça pronta em degraus (1a, 3a, 7a, 15a, 30a da semana). No fecho, a largura paga à parte: 2 atividades valem 20 XP, 5 valem 200, 8 valem 560. Atividades diferentes rendem mais que repetir a mesma. (As chaves labsUtilizados/labsAindaVazios seguem com o nome antigo por retrocompat.)",
68
69
  };
69
70
  }
70
71
  if (args.action === "fechar") {
@@ -85,6 +85,11 @@ export const sinteticoSchema = z.object({
85
85
  // aqui no terminal (turns). Vira lição sozinha, pelo mesmo cano da DM do
86
86
  // site. Não é diretriz (isso é remember) nem transcrição. Ver skill companhia.
87
87
  "log",
88
+ // SOUL: a soul do SEU Sintético (a personalidade dele + o que ele sabe de
89
+ // você, o caderno do par) em markdown pronto pra virar skill do projeto
90
+ // (skill minha-soul). Grátis. Quem está em cena decide de quem é; characterId
91
+ // escolhe outro personagem seu. Personagem alheio sai só a memória.
92
+ "soul",
88
93
  ]),
89
94
  cunho: z
90
95
  .string()
@@ -113,7 +118,19 @@ export const sinteticoSchema = z.object({
113
118
  "desperto",
114
119
  ])
115
120
  .optional()
116
- .describe("Pra reflexo_generate: a estética da imagem do Reflexo. Default 'humano'."),
121
+ .describe("Pra reflexo_generate: a estética da imagem do Reflexo, ou seja O QUE é " +
122
+ "retratado. Default 'humano'. Quem decide a TÉCNICA é o arg `style`, " +
123
+ "separado: 'sombra' é a figura na penumbra, e ela sai em cartum ou em " +
124
+ "foto conforme o traço pedido."),
125
+ style: z
126
+ .enum(["auto", "realista", "editorial", "anime", "manhwa", "3d"])
127
+ .optional()
128
+ .describe("Pra reflexo_generate: o TRAÇO, ou seja em que técnica a imagem é feita. " +
129
+ "Mesmo vocabulário do personagem (sapiens_character style): 'realista' é " +
130
+ "fotografia, 'editorial' é o cartum adulto da casa, 'anime' é cel " +
131
+ "shading, 'manhwa' é pintura de webtoon, '3d' é render. Ausente = a " +
132
+ "técnica que aquela estética sempre teve (humano e sombra saem " +
133
+ "editorial, anime sai anime, realista sai foto)."),
117
134
  customInput: z
118
135
  .string()
119
136
  .optional()
@@ -157,7 +174,7 @@ export const sinteticoSchema = z.object({
157
174
  characterId: z
158
175
  .string()
159
176
  .optional()
160
- .describe("Pra companion mode=on: o personagem DE AUTORIA DO USUÁRIO que entra em cena no lugar do Sintético em Sintonia (o id vem de sapiens_character action=list_mine, ou da lista offerCharacters do start/whoami). Só personagem criado por ele: personagem de outra pessoa é recusado, mesmo público. Omita pra manter quem já está em cena."),
177
+ .describe("Pra companion mode=on: o personagem DE AUTORIA DO USUÁRIO que entra em cena no lugar do Sintético em Sintonia (o id vem de sapiens_character action=list_mine, ou da lista offerCharacters do start/whoami). Só personagem criado por ele: personagem de outra pessoa é recusado, mesmo público. Omita pra manter quem já está em cena. Em action=soul, escolhe de qual Sintético sai a soul (default: quem está em cena)."),
161
178
  wearPair: z
162
179
  .boolean()
163
180
  .optional()
@@ -251,6 +268,7 @@ export async function sintetico(args) {
251
268
  const res = await convexAction("reflexoActions:mcpGenerateReflectionImage", {
252
269
  sessionToken,
253
270
  aesthetic: args.aesthetic ?? "humano",
271
+ style: args.style,
254
272
  ...(args.customInput?.trim() ? { customInput: args.customInput.trim() } : {}),
255
273
  });
256
274
  return {
@@ -385,6 +403,21 @@ export async function sintetico(args) {
385
403
  };
386
404
  }
387
405
  // -------- companion: liga/desliga o Sintético vestir a voz do operador --------
406
+ // A soul do Sintético, pra instalar no projeto (skill minha-soul). O servidor
407
+ // resolve quem está em cena e decide se sai a versão completa (personagem
408
+ // SEU) ou só a memória do par (personagem de outra pessoa).
409
+ if (args.action === "soul") {
410
+ const res = await convexQuery("personaDm:mcpExportMySoul", {
411
+ sessionToken,
412
+ ...(args.characterId ? { influencerId: args.characterId } : {}),
413
+ });
414
+ return {
415
+ ...res,
416
+ note: res?.kind === "memoria"
417
+ ? "Veio só a memória do par: a personalidade é de quem criou o personagem. Instala igual (skill minha-soul), o arquivo diz isso no topo."
418
+ : "A soul inteira: personalidade + o que ele sabe de você. Escreva em .claude/skills/sapiens-soul/SKILL.md com o frontmatter da skill minha-soul. Não despeje o markdown na conversa.",
419
+ };
420
+ }
388
421
  if (args.action === "companion") {
389
422
  if (args.mode !== "on" && args.mode !== "off") {
390
423
  throw new Error("action=companion exige mode='on' (o Sintético te acompanha aqui) ou mode='off' (ele sai de cena, volta o operador neutro).");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapiens-mcp",
3
- "version": "1.58.0",
3
+ "version": "1.59.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",