sapiens-mcp 1.43.0 → 1.43.2
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 +13 -6
- package/dist/skills.js +47 -11
- package/dist/tools/aula.js +129 -13
- package/dist/tools/character.js +15 -2
- package/dist/tools/reference.js +20 -4
- package/dist/tools/semana.js +65 -0
- package/dist/tools/studios.js +7 -4
- package/dist/tools/video.js +14 -6
- package/package.json +1 -1
package/dist/registry.js
CHANGED
|
@@ -28,6 +28,7 @@ import { support, supportSchema } from "./tools/support.js";
|
|
|
28
28
|
import { atlas, atlasSchema } from "./tools/atlas.js";
|
|
29
29
|
import { reference, referenceSchema } from "./tools/reference.js";
|
|
30
30
|
import { trilhas, trilhasSchema } from "./tools/trilhas.js";
|
|
31
|
+
import { semana, semanaSchema } from "./tools/semana.js";
|
|
31
32
|
import { shareDrop, shareDropSchema } from "./tools/shareDrop.js";
|
|
32
33
|
import { skill, skillSchema } from "./tools/skill.js";
|
|
33
34
|
import { describeConvexError } from "./convexClient.js";
|
|
@@ -56,7 +57,7 @@ export const TOOLS = {
|
|
|
56
57
|
handler: meta,
|
|
57
58
|
},
|
|
58
59
|
sapiens_skill: {
|
|
59
|
-
description: "As SKILLS da casa: o passo a passo travado de cada fluxo do Sapiens, servido pelo próprio connector (sem login, sem custo, sem rede). LEIA A SKILL ANTES DE OPERAR O FLUXO — é mais barato que errar uma geração que cobra Sinapses. Sub-actions: 'list' (índice: slug + quando usar cada uma), 'get' (o SKILL.md inteiro, passe name=<slug>). Slugs: primeiros-passos (porta de entrada e as 4 armadilhas: timeout que já cobrou, disjuntor anti-loop, saldo, sessão), voz-da-casa (DNA editorial, leia antes de redigir qualquer texto publicável), musica (Musicator em 4 passos + efeito sonoro), video (qual modelo, iterar barato no Mini, storyboard por referência, sonorize), imagem (prompt full-bleed na régua da casa, multi-referência, templates), studio (gerar na identidade da pessoa vs base
|
|
60
|
+
description: "As SKILLS da casa: o passo a passo travado de cada fluxo do Sapiens, servido pelo próprio connector (sem login, sem custo, sem rede). LEIA A SKILL ANTES DE OPERAR O FLUXO — é mais barato que errar uma geração que cobra Sinapses. Sub-actions: 'list' (índice: slug + quando usar cada uma), 'get' (o SKILL.md inteiro, passe name=<slug>). Slugs: primeiros-passos (porta de entrada e as 4 armadilhas: timeout que já cobrou, disjuntor anti-loop, saldo, sessão), voz-da-casa (DNA editorial, leia antes de redigir qualquer texto publicável), musica (Musicator em 4 passos + efeito sonoro), video (qual modelo, iterar barato no Mini, storyboard por referência, sonorize), imagem (prompt full-bleed na régua da casa, multi-referência, templates), studio (o perfil de empresa da casa, o time, e gerar na identidade da pessoa vs base), tirinha (2 fases, a imagem sai SEM texto), forum-comunidade (mídia estruturada, menção, tese), companhia (o Sintético veste você), trilhas (missão e prova). O mesmo conteúdo também sai como resource MCP em skill://sapiens/<slug>/SKILL.md pra quem lê resources.",
|
|
60
61
|
schema: skillSchema,
|
|
61
62
|
handler: skill,
|
|
62
63
|
},
|
|
@@ -96,7 +97,7 @@ export const TOOLS = {
|
|
|
96
97
|
handler: search,
|
|
97
98
|
},
|
|
98
99
|
sapiens_studios: {
|
|
99
|
-
description: "Catálogo dos estúdios/experimentos Sapiens + o SEU studio + a Emancipação. Sub-actions: mine (o
|
|
100
|
+
description: "Catálogo dos estúdios/experimentos Sapiens + o SEU studio + a Emancipação. Sub-actions: mine (o studio do user, que é o perfil de EMPRESA da casa dele: nome/endereço público/marca/operador/tamanho do time), list (todos com URL+status+tags+mcpReady), get (detalhe de 1 slug), publishable_url (formata URL /articles/<slug>), emancipar (INICIA o Nível 3: blueprint pra construir a casa PRÓPRIA do membro na infra dele, fora do Sapiens), module (guia de um módulo de infra: fundacao/sapiens-connect/telegram/email/auth). Use quando user pergunta 'que estúdios existem', 'qual o meu studio', ou 'quero montar meu site/minha casa própria'. Estúdios cobertos: helen-voice, musicator, persona-sapiens, personagem-atlas, sapiens-shorts, sapiens-video, text-post-builder, comic-builder, carrosel-editorial, comunidade, repertorio.",
|
|
100
101
|
schema: studiosSchema,
|
|
101
102
|
handler: studios,
|
|
102
103
|
},
|
|
@@ -121,7 +122,7 @@ export const TOOLS = {
|
|
|
121
122
|
handler: shorts,
|
|
122
123
|
},
|
|
123
124
|
sapiens_video: {
|
|
124
|
-
description: "Sapiens Video — gera vídeo (qualquer membro logado; vídeo é caro, cobra as Sinapses da sua conta). Sub-action 'create' (recomendada): escolhe modelo + config e gera num call (cria a row + renderiza). Modelos: 'sapiens-video-seedance' (Seedance 2.0, cena+áudio nativo, 4-15s, 480/720/1080p, t2v/i2v; aceita até 4 imagens de REFERÊNCIA via referenceImageIds/referenceImageUrls/referenceImagePaths (os Veo fast/quality também aceitam, até 3; Lite/Kling/WAN/Omni não), que guiam estilo/personagem/composição SEM virar o 1º frame — é o fluxo STORYBOARD: gere a folha de key poses com sapiens_image templateSlug='storyboard-sapiens-v1', passe folha + personagem como refs num t2v e descreva o take contínuo no prompt, citando as refs por descrição e mandando ignorar o traço do sketch; aceita também 1 VÍDEO DE MOVIMENTO via referenceVideoUrls (role 'refvideo' -> reference_videos, <=15s, host da casa): a coreografia/câmera do clipe guia o take, combinável com a folha), 'sapiens-video-seedance-2-fast' e 'sapiens-video-seedance-2-mini' (os irmãos do 2.0: MESMO repertório completo, incluindo referência, frame final e vídeo de movimento; o Fast custa 20% menos e o Mini METADE, ambos com teto 720p — pedir 1080p neles entrega e cobra 720p. Use o Mini pra iterar enquadramento/prompt barato e feche no 'sapiens-video-seedance' quando o take estiver certo), 'sapiens-video-kling' (Kling 3.0 Pro, anima imagem, 3-15s, sound opcional, i2v/t2v), 'sapiens-video-wan' (WAN 2.5, imagem que fala/canta com áudio+lip-sync, 5/10s, i2v), 'sapiens-video-kling-motion' (Motion transfer: passa o movimento de um vídeo pra uma imagem, PRECISA de pessoa com tronco visível na imagem E no vídeo), 'sapiens-video-shot-mimic' (Shot Mimic: recria o plano/câmera/cortes de um vídeo de referência como cena nova), 'sapiens-video-omni' (Gemini Omni: texto vira vídeo 10s 720p com áudio nativo; NÃO aceita mídia do user, ignora references/durationSec/resolution; editOfImageId aponta um vídeo Omni seu e o prompt edita a MESMA cena, preservando câmera e ambiente), 'sapiens-video-lite/fast/quality' (Veo 3.1). Args create: model, prompt, durationSec, resolution ('480p'/'720p'/'1080p'), audio, aspectRatio. FRAME INICIAL/FINAL POR REFERÊNCIA (recomendado): startImageId/endImageId (id da sua galeria) ou startImageUrl/endImageUrl (url de galeria/Acervo/personagem) — resolvidos server-side igual à imagem, descubra via sapiens_reference. FRAME POR ARQUIVO LOCAL (só no MCP instalado/stdio, não no remoto): startImagePath/endImagePath = caminho absoluto de uma imagem no seu PC (PNG/JPEG/WebP até 8MB); o processo lê o arquivo e sobe como frame inicial/final, igual a subir no gerador do site — 1 imagem inicial + 1 final por vídeo, então pra vários vídeos rode create uma vez por imagem. No remoto use id/url. Alternativa base64: references (role 'start'=imagem i2v, 'end'=frame final, 'driving'=vídeo de movimento do Motion). Suporte a frame final varia por modelo. Custo server-side por config. Sub-action 'generate' (legado): renderiza um imageId de vídeo já criado no site. Retorna {success, url, imageId, cost}. VITRINE (sem custo): sub-action 'demos' lista os SEUS demo films (kind=demo do Estúdio de Vídeo) com slug + estado de vitrine; sub-action 'showcase' põe/tira um demo (por slug) do mini-cinema da /conectar-claude, com showcaseTag (chip de capacidade) e showcaseOrder (ordem asc). Fluxo: 'demos' pra achar o slug, depois 'showcase' com showcase=true. Só entra na vitrine pública se for a conta da casa. VÍDEOS PROGRAMÁTICOS (ADMIN, sem custo):
|
|
125
|
+
description: "Sapiens Video — gera vídeo (qualquer membro logado; vídeo é caro, cobra as Sinapses da sua conta). Sub-action 'create' (recomendada): escolhe modelo + config e gera num call (cria a row + renderiza). Modelos: 'sapiens-video-seedance' (Seedance 2.0, cena+áudio nativo, 4-15s, 480/720/1080p, t2v/i2v; aceita até 4 imagens de REFERÊNCIA via referenceImageIds/referenceImageUrls/referenceImagePaths (os Veo fast/quality também aceitam, até 3; Lite/Kling/WAN/Omni não), que guiam estilo/personagem/composição SEM virar o 1º frame — é o fluxo STORYBOARD: gere a folha de key poses com sapiens_image templateSlug='storyboard-sapiens-v1', passe folha + personagem como refs num t2v e descreva o take contínuo no prompt, citando as refs por descrição e mandando ignorar o traço do sketch; aceita também 1 VÍDEO DE MOVIMENTO via referenceVideoUrls (role 'refvideo' -> reference_videos, <=15s, host da casa): a coreografia/câmera do clipe guia o take, combinável com a folha), 'sapiens-video-seedance-2-fast' e 'sapiens-video-seedance-2-mini' (os irmãos do 2.0: MESMO repertório completo, incluindo referência, frame final e vídeo de movimento; o Fast custa 20% menos e o Mini METADE, ambos com teto 720p — pedir 1080p neles entrega e cobra 720p. Use o Mini pra iterar enquadramento/prompt barato e feche no 'sapiens-video-seedance' quando o take estiver certo), 'sapiens-video-kling' (Kling 3.0 Pro, anima imagem, 3-15s, sound opcional, i2v/t2v), 'sapiens-video-wan' (WAN 2.5, imagem que fala/canta com áudio+lip-sync, 5/10s, i2v), 'sapiens-video-kling-motion' (Motion transfer: passa o movimento de um vídeo pra uma imagem, PRECISA de pessoa com tronco visível na imagem E no vídeo), 'sapiens-video-shot-mimic' (Shot Mimic: recria o plano/câmera/cortes de um vídeo de referência como cena nova), 'sapiens-video-omni' (Gemini Omni: texto vira vídeo 10s 720p com áudio nativo; NÃO aceita mídia do user, ignora references/durationSec/resolution; editOfImageId aponta um vídeo Omni seu e o prompt edita a MESMA cena, preservando câmera e ambiente), 'sapiens-video-lite/fast/quality' (Veo 3.1). Args create: model, prompt, durationSec, resolution ('480p'/'720p'/'1080p'), audio, aspectRatio. FRAME INICIAL/FINAL POR REFERÊNCIA (recomendado): startImageId/endImageId (id da sua galeria) ou startImageUrl/endImageUrl (url de galeria/Acervo/personagem) — resolvidos server-side igual à imagem, descubra via sapiens_reference. FRAME POR ARQUIVO LOCAL (só no MCP instalado/stdio, não no remoto): startImagePath/endImagePath = caminho absoluto de uma imagem no seu PC (PNG/JPEG/WebP até 8MB); o processo lê o arquivo e sobe como frame inicial/final, igual a subir no gerador do site — 1 imagem inicial + 1 final por vídeo, então pra vários vídeos rode create uma vez por imagem. No remoto use id/url. Alternativa base64: references (role 'start'=imagem i2v, 'end'=frame final, 'driving'=vídeo de movimento do Motion). Suporte a frame final varia por modelo. Custo server-side por config. Sub-action 'generate' (legado): renderiza um imageId de vídeo já criado no site. Retorna {success, url, imageId, cost}. VITRINE (sem custo): sub-action 'demos' lista os SEUS demo films (kind=demo do Estúdio de Vídeo) com slug + estado de vitrine; sub-action 'showcase' põe/tira um demo (por slug) do mini-cinema da /conectar-claude, com showcaseTag (chip de capacidade) e showcaseOrder (ordem asc). Fluxo: 'demos' pra achar o slug, depois 'showcase' com showcase=true. Só entra na vitrine pública se for a conta da casa. VÍDEOS PROGRAMÁTICOS (ADMIN, sem custo): o Lab do Estúdio de Vídeo (/experimentos/films, tabela videoSpecs, 5 kinds: demo | aula-tour | essay | tipografia-musical | dataviz) opera por aqui sem browser — 'film-list' (todos os kinds; filtros filmKind/filmStatus), 'film-get' (spec inteiro por slug), 'film-upsert' (cria/atualiza por slug, idempotente; spec = objeto JSON no shape do 'Copiar spec' da tela, validação no servidor), 'film-status' (produção por slug: filmStatus + videoUrl + durationSecMeasured; o fecho do render é os três num call), 'film-publish' (Acervo aba Fitas + portfólio; exige pronto+URL), 'film-delete' (limpar rascunho). O RENDER do filme segue no agente local (skill /film, repo da casa): o MCP registra e fecha o ciclo, não renderiza. create é ASSÍNCRONA: cria o row, debita e volta NA HORA com {imageId, status:'rendering', cost} (não espera o render, que leva de segundos a minutos). Acompanhe com a sub-action 'status' (imageId) até status='completed' (traz a url) ou 'error'/'blocked'. NÃO chame create de novo enquanto renderiza (cria outro vídeo e cobra de novo); falha de provider refunda sozinha. SOM: 'sonorize' (imageId de vídeo SEU completed + prompt do som da cena) gera uma VARIANTE nova com trilha sincronizada (20 Sinapses/s, o original fica intacto; sonorize sempre o original, nunca uma variante). ADMIN: 'shadows' (videoUrl + title) extrai o deepshadow (depth-map) de um vídeo: entra na sua timeline de vídeos e no Acervo como driving reutilizável; 'shadows-list' lista os deepshadows prontos. Sub-action 'models' (sem custo, sem login): lista os modelos de vídeo ativos + preço-piso + config (durações/resoluções) + disponibilidade (Omni depende de env).",
|
|
125
126
|
schema: videoSchema,
|
|
126
127
|
handler: video,
|
|
127
128
|
},
|
|
@@ -141,7 +142,7 @@ export const TOOLS = {
|
|
|
141
142
|
handler: brand,
|
|
142
143
|
},
|
|
143
144
|
sapiens_character: {
|
|
144
|
-
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 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 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). 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.",
|
|
145
|
+
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 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 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). FICHA (generate_sheet, COBRA 450 Sinapses): desenha a página-pôster do personagem, uma folha só com pose, expressões, trocas de roupa e os adereços dele, no traço das imagens que ele já tem (exige pelo menos uma). 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 sheets em action=get), não se sobrescrevem. É geração síncrona: se voltar Timeout, cheque action=get antes de repetir, senão cobra duas vezes. 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.",
|
|
145
146
|
schema: characterSchema,
|
|
146
147
|
handler: character,
|
|
147
148
|
},
|
|
@@ -166,7 +167,7 @@ export const TOOLS = {
|
|
|
166
167
|
handler: instagram,
|
|
167
168
|
},
|
|
168
169
|
sapiens_aula: {
|
|
169
|
-
description: "Aula (deck
|
|
170
|
+
description: "Aula (deck servido em /aulas/<slug>) — ADMIN-ONLY (aula é conteúdo de mentor, não de aluno; aluno leva 'restrito ao dono'). Edita direto no Convex, sem script de disco. A aula de hoje é MODULAR: guarda `source = { recipe, modules[] }` e materializa os slides na LEITURA, então gravar slide materializado não adianta (some no próximo materialize) — mexe na FONTE. Fluxo de conteúdo: 'map' (índice BARATO: blocos da receita + ids de módulo + contagem de slides, sem arrastar os 45 slides; SEMPRE comece por ele) -> 'module' (1 módulo inteiro, pronto pra editar) -> 'module-save' (grava o módulo e remonta os slides; módulo NOVO precisa de placeAfter=<id vizinho> ou bloco=<título>; `module` ausente/null REMOVE). Fluxo de roteiro: 'recipe-op' (op=move|remove|add + toIndex/bloco) muda a ORDEM sem tocar no conteúdo. 'meta' edita título/subtítulo/tag/data/duration e o status draft|published (publica e despublica). 'delete' apaga a aula de vez (sem undo: puxe 'get' antes se quiser guardar); aula NO AR é recusada até você tirar de circulação com meta status=draft, ou insistir com force=true. Aula LEGADA (sem source) usa 'get'/'upsert' com o objeto inteiro: title (obrig) + slides[] (≥1) + subtitle/data/duration/tag/mentorAgenda. Slides são { type, ...campos }: cover, cover-image/section-image/content-image (imageUrl), agenda (items[]), content (body markdown/HTML + list[]/listType), two-col (cols[]), video (videoUrl ou videos[] lado a lado), quote, callout (tone tip|warn|note), comic (panels[]), pause, close (items[]). 'list' dá o panorama. Toda escrita re-linta a voz e grava voiceWarnings (1ª pessoa, anti-corporate, SEM travessão). A rota serve sob demanda: slug novo aparece sem rebuild.",
|
|
170
171
|
schema: aulaSchema,
|
|
171
172
|
handler: aula,
|
|
172
173
|
},
|
|
@@ -190,8 +191,13 @@ export const TOOLS = {
|
|
|
190
191
|
schema: trilhasSchema,
|
|
191
192
|
handler: trilhas,
|
|
192
193
|
},
|
|
194
|
+
sapiens_semana: {
|
|
195
|
+
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, e se sobrou semana anterior por fechar), '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.",
|
|
196
|
+
schema: semanaSchema,
|
|
197
|
+
handler: semana,
|
|
198
|
+
},
|
|
193
199
|
sapiens_share: {
|
|
194
|
-
description: "Share Drop (ADMIN-ONLY): sobe um HTML single-file (doctype + CSS/JS inline) e recebe o link curto sint.fyi/s/<code> pra mandar pra alguém abrir no navegador sem instalar nada. O PONTO: publicar um artefato e depois RE-PUBLICAR no MESMO link quantas vezes quiser (action=update com o code) — edita o HTML aqui no Claude, joga pro ar, atualiza o mesmo arquivo. Sub-actions: 'list' (links ativos: code + url + título + tamanho + isActive/hasPassword/requireLogin), 'upload' (cria link NOVO a partir de html ou htmlPath → devolve {code, url}), 'update' (re-publica no MESMO code: mesma url, conteúdo novo, apaga o blob antigo), 'delete' (tira do ar — o link vira 404), 'settings' (isActive liga/desliga, password senha string vazia remove, requireLogin exige conta logada). O HTML entra por `html` (conteúdo string, funciona no stdio e no remoto) OU `htmlPath` (caminho absoluto de um .html local, SÓ no MCP instalado/stdio). Título sai do <title> do HTML se não passar `title` (ou keepTitle=true no update pra manter o atual). Sem custo em Sinapses. Espelha
|
|
200
|
+
description: "Share Drop (ADMIN-ONLY): sobe um HTML single-file (doctype + CSS/JS inline) e recebe o link curto sint.fyi/s/<code> pra mandar pra alguém abrir no navegador sem instalar nada. O PONTO: publicar um artefato e depois RE-PUBLICAR no MESMO link quantas vezes quiser (action=update com o code) — edita o HTML aqui no Claude, joga pro ar, atualiza o mesmo arquivo. Sub-actions: 'list' (links ativos: code + url + título + tamanho + isActive/hasPassword/requireLogin), 'upload' (cria link NOVO a partir de html ou htmlPath → devolve {code, url}), 'update' (re-publica no MESMO code: mesma url, conteúdo novo, apaga o blob antigo), 'delete' (tira do ar — o link vira 404), 'settings' (isActive liga/desliga, password senha string vazia remove, requireLogin exige conta logada). O HTML entra por `html` (conteúdo string, funciona no stdio e no remoto) OU `htmlPath` (caminho absoluto de um .html local, SÓ no MCP instalado/stdio). Título sai do <title> do HTML se não passar `title` (ou keepTitle=true no update pra manter o atual). Sem custo em Sinapses. Espelha o Lab /dashboard/admin/share-drop.",
|
|
195
201
|
schema: shareDropSchema,
|
|
196
202
|
handler: shareDrop,
|
|
197
203
|
},
|
|
@@ -271,6 +277,7 @@ const TOOL_TITLES = {
|
|
|
271
277
|
sapiens_atlas: "Atlas Ecossistema IA",
|
|
272
278
|
sapiens_reference: "Referências",
|
|
273
279
|
sapiens_trilhas: "Trilhas & Desafios",
|
|
280
|
+
sapiens_semana: "Minha Semana",
|
|
274
281
|
sapiens_instagram: "Auto-DM Instagram",
|
|
275
282
|
sapiens_share: "Share Drop",
|
|
276
283
|
};
|
package/dist/skills.js
CHANGED
|
@@ -92,6 +92,27 @@ Primeira pessoa. Opinião explícita. Conversa, não palestra. Analogia concreta
|
|
|
92
92
|
- "Neste artigo vamos abordar", "vamos explorar", "sem mais delongas".
|
|
93
93
|
- Tom influencer, promessa de atalho mágico, receita pronta.
|
|
94
94
|
- Fechar tudo com CTA. O texto termina quando a ideia termina.
|
|
95
|
+
- **Definir por negação** ("não é X, é Y", "nada de Z"). A casa só afirma: diz Y direto.
|
|
96
|
+
|
|
97
|
+
## Tiques de IA que a casa corta
|
|
98
|
+
|
|
99
|
+
O modelo repete esses porque soam competentes. Todos caem.
|
|
100
|
+
|
|
101
|
+
- **Falsa revelação**: "o que ninguém te conta", "a parte que todo mundo pula". Corta o setup, a afirmação fica de pé sozinha.
|
|
102
|
+
- **Atribuição vaga**: "especialistas concordam", "estudos mostram". Nomeia a fonte ou corta a frase.
|
|
103
|
+
- **Inflar importância**: "divisor de águas", "marca um momento decisivo". Fala o fato e deixa quem lê julgar o tamanho.
|
|
104
|
+
- **Análise em gerúndio**: "reforçando o compromisso do time", "evidenciando", "destacando". Troca pela consequência concreta.
|
|
105
|
+
- **Revelação com dois-pontos**: "O detalhe que faz funcionar: um agente separado corrige." Vira frase normal.
|
|
106
|
+
- **Setup retórico**: "e se eu te dissesse", "pensa comigo", "plot twist", e pergunta que o próprio texto responde na linha seguinte.
|
|
107
|
+
- **Frase vazia**: "vale destacar", "é importante notar", "no final das contas", "quando se trata de", "nos dias de hoje".
|
|
108
|
+
- **Rodízio de sinônimo**: o agente, depois o assistente, depois a ferramenta, tudo pra mesma coisa. Repetir a palavra certa é precisão.
|
|
109
|
+
- **Kicker de falsa profundidade**: a última linha "funda" que vira aforismo. Deleta, não reescreve numa metáfora melhor. Termina na frase concreta que já estava lá.
|
|
110
|
+
|
|
111
|
+
Hedge não entra nessa lista: "ao meu ver", "por enquanto", "talvez" assinam a voz e ficam.
|
|
112
|
+
|
|
113
|
+
## Revisar sem apagar a pessoa
|
|
114
|
+
|
|
115
|
+
Revisão é a menor edição que resolve. Corrige o tique, o erro e o trecho ilegível, e deixa em paz a frase que já funciona. Não deixa todo parágrafo igualmente arrumado, assimetria é sinal de humano. Não inventa número, exemplo nem opinião que não estava no original.
|
|
95
116
|
|
|
96
117
|
## O que manter
|
|
97
118
|
|
|
@@ -185,15 +206,15 @@ NÃO chame create de novo enquanto renderiza: cria outro vídeo e cobra de novo.
|
|
|
185
206
|
|
|
186
207
|
Sonorize sempre o ORIGINAL, nunca uma variante. Acompanhe com \`action=status\` no imageId NOVO que o sonorize devolve.
|
|
187
208
|
|
|
188
|
-
## Extrair
|
|
209
|
+
## Extrair o deepshadow (ADMIN)
|
|
189
210
|
|
|
190
211
|
\`action=shadows\` com \`videoUrl\` (URL pública) e \`title\` extrai o mapa de profundidade de um vídeo: 200 Sinapses/segundo, com refund na falha. Passe \`durationSec\` quando souber, pra cobrar proporcional; sem ela vai no flat ~2000.
|
|
191
212
|
|
|
192
|
-
|
|
213
|
+
O deepshadow cai na SUA timeline de vídeos (quem extrai vira dono) e vira ficha no Acervo como driving reutilizável pro Shot Mimic e o Kling Motion. \`action=shadows-list\` lista os prontos.
|
|
193
214
|
|
|
194
215
|
## Vídeos Programáticos são outra coisa
|
|
195
216
|
|
|
196
|
-
|
|
217
|
+
O Lab de filmes-de-código da casa (/experimentos/films) tem cinco tipos: demo (UI clonada mais câmera), aula-tour (telas reais mais narração), essay (fita-ensaio abstrata), tipografia-musical (a música dirige o corte) e dataviz (números no tempo).
|
|
197
218
|
|
|
198
219
|
O RENDER não sai deste connector: um agente local no repo da casa produz o mp4. Mas o CICLO na plataforma fecha por aqui, sem custo: \`film-list\`, \`film-get\`, \`film-upsert\`, \`film-status\`, \`film-publish\`. Membro pedindo "fita-ensaio" ou "demo film": aponte pra tela e pro agente local.`,
|
|
199
220
|
},
|
|
@@ -231,7 +252,7 @@ Refs valem pros modelos robustos (nano-banana-2, gpt-image-2-*, grok-2-image*).
|
|
|
231
252
|
|
|
232
253
|
## Cuidados
|
|
233
254
|
|
|
234
|
-
- \`generate\` é SÍNCRONA e cobra ao concluir. Modelo pesado (Pro, gpt-image-2-high, Grok quality, 2K/4K) cai na regra do timeout: cheque \`sapiens_gallery action=list\` antes de repetir, senão cobra duas vezes.
|
|
255
|
+
- \`generate\` é SÍNCRONA e cobra ao concluir. Modelo pesado (Pro, gpt-image-2-high, Grok quality, Seedream 5.0 Pro, 2K/4K) cai na regra do timeout: cheque \`sapiens_gallery action=list\` antes de repetir, senão cobra duas vezes. O \`seedream-5-0-pro\` foi medido em ~140s, ACIMA do teto de 120s do cliente, então o Timeout nele é o esperado e a imagem está lá.
|
|
235
256
|
- \`request_generation\` NÃO gera imagem: só cria a row pendente e debita, pra modelos \`sapiens-video-*\` antes de chamar vídeo ou shorts.
|
|
236
257
|
- Uma imagem só vira pública (e ganha página indexável) com \`sapiens_gallery action=publish\`.
|
|
237
258
|
|
|
@@ -242,12 +263,21 @@ Aí não é geração base, é o Studio dela. Veja a skill \`studio\`.`,
|
|
|
242
263
|
{
|
|
243
264
|
name: "studio",
|
|
244
265
|
title: "Meu Studio e a Emancipação",
|
|
245
|
-
description: "
|
|
246
|
-
body: `##
|
|
266
|
+
description: "O studio é o perfil de EMPRESA da pessoa (obra, time, endereço público) e é também a identidade que o useStudio aplica na geração. Puxe quando ela disser 'do meu jeito', 'na minha marca', falar do studio dela, ou pedir casa própria.",
|
|
267
|
+
body: `## O que o studio é
|
|
268
|
+
|
|
269
|
+
O studio é o **perfil de empresa** da pessoa: um endereço público (\`sapiensinteticos.com/studios/<slug>\`) com a obra, o time e o que a casa faz. Não é uma paleta de ferramentas, e não tem níveis: isso morreu.
|
|
247
270
|
|
|
248
|
-
|
|
271
|
+
Duas coisas moram nele, e vale separar:
|
|
249
272
|
|
|
250
|
-
**
|
|
273
|
+
- **A página.** Obra, time, sobre, capa, logo, folha. Quem edita é o membro, na própria página, no modo edição. Você não edita isso pelo MCP.
|
|
274
|
+
- **A identidade de geração.** Marca e personagem-operador, que o \`useStudio\` aplica.
|
|
275
|
+
|
|
276
|
+
Uma pessoa pode ter até 4 studios e integrar até 4. O que o \`useStudio\` aplica é o **primário** dela; o servidor resolve pela SESSÃO, você nunca passa id.
|
|
277
|
+
|
|
278
|
+
## Studio vs base: não misture
|
|
279
|
+
|
|
280
|
+
**Seguindo o studio:** \`sapiens_image\` com \`useStudio=true\`. O servidor acha o studio primário e aplica marca, personagem e vibe sozinho (o que você passar explícito vence). O retorno traz \`studioApplied=true\`.
|
|
251
281
|
|
|
252
282
|
Use quando ela disser "no meu studio", "na minha marca", "do meu jeito", "como sempre".
|
|
253
283
|
|
|
@@ -257,11 +287,17 @@ Ou é studio, ou é base. Não misture na mesma peça.
|
|
|
257
287
|
|
|
258
288
|
## Antes de criar no studio
|
|
259
289
|
|
|
260
|
-
\`sapiens_studios action=mine\` mostra
|
|
290
|
+
\`sapiens_studios action=mine\` mostra nome, endereço público, marca, operador e o tamanho do time.
|
|
291
|
+
|
|
292
|
+
Se você pediu \`useStudio=true\` e voltou \`studioApplied=false\`, a pessoa ainda não fundou uma casa: avise e aponte /dashboard/studio.
|
|
293
|
+
|
|
294
|
+
## O time
|
|
295
|
+
|
|
296
|
+
Gente entra por convite, e o convite exige **follow mútuo**: os dois precisam já se seguir. Personagem do próprio elenco entra sem convite, é posse. Teto de 4 pessoas por casa.
|
|
261
297
|
|
|
262
|
-
|
|
298
|
+
A obra da página é automática por default: a soma dos Destaques de quem está no time. Se alguém empurrar uma peça à mão, ela passa a ser curada. Tudo isso se faz na página, não por aqui.
|
|
263
299
|
|
|
264
|
-
## Emancipação
|
|
300
|
+
## Emancipação
|
|
265
301
|
|
|
266
302
|
O passo grande: quando o membro quer a casa PRÓPRIA dele, site ou produto próprio, FORA do Sapiens.
|
|
267
303
|
|
package/dist/tools/aula.js
CHANGED
|
@@ -2,26 +2,84 @@ import { z } from "zod";
|
|
|
2
2
|
import { convexMutation, convexQuery, getSessionToken } from "../convexClient.js";
|
|
3
3
|
import { need } from "../schema.js";
|
|
4
4
|
/**
|
|
5
|
-
* sapiens_aula — CRUD do deck de aula
|
|
5
|
+
* sapiens_aula — CRUD do deck de aula via session token.
|
|
6
6
|
* ADMIN-ONLY (requireMcpAdmin no Convex): aula é conteúdo de mentor, não de
|
|
7
|
-
* aluno. Substitui
|
|
8
|
-
*
|
|
7
|
+
* aluno. Substitui os scripts de disco: o Claude edita e publica direto no
|
|
8
|
+
* Convex, fonte de verdade que o /aulas/<slug> lê.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Duas famílias de sub-action, porque existem dois tipos de aula:
|
|
11
|
+
*
|
|
12
|
+
* AULA MODULAR (tem `source = { recipe, modules[] }`, o padrão hoje): os
|
|
13
|
+
* slides são MATERIALIZADOS na leitura a partir da fonte. Editar o slide
|
|
14
|
+
* materializado não adianta, some no próximo materialize. Fluxo certo:
|
|
15
|
+
* map -> module -> module-save (conteúdo)
|
|
16
|
+
* recipe-op (ordem dos módulos na aula)
|
|
17
|
+
* O `map` é o índice barato: dá os blocos e os ids de módulo sem arrastar os
|
|
18
|
+
* 45 slides junto. Só depois dele você sabe qual `moduleId` pedir.
|
|
19
|
+
*
|
|
20
|
+
* AULA LEGADA (sem source): o `slides` É a fonte, e o caminho é get/upsert
|
|
21
|
+
* com o objeto inteiro.
|
|
22
|
+
*
|
|
23
|
+
* `meta` (título, série, data, duração, draft/published) e `delete` valem pras
|
|
24
|
+
* duas.
|
|
14
25
|
*/
|
|
15
26
|
export const aulaSchema = z.object({
|
|
16
|
-
action: z.enum([
|
|
27
|
+
action: z.enum([
|
|
28
|
+
"list",
|
|
29
|
+
"get",
|
|
30
|
+
"map",
|
|
31
|
+
"module",
|
|
32
|
+
"module-save",
|
|
33
|
+
"recipe-op",
|
|
34
|
+
"meta",
|
|
35
|
+
"upsert",
|
|
36
|
+
"delete",
|
|
37
|
+
]),
|
|
17
38
|
slug: z
|
|
18
39
|
.string()
|
|
19
40
|
.optional()
|
|
20
|
-
.describe("kebab-case (a-z, 0-9, hífen), ex: 2026-06-25-minha-aula. Obrigatório
|
|
41
|
+
.describe("kebab-case (a-z, 0-9, hífen), ex: 2026-06-25-minha-aula. Obrigatório em tudo menos list."),
|
|
21
42
|
aula: z
|
|
22
43
|
.any()
|
|
23
44
|
.optional()
|
|
24
|
-
.describe("Objeto completo da aula (obrigatório pra upsert). Campos top-level: title (obrig), subtitle?, data? (YYYY-MM-DD), duration?, tag?, mentorAgenda?, slides[] (≥1). Cada slide é { type, ...campos }. Tipos: cover (eyebrow/title/subtitle/meta), cover-image/section-image/content-image (imageUrl + campos), agenda (items:[{num,title,subtitle,time}]), content (eyebrow/title/body[markdown ou HTML]/list[]/listType), two-col (cols:[{h,body}]), quote (text/attribution), callout (tone:tip|warn|note/tag/body), comic (panels:[{imageUrl,caption}]), pause, close (eyebrow/title/items[]). Voz Sapiens: 1ª pessoa, anti-corporate, SEM travessão (—). O servidor re-linta a voz e grava voiceWarnings."),
|
|
45
|
+
.describe("Objeto completo da aula (obrigatório pra upsert). Campos top-level: title (obrig), subtitle?, data? (YYYY-MM-DD), duration?, tag?, mentorAgenda?, slides[] (≥1). Cada slide é { type, ...campos }. Tipos: cover (eyebrow/title/subtitle/meta), cover-image/section-image/content-image (imageUrl + campos), agenda (items:[{num,title,subtitle,time}]), content (eyebrow/title/body[markdown ou HTML]/list[]/listType), two-col (cols:[{h,body}]), video (videoUrl OU videos:[{h,videoUrl,caption}] pra comparar lado a lado), quote (text/attribution), callout (tone:tip|warn|note/tag/body), comic (panels:[{imageUrl,caption}]), pause, close (eyebrow/title/items[]). Voz Sapiens: 1ª pessoa, anti-corporate, SEM travessão (—). O servidor re-linta a voz e grava voiceWarnings."),
|
|
46
|
+
moduleId: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe("id do módulo dentro da fonte (kebab-case, ex: folha-tres-takes). Obrigatório pra module, module-save e recipe-op. Descubra os ids com action=map."),
|
|
50
|
+
module: z
|
|
51
|
+
.any()
|
|
52
|
+
.optional()
|
|
53
|
+
.describe("action=module-save: o módulo inteiro { id, title, concept, audience[], slides[] }. Mesmo shape de slide do `aula.slides`. Omita (ou mande null) pra REMOVER o módulo da fonte e de todos os blocos."),
|
|
54
|
+
placeAfter: z
|
|
55
|
+
.string()
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("action=module-save de módulo NOVO: id de um módulo já na receita; o novo entra logo depois dele, no mesmo bloco. Alternativa ao `bloco`."),
|
|
58
|
+
bloco: z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Título do bloco da receita (ex: 'A Folha'). Em module-save de módulo novo, entra no fim desse bloco. Em recipe-op, é o bloco de destino."),
|
|
62
|
+
op: z
|
|
63
|
+
.enum(["move", "remove", "add"])
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("action=recipe-op: 'move' reordena (use toIndex, e bloco pra mudar de bloco), 'remove' tira o módulo da aula sem apagar o conteúdo dele da fonte, 'add' cita na receita um módulo que já existe na fonte."),
|
|
66
|
+
toIndex: z
|
|
67
|
+
.number()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("action=recipe-op op=move|add: posição (0 = primeiro do bloco). Sem ele, vai pro fim."),
|
|
70
|
+
title: z.string().optional().describe("action=meta: novo título."),
|
|
71
|
+
subtitle: z.string().optional().describe("action=meta: novo subtítulo."),
|
|
72
|
+
tag: z.string().optional().describe("action=meta: série/etiqueta (ex: 'Produção · Vídeo dirigido')."),
|
|
73
|
+
data: z.string().optional().describe("action=meta: data YYYY-MM-DD."),
|
|
74
|
+
duration: z.string().optional().describe("action=meta: duração legível (ex: '3h30')."),
|
|
75
|
+
status: z
|
|
76
|
+
.enum(["draft", "published"])
|
|
77
|
+
.optional()
|
|
78
|
+
.describe("action=meta: 'draft' tira do ar (só admin vê), 'published' põe no ar."),
|
|
79
|
+
force: z
|
|
80
|
+
.boolean()
|
|
81
|
+
.optional()
|
|
82
|
+
.describe("action=delete: apaga mesmo estando publicada. Sem isso, aula no ar é recusada e o caminho é tirar de circulação antes (action=meta status=draft)."),
|
|
25
83
|
});
|
|
26
84
|
export async function aula(args) {
|
|
27
85
|
const sessionToken = getSessionToken();
|
|
@@ -36,12 +94,62 @@ export async function aula(args) {
|
|
|
36
94
|
});
|
|
37
95
|
return found ? { found: true, aula: found } : { found: false, slug };
|
|
38
96
|
}
|
|
97
|
+
case "map":
|
|
98
|
+
return await convexQuery("mcpExtras:mcpAulaMap", {
|
|
99
|
+
sessionToken,
|
|
100
|
+
slug: need(args.slug, "slug"),
|
|
101
|
+
});
|
|
102
|
+
case "module":
|
|
103
|
+
return await convexQuery("mcpExtras:mcpAulaModule", {
|
|
104
|
+
sessionToken,
|
|
105
|
+
slug: need(args.slug, "slug"),
|
|
106
|
+
moduleId: need(args.moduleId, "moduleId"),
|
|
107
|
+
});
|
|
108
|
+
case "module-save": {
|
|
109
|
+
// `module` é z.any(): cliente costuma serializar objeto sem tipo como
|
|
110
|
+
// string JSON. Normaliza aqui (o servidor também parseia, mas o shape
|
|
111
|
+
// certo sai daqui). Ausente vira null: é o sinal de remoção.
|
|
112
|
+
let mod = args.module;
|
|
113
|
+
if (typeof mod === "string") {
|
|
114
|
+
try {
|
|
115
|
+
mod = JSON.parse(mod);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
throw new Error('Arg "module" veio como string mas não é JSON válido.');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return await convexMutation("mcpExtras:mcpAulaModuleSave", {
|
|
122
|
+
sessionToken,
|
|
123
|
+
slug: need(args.slug, "slug"),
|
|
124
|
+
moduleId: need(args.moduleId, "moduleId"),
|
|
125
|
+
module: mod ?? null,
|
|
126
|
+
placeAfter: args.placeAfter,
|
|
127
|
+
bloco: args.bloco,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
case "recipe-op":
|
|
131
|
+
return await convexMutation("mcpExtras:mcpAulaRecipeOp", {
|
|
132
|
+
sessionToken,
|
|
133
|
+
slug: need(args.slug, "slug"),
|
|
134
|
+
op: need(args.op, "op"),
|
|
135
|
+
moduleId: need(args.moduleId, "moduleId"),
|
|
136
|
+
bloco: args.bloco,
|
|
137
|
+
toIndex: args.toIndex,
|
|
138
|
+
});
|
|
139
|
+
case "meta":
|
|
140
|
+
return await convexMutation("mcpExtras:mcpAulaMeta", {
|
|
141
|
+
sessionToken,
|
|
142
|
+
slug: need(args.slug, "slug"),
|
|
143
|
+
title: args.title,
|
|
144
|
+
subtitle: args.subtitle,
|
|
145
|
+
tag: args.tag,
|
|
146
|
+
data: args.data,
|
|
147
|
+
duration: args.duration,
|
|
148
|
+
status: args.status,
|
|
149
|
+
});
|
|
39
150
|
case "upsert": {
|
|
40
151
|
const slug = need(args.slug, "slug");
|
|
41
152
|
const raw = need(args.aula, "aula");
|
|
42
|
-
// `aula` é z.any(): sem tipo declarado, o cliente costuma serializar o
|
|
43
|
-
// objeto como string JSON. Normaliza aqui pra mandar objeto sempre (o
|
|
44
|
-
// servidor também parseia string, mas o shape certo sai daqui).
|
|
45
153
|
let aulaObj = raw;
|
|
46
154
|
if (typeof aulaObj === "string") {
|
|
47
155
|
try {
|
|
@@ -57,5 +165,13 @@ export async function aula(args) {
|
|
|
57
165
|
aula: aulaObj,
|
|
58
166
|
});
|
|
59
167
|
}
|
|
168
|
+
case "delete":
|
|
169
|
+
// Sem undo do lado do servidor: quem quiser guardar o conteúdo puxa
|
|
170
|
+
// action=get antes. Aula publicada é recusada até vir force.
|
|
171
|
+
return await convexMutation("mcpExtras:mcpDeleteAula", {
|
|
172
|
+
sessionToken,
|
|
173
|
+
slug: need(args.slug, "slug"),
|
|
174
|
+
force: args.force,
|
|
175
|
+
});
|
|
60
176
|
}
|
|
61
177
|
}
|
package/dist/tools/character.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { httpUrl } from "../schema.js";
|
|
3
|
-
import { convexQuery, convexMutation, getSessionToken } from "../convexClient.js";
|
|
3
|
+
import { convexQuery, convexMutation, convexAction, getSessionToken } from "../convexClient.js";
|
|
4
4
|
/**
|
|
5
5
|
* sapiens_character — personagens (character sheets) do Sapiens.
|
|
6
6
|
*
|
|
@@ -42,12 +42,13 @@ export const characterSchema = z.object({
|
|
|
42
42
|
"remove_image",
|
|
43
43
|
"set_main_image",
|
|
44
44
|
"reorder_images",
|
|
45
|
+
"generate_sheet",
|
|
45
46
|
"delete",
|
|
46
47
|
]),
|
|
47
48
|
characterId: z
|
|
48
49
|
.string()
|
|
49
50
|
.optional()
|
|
50
|
-
.describe("ID do personagem (influencers:_id). Obrigatório em get/add_image/set_card/activate/set_visibility. Descubra via list_public ou list_mine."),
|
|
51
|
+
.describe("ID do personagem (influencers:_id). Obrigatório em get/add_image/set_card/activate/set_visibility/generate_sheet. Descubra via list_public ou list_mine."),
|
|
51
52
|
limit: z
|
|
52
53
|
.number()
|
|
53
54
|
.int()
|
|
@@ -240,6 +241,18 @@ export async function character(args) {
|
|
|
240
241
|
orderedUrls: args.orderedUrls,
|
|
241
242
|
});
|
|
242
243
|
}
|
|
244
|
+
// -------- generate_sheet: a ficha (página-pôster) do personagem --------
|
|
245
|
+
// Geração SÍNCRONA que COBRA: cai na regra do timeout. Se voltar Timeout,
|
|
246
|
+
// NÃO repita às cegas: confira em action=get (campo sheets) se a peça caiu.
|
|
247
|
+
if (args.action === "generate_sheet") {
|
|
248
|
+
if (!args.characterId)
|
|
249
|
+
throw new Error("action=generate_sheet exige characterId.");
|
|
250
|
+
const sessionToken = getSessionToken();
|
|
251
|
+
return await convexAction("characterSheetActions:mcpGenerateCharacterSheet", {
|
|
252
|
+
sessionToken,
|
|
253
|
+
influencerId: args.characterId,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
243
256
|
// -------- delete: apaga o próprio personagem (permanente) --------
|
|
244
257
|
if (args.action === "delete") {
|
|
245
258
|
if (!args.characterId)
|
package/dist/tools/reference.js
CHANGED
|
@@ -7,13 +7,19 @@ import { convexAction, convexQuery, getSessionToken } from "../convexClient.js";
|
|
|
7
7
|
* navegar os bancos e pegar o que vira referência em imagem (sapiens_image) ou
|
|
8
8
|
* vídeo (sapiens_video).
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* As duas são a MESMA porta em transportes diferentes (browser e agente), e a
|
|
11
|
+
* lei das duas mora em `apps/sapiens/PICKER_PATTERNS.md`. A invariante que
|
|
12
|
+
* importa aqui: banco novo no picker web nasce com bucket irmão neste arquivo,
|
|
13
|
+
* senão o agente enxerga menos que o browser e a paridade quebra em silêncio.
|
|
14
|
+
*
|
|
15
|
+
* Buckets (as abas do popup, completas):
|
|
11
16
|
* - history imagens recentes do user (privadas + públicas)
|
|
12
17
|
* - favorites imagens que o user curtiu (só as suas)
|
|
13
18
|
* - videos vídeos do user (Meus Vídeos)
|
|
14
19
|
* - stock_video Banco de Vídeo da casa (clipes/B-roll); aceita `term`/`orientation`/`loopOnly`
|
|
15
20
|
* - acervo stock + comunidade de IMAGEM (público); aceita `term` (busca) e `source`
|
|
16
21
|
* - characters personagens; `mode` = 'mine' (default) ou 'public'
|
|
22
|
+
* - deepshadow guias de movimento; `shadowSource` = 'house' (banco curado, default) ou 'mine'
|
|
17
23
|
*
|
|
18
24
|
* Cada item volta normalizado:
|
|
19
25
|
* - imagem PRÓPRIA (history/favorites): `imageId` + `url` → use imageId em
|
|
@@ -28,11 +34,12 @@ export const referenceSchema = z.object({
|
|
|
28
34
|
.describe("'browse' navega um bucket do acervo; 'resolve' acha UM asset pelo ID citável (handle <tipo>_<id>) " +
|
|
29
35
|
"e diz se é seu / público + devolve a url pra usar de referência."),
|
|
30
36
|
bucket: z
|
|
31
|
-
.enum(["history", "favorites", "videos", "stock_video", "acervo", "characters"])
|
|
37
|
+
.enum(["history", "favorites", "videos", "stock_video", "acervo", "characters", "deepshadow"])
|
|
32
38
|
.optional()
|
|
33
39
|
.describe("Só 'browse': qual banco navegar: 'history' (suas imagens recentes), 'favorites' (as que você curtiu), " +
|
|
34
40
|
"'videos' (seus vídeos), 'stock_video' (Banco de Vídeo da casa: clipes/B-roll prontos, aceita term/orientation/loopOnly), " +
|
|
35
|
-
"'acervo' (stock + comunidade públicos de IMAGEM), 'characters' (personagens)
|
|
41
|
+
"'acervo' (stock + comunidade públicos de IMAGEM), 'characters' (personagens), " +
|
|
42
|
+
"'deepshadow' (guias de movimento: os SEUS com shadowSource='mine', ou o banco curado da casa por default)."),
|
|
36
43
|
handle: z
|
|
37
44
|
.string()
|
|
38
45
|
.optional()
|
|
@@ -60,6 +67,10 @@ export const referenceSchema = z.object({
|
|
|
60
67
|
.enum(["all", "stock", "community"])
|
|
61
68
|
.optional()
|
|
62
69
|
.describe("Só bucket 'acervo': fonte. Default 'all' (stock + comunidade)."),
|
|
70
|
+
shadowSource: z
|
|
71
|
+
.enum(["mine", "house"])
|
|
72
|
+
.optional()
|
|
73
|
+
.describe("Só bucket 'deepshadow': 'mine' (os que VOCÊ extraiu) ou 'house' (o banco curado da casa, default)."),
|
|
63
74
|
orientation: z
|
|
64
75
|
.enum(["vertical", "horizontal", "square"])
|
|
65
76
|
.optional()
|
|
@@ -97,7 +108,7 @@ export async function reference(args) {
|
|
|
97
108
|
if (args.action === "browse") {
|
|
98
109
|
if (!args.bucket) {
|
|
99
110
|
return {
|
|
100
|
-
error: "browse exige `bucket` (history | favorites | videos | stock_video | acervo | characters).",
|
|
111
|
+
error: "browse exige `bucket` (history | favorites | videos | stock_video | acervo | characters | deepshadow).",
|
|
101
112
|
};
|
|
102
113
|
}
|
|
103
114
|
const res = await convexAction("mcpReferences:referenceBrowse", {
|
|
@@ -110,6 +121,7 @@ export async function reference(args) {
|
|
|
110
121
|
orientation: args.orientation,
|
|
111
122
|
loopOnly: args.loopOnly,
|
|
112
123
|
mode: args.mode,
|
|
124
|
+
shadowSource: args.shadowSource,
|
|
113
125
|
});
|
|
114
126
|
let note;
|
|
115
127
|
if (args.bucket === "videos") {
|
|
@@ -120,6 +132,10 @@ export async function reference(args) {
|
|
|
120
132
|
note =
|
|
121
133
|
"Clipes do Banco de Vídeo da casa (B-roll pronto). Use a `url` do clipe: como referência de vídeo em sapiens_video (mesma rail do Meus Vídeos), de fundo/atmosfera, ou baixe direto. orientation/durationSeconds/loopFriendly ajudam a escolher. Não são imagem: NÃO servem de frame inicial/final (pra frame use uma IMAGEM).";
|
|
122
134
|
}
|
|
135
|
+
else if (args.bucket === "deepshadow") {
|
|
136
|
+
note =
|
|
137
|
+
"Guias de movimento (mapa de profundidade). Use a `url` em sapiens_video referenceVideoUrls: a coreografia e a câmera do clipe guiam o take. `thumbnailUrl` é só preview (a soma com esqueleto), nunca mande ela como driving. Teto de duração varia por motor.";
|
|
138
|
+
}
|
|
123
139
|
else if (args.bucket === "acervo" || args.bucket === "characters") {
|
|
124
140
|
note =
|
|
125
141
|
"São referências públicas: use a `url` (characters trazem mainImageUrl + imageUrls) em sapiens_image referenceImageUrls, ou em sapiens_video startImageUrl/endImageUrl. Não são suas, então NÃO entram em sourceImageIds.";
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { convexQuery, convexMutation, getSessionToken, } from "../convexClient.js";
|
|
3
|
+
/**
|
|
4
|
+
* sapiens_semana — o ofício da semana do membro pelo Claude.
|
|
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
|
|
9
|
+
* produz em várias frentes, então a régua precisa existir aqui também.
|
|
10
|
+
*
|
|
11
|
+
* Sub-actions:
|
|
12
|
+
* - get: como está a semana (labs utilizados, quanto a Casa Cheia renderia
|
|
13
|
+
* no fecho, e se sobrou semana anterior pra fechar).
|
|
14
|
+
* - fechar: fecha as semanas pendentes e credita a Casa Cheia de cada uma.
|
|
15
|
+
*
|
|
16
|
+
* Identidade SEMPRE pelo sessionToken. Sem custo em Sinapses: isto PAGA XP, não
|
|
17
|
+
* cobra. Idempotente no servidor, então chamar duas vezes não credita duas vezes.
|
|
18
|
+
*/
|
|
19
|
+
export const semanaSchema = z.object({
|
|
20
|
+
action: z.enum(["get", "fechar"]),
|
|
21
|
+
});
|
|
22
|
+
export async function semana(args) {
|
|
23
|
+
const sessionToken = getSessionToken();
|
|
24
|
+
if (args.action === "get") {
|
|
25
|
+
const s = await convexQuery("labs:mcpGetMinhaSemana", { sessionToken });
|
|
26
|
+
if (!s)
|
|
27
|
+
throw new Error("Não consegui ler sua semana. Confira o login.");
|
|
28
|
+
const usados = (s.labs ?? []).filter((l) => l.usado);
|
|
29
|
+
const vazios = (s.labs ?? []).filter((l) => !l.usado);
|
|
30
|
+
return {
|
|
31
|
+
semana: s.weekKey,
|
|
32
|
+
labsUtilizados: usados.map((l) => ({
|
|
33
|
+
lab: l.label,
|
|
34
|
+
pecas: l.pieces,
|
|
35
|
+
pago: l.pago,
|
|
36
|
+
})),
|
|
37
|
+
labsAindaVazios: vazios.map((l) => l.label),
|
|
38
|
+
xpDeOficioNaSemana: s.oficioDaSemana,
|
|
39
|
+
casaCheiaSeFecharAgora: s.casaCheiaPrevista,
|
|
40
|
+
semanasPendentes: s.semanasPendentes ?? [],
|
|
41
|
+
note: (s.semanasPendentes?.length ?? 0) > 0
|
|
42
|
+
? "Tem semana fechada esperando: action=fechar credita a Casa Cheia dela."
|
|
43
|
+
: "A Casa Cheia da semana corrente é creditada quando ela virar e você fechar.",
|
|
44
|
+
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.",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (args.action === "fechar") {
|
|
48
|
+
const r = await convexMutation("labs:mcpFecharMinhaSemana", {
|
|
49
|
+
sessionToken,
|
|
50
|
+
});
|
|
51
|
+
if (!r?.fechadas) {
|
|
52
|
+
return {
|
|
53
|
+
fechadas: 0,
|
|
54
|
+
xp: 0,
|
|
55
|
+
note: "Não tinha semana pendente. A semana corrente só fecha depois que ela virar.",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
fechadas: r.fechadas,
|
|
60
|
+
xpCreditado: r.xp,
|
|
61
|
+
note: `Casa cheia creditada: +${r.xp} XP em ${r.fechadas} semana(s). O servidor fecha até 12 por chamada, então repita se ainda sobrar.`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
throw new Error("action inválida. Use get ou fechar.");
|
|
65
|
+
}
|
package/dist/tools/studios.js
CHANGED
|
@@ -15,7 +15,7 @@ import { convexAction, convexQuery, getSessionToken } from "../convexClient.js";
|
|
|
15
15
|
export const studiosSchema = z.object({
|
|
16
16
|
action: z
|
|
17
17
|
.enum(["list", "get", "publishable_url", "mine", "emancipar", "module"])
|
|
18
|
-
.describe("mine = o SEU studio (
|
|
18
|
+
.describe("mine = o SEU studio (o perfil de empresa da sua casa): nome, endereço público, marca, operador e tamanho do time, pra você gerar com useStudio. list/get = catálogo de estúdios da casa. publishable_url = URL de artigo. " +
|
|
19
19
|
"emancipar = INICIA a Emancipação (Nível 3 do Studio): puxa o blueprint-mestre pra VOCÊ (Claude) construir a casa PRÓPRIA do membro, na infra DELE (Vercel + Convex + domínio dele), FORA do Sapiens. Devolve a identidade do studio dele já hidratada + o índice de módulos + o guia da Fundação. " +
|
|
20
20
|
"module = puxa o guia de UM módulo de infra pra continuar a construção (ex: fundacao, sapiens-connect, midia, telegram, email, auth)."),
|
|
21
21
|
studio: z
|
|
@@ -149,15 +149,18 @@ const STUDIOS = {
|
|
|
149
149
|
},
|
|
150
150
|
};
|
|
151
151
|
export async function studios(args) {
|
|
152
|
-
// action=mine: o
|
|
153
|
-
// non-PII pro Claude saber o que está montado antes de gerar
|
|
152
|
+
// action=mine: o studio PRIMÁRIO do user logado (o perfil de empresa da casa
|
|
153
|
+
// dele), resumo non-PII pro Claude saber o que está montado antes de gerar
|
|
154
|
+
// com useStudio. Os campos `level`/`levelLabel`/`tools` vêm vazios: os níveis
|
|
155
|
+
// e as ferramentas à la carte morreram quando o studio virou company page, e
|
|
156
|
+
// eles só continuam no retorno porque pacotes já publicados os imprimem.
|
|
154
157
|
if (args.action === "mine") {
|
|
155
158
|
const sessionToken = getSessionToken();
|
|
156
159
|
const studio = await convexAction("desktopMcp:studioMine", { sessionToken });
|
|
157
160
|
if (!studio) {
|
|
158
161
|
return {
|
|
159
162
|
studio: null,
|
|
160
|
-
note: "Você ainda não
|
|
163
|
+
note: "Você ainda não fundou um studio. Funde o seu em sapiensinteticos.com/dashboard/studio: ele vira uma página pública com a sua obra e o seu time.",
|
|
161
164
|
};
|
|
162
165
|
}
|
|
163
166
|
return { studio };
|
package/dist/tools/video.js
CHANGED
|
@@ -18,7 +18,7 @@ import { httpUrl } from "../schema.js";
|
|
|
18
18
|
* URL e guarda no Acervo (Corpo) como deepshadow reutilizável.
|
|
19
19
|
* 200 Sinapses/segundo (durationSec; sem ela, flat 2000). Refund se falhar.
|
|
20
20
|
* - shadows-list: (ADMIN) lista o banco de motion (deepshadows + guias de corpo)
|
|
21
|
-
* com as duas views por ficha: url =
|
|
21
|
+
* com as duas views por ficha: url = deepshadow puro (driving pros
|
|
22
22
|
* geradores) e skeletonUrl = a soma (sombras + esqueleto, preview
|
|
23
23
|
* humano que separa personagem de objeto). Sem custo.
|
|
24
24
|
* - sonorize: dá som a um clipe SEU já gerado (MMAudio v2): imageId + prompt do
|
|
@@ -26,7 +26,7 @@ import { httpUrl } from "../schema.js";
|
|
|
26
26
|
* fica intacto). Cobra por segundo do clipe; poll via action=status.
|
|
27
27
|
*
|
|
28
28
|
* Vídeos Programáticos (Estúdio de Vídeo, /experimentos/films) — ADMIN, sem custo.
|
|
29
|
-
*
|
|
29
|
+
* O Lab de specs da casa (tabela videoSpecs, 5 kinds: demo | aula-tour | essay |
|
|
30
30
|
* tipografia-musical | dataviz). A PRODUÇÃO do mp4 segue no agente local (skill
|
|
31
31
|
* /film, repo films/); estas actions fecham o CICLO na plataforma sem browser:
|
|
32
32
|
* - film-list: lista os specs (todos os kinds; filtros filmKind/filmStatus).
|
|
@@ -67,12 +67,20 @@ import { httpUrl } from "../schema.js";
|
|
|
67
67
|
* seu e o prompt edita a MESMA cena (troca item/personagem preservando
|
|
68
68
|
* o resto). Não aceita mídia do user (ignora references/durationSec/resolution).
|
|
69
69
|
*
|
|
70
|
+
* FORA DE PROPÓSITO: o `sapiens-video-seedance-fast` (Seedance 1.0 Fast, piso 600)
|
|
71
|
+
* está ativo no catálogo do backend mas NÃO entra neste enum. Ele é geração velha:
|
|
72
|
+
* sem áudio, sem referência e sem frame final. Economiza 200 sinapses no piso contra
|
|
73
|
+
* o 1.5 Pro e perde três capacidades. Quem quer queimar tentativa barata usa o
|
|
74
|
+
* `sapiens-video-seedance-2-mini`, que custa metade do 2.0 com o repertório inteiro.
|
|
75
|
+
* Não "conserte" essa ausência: ela é decisão (29/jul/2026).
|
|
76
|
+
*
|
|
70
77
|
* Custo: server-side por config (duração x resolução [x áudio]). i2v/motion usam
|
|
71
78
|
* `references` em base64 (role 'start' = imagem inicial, 'end' = frame final,
|
|
72
79
|
* 'driving' = vídeo de movimento do Motion).
|
|
73
80
|
*
|
|
74
81
|
* Retorna `{ success, url, imageId, cost }` ou `{ success: false, error }`.
|
|
75
82
|
*/
|
|
83
|
+
// "sapiens-video-seedance-fast" (1.0 Fast) fica de fora de propósito, ver bloco acima.
|
|
76
84
|
const VIDEO_MODELS = [
|
|
77
85
|
"sapiens-video-seedance-15",
|
|
78
86
|
"sapiens-video-seedance",
|
|
@@ -107,7 +115,7 @@ export const videoSchema = z.object({
|
|
|
107
115
|
"film-publish",
|
|
108
116
|
"film-delete",
|
|
109
117
|
]),
|
|
110
|
-
// --- Vídeos Programáticos (film-*):
|
|
118
|
+
// --- Vídeos Programáticos (film-*): Lab de specs da casa, ADMIN, sem custo ---
|
|
111
119
|
filmKind: z
|
|
112
120
|
.enum(FILM_KINDS)
|
|
113
121
|
.optional()
|
|
@@ -144,7 +152,7 @@ export const videoSchema = z.object({
|
|
|
144
152
|
search: z
|
|
145
153
|
.string()
|
|
146
154
|
.optional()
|
|
147
|
-
.describe("action=shadows-list: filtro de busca opcional (título/tags). Sem ele, lista o banco inteiro (até 300). Cada item traz url (
|
|
155
|
+
.describe("action=shadows-list: filtro de busca opcional (título/tags). Sem ele, lista o banco inteiro (até 300). Cada item traz url (deepshadow puro, driving) e skeletonUrl (soma com esqueleto, preview humano) quando existe."),
|
|
148
156
|
// --- action=showcase (curadoria da vitrine /conectar-claude) ---
|
|
149
157
|
slug: z
|
|
150
158
|
.string()
|
|
@@ -262,7 +270,7 @@ export const videoSchema = z.object({
|
|
|
262
270
|
.describe("action=create (só Seedance): 1 URL pública (host da casa) de um VÍDEO DE MOVIMENTO (role 'refvideo' -> reference_videos, <=15s): " +
|
|
263
271
|
"a coreografia/câmera do clipe GUIA o take sem ser recriado plano a plano (isso é o Shot Mimic). " +
|
|
264
272
|
"Combina com o fluxo storyboard: folha = beats, vídeo = movimento, personagem = identidade. " +
|
|
265
|
-
"
|
|
273
|
+
"Deepshadows do banco de motion servem direto (ADMIN: descubra com action=shadows-list)."),
|
|
266
274
|
// Frame inicial/final por ARQUIVO LOCAL (paridade com o upload do gerador do
|
|
267
275
|
// site). Só no MCP instalado (stdio): o processo lê o arquivo do disco e sobe
|
|
268
276
|
// como reference role 'start'/'end', sem o base64 passar pelo contexto do
|
|
@@ -390,7 +398,7 @@ export async function video(args) {
|
|
|
390
398
|
if (args.action === "demos") {
|
|
391
399
|
return await convexQuery("videoSpecs:mcpListMyDemoFilms", { sessionToken });
|
|
392
400
|
}
|
|
393
|
-
// --- Vídeos Programáticos (
|
|
401
|
+
// --- Vídeos Programáticos (Lab de specs, ADMIN, sem custo) ---
|
|
394
402
|
if (args.action === "film-list") {
|
|
395
403
|
return await convexQuery("videoSpecs:mcpListMyVideoSpecs", {
|
|
396
404
|
sessionToken,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.43.
|
|
3
|
+
"version": "1.43.2",
|
|
4
4
|
"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.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|