sapiens-mcp 1.29.0 → 1.29.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/convexClient.js +6 -2
- package/dist/index.js +6 -6
- package/dist/tools/image.js +33 -4
- package/dist/tools/meta.js +12 -2
- package/dist/tools/musicator.js +9 -8
- package/dist/tools/shorts.js +4 -2
- package/dist/tools/studios.js +1 -1
- package/dist/tools/video.js +39 -3
- package/package.json +1 -1
package/dist/convexClient.js
CHANGED
|
@@ -239,10 +239,14 @@ export function describeConvexError(e) {
|
|
|
239
239
|
// Teto de tempo por chamada ao Convex. O ConvexHttpClient não aceita
|
|
240
240
|
// AbortSignal em query/mutation/action, então o bound prático é um race contra
|
|
241
241
|
// um timer. Sem isto, um backend pendurado deixa a chamada MCP presa até o
|
|
242
|
-
// timeout do host, sem erro claro
|
|
242
|
+
// timeout do host, sem erro claro, ruim numa sessão que acabou de mandar
|
|
243
243
|
// debitar Sinapses e não sabe se caiu. NÃO há retry/backoff de propósito:
|
|
244
244
|
// chamadas não-idempotentes (cobrança) não podem re-disparar às cegas.
|
|
245
|
-
|
|
245
|
+
// Default 120s (era 30s): geração síncrona (imagem pesada, artigo, mega-gráfico,
|
|
246
|
+
// carrossel) leva de 30 a 90s e estourava o teto de 30s, voltando 'Timeout' pro
|
|
247
|
+
// cliente MESMO tendo gerado e COBRADO. 120s cobre esses casos; render de vídeo
|
|
248
|
+
// (minutos) ainda precisa do fluxo assíncrono. Override por env pra outro teto.
|
|
249
|
+
const CONVEX_TIMEOUT_MS = Number(process.env.SAPIENS_CONVEX_TIMEOUT_MS) || 120000;
|
|
246
250
|
function withTimeout(p, label) {
|
|
247
251
|
let timer;
|
|
248
252
|
const timeout = new Promise((_, reject) => {
|
package/dist/index.js
CHANGED
|
@@ -36,12 +36,12 @@ import { describeConvexError } from "./convexClient.js";
|
|
|
36
36
|
import { MCP_VERSION } from "./version.js";
|
|
37
37
|
const TOOLS = {
|
|
38
38
|
sapiens_pipeline: {
|
|
39
|
-
description: "CRUD do content pipeline Sapiens (sources/productions/publishables). Sub-actions: list_sources, list_articles (use includeDrafts pra incluir drafts; onlyAvailable pra esconder os já virados em source), get_source, get_production, list_versions, add_article_as_source, create_draft_article_and_source (seed), create_production (sourceId+format → productionId draft), update_production (substitui payload, opcionalmente muda status), finalize_production (cria publishable v1, v2... com snapshot), remove_production, remove_source, set_source_done, update_source_notes, restore_version (volta payload duma versão antiga), propose_mega_grafico_plan (granular: só gera plano via Gemini, devolve fullPrompt+spec), run_mega_grafico_full (ONE-SHOT, recomendado: cria production+propõe plano+gera imagem+aplica selo Sapiens+finaliza publishable numa chamada só), generate_carousel (gera um carrossel editorial standalone a partir de brief OU articleId — 7-9 slides na voz Sapiens + imagens do banco; devolve id + url do editor pro humano abrir, ajustar e exportar; admin-only, cobra Sinapses, reembolsa se falhar). Pra mega_grafico, SEMPRE prefira run_mega_grafico_full em vez de sequenciar manualmente
|
|
39
|
+
description: "CRUD do content pipeline Sapiens (sources/productions/publishables). Sub-actions: list_sources, list_articles (use includeDrafts pra incluir drafts; onlyAvailable pra esconder os já virados em source), get_source, get_production, list_versions, add_article_as_source, create_draft_article_and_source (seed), create_production (sourceId+format → productionId draft), update_production (substitui payload, opcionalmente muda status), finalize_production (cria publishable v1, v2... com snapshot), remove_production, remove_source, set_source_done, update_source_notes, restore_version (volta payload duma versão antiga), propose_mega_grafico_plan (granular: só gera plano via Gemini, devolve fullPrompt+spec), run_mega_grafico_full (ONE-SHOT, recomendado: cria production+propõe plano+gera imagem+aplica selo Sapiens+finaliza publishable numa chamada só), generate_carousel (gera um carrossel editorial standalone a partir de brief OU articleId — 7-9 slides na voz Sapiens + imagens do banco; devolve id + url do editor pro humano abrir, ajustar e exportar; admin-only, cobra Sinapses, reembolsa se falhar). Pra mega_grafico, SEMPRE prefira run_mega_grafico_full em vez de sequenciar manualmente (menos drift). Idempotente só na production (passa productionId pra reusar a MESMA row), mas cada run RE-GERA a imagem e cobra de novo (~900 Sinapses): não é grátis re-rodar. OBRIGATÓRIO perguntar ao user antes se withHelen=true (cartoon Helen interage com tema, ~15-25% do poster) ou false (poster 100% diagramático). Custo ~900-1000 sinapses por geração. run_mega_grafico_full e generate_carousel são SÍNCRONAS e pesadas (Gemini + imagem): podem passar do teto de ~120s do cliente e voltar 'Timeout' MESMO tendo criado a production e cobrado, então cheque /dashboard/admin/content antes de repetir. Use skipFinalize=true se quiser deixar production em 'ready' pro admin revisar antes de publishable. Payload livre por formato — chame sapiens_meta action=formats pra ver schemas sugeridos.",
|
|
40
40
|
schema: pipelineSchema,
|
|
41
41
|
handler: pipeline,
|
|
42
42
|
},
|
|
43
43
|
sapiens_image: {
|
|
44
|
-
description: "Operações de imagem via Sapiens (Gemini, Azure gpt-image-2, Grok, Veo). Sub-actions: 'generate' (gera imagem completa imediato — prompt+model+aspectRatio+size; suporta mode=edit/variation e MULTI-REFERÊNCIA: combine até 4 imagens como referência numa geração só, igual ao modal 'Selecionar Referência' do web — via referenceImageUrls (sua galeria + Acervo + personagens públicos de sapiens_character) e/ou sourceImageIds (ids da sua galeria); refs valem pros modelos robustos nano-banana-2/gpt-image-2-*/grok-2-image*), 'request_generation' (v1.7, cria APENAS row pendente em generatedImages + debita créditos — pra modelos sapiens-video-* ANTES de sapiens_shorts/sapiens_video; whitelist, rate limit 3/min), 'compose' (v1.8, combina persona+screen via Gemini pra app-demo Shorts; 25 sinapses, rate limit 10/min). generate=image one-shot, request_generation=criar row video, compose=montar start frame app-demo. TEMPLATE (v1.17): passe templateSlug numa generate pra usar um super-prompt travado da casa — o `prompt` vira só a CENA (quem + pose + objeto-conceito) e o template embrulha estilo+fundo+enquadramento+ref de traço. 'retrato-sapiens-v1' = retrato editorial cartoon de um personagem no grid verde Sapiens (mesma 'mão' dos artigos); sem ref própria, injeta a Helen como âncora de traço (passar referenceImageUrls troca quem aparece). Mutuamente exclusivo com brandSlug.",
|
|
44
|
+
description: "Operações de imagem via Sapiens (Gemini, Azure gpt-image-2, Grok, Veo). Sub-actions: 'generate' (gera imagem completa imediato — prompt+model+aspectRatio+size; suporta mode=edit/variation e MULTI-REFERÊNCIA: combine até 4 imagens como referência numa geração só, igual ao modal 'Selecionar Referência' do web — via referenceImageUrls (sua galeria + Acervo + personagens públicos de sapiens_character) e/ou sourceImageIds (ids da sua galeria); refs valem pros modelos robustos nano-banana-2/gpt-image-2-*/grok-2-image*), 'request_generation' (v1.7, cria APENAS row pendente em generatedImages + debita créditos — pra modelos sapiens-video-* ANTES de sapiens_shorts/sapiens_video; whitelist, rate limit 3/min), 'compose' (v1.8, combina persona+screen via Gemini pra app-demo Shorts; 25 sinapses, rate limit 10/min). generate=image one-shot, request_generation=criar row video, compose=montar start frame app-demo. TEMPLATE (v1.17): passe templateSlug numa generate pra usar um super-prompt travado da casa — o `prompt` vira só a CENA (quem + pose + objeto-conceito) e o template embrulha estilo+fundo+enquadramento+ref de traço. 'retrato-sapiens-v1' = retrato editorial cartoon de um personagem no grid verde Sapiens (mesma 'mão' dos artigos); sem ref própria, injeta a Helen como âncora de traço (passar referenceImageUrls troca quem aparece). Mutuamente exclusivo com brandSlug. Sub-action 'models' (sem custo, sem login): lista o catálogo vivo (modelos ativos + preço atual com override admin + maxResolution + se aceita referência) pra descobrir modelo/preço em vez de chutar. NOTA: generate é SÍNCRONA e cobra ao concluir; modelo pesado (Pro, gpt-image-2-high, Grok quality, 2K/4K) pode estourar o teto de ~120s do cliente e voltar 'Timeout' MESMO tendo gerado e cobrado, então na dúvida cheque sapiens_gallery action=list antes de repetir (evita cobrança dupla).",
|
|
45
45
|
schema: imageSchema,
|
|
46
46
|
handler: image,
|
|
47
47
|
},
|
|
@@ -71,7 +71,7 @@ const TOOLS = {
|
|
|
71
71
|
handler: article,
|
|
72
72
|
},
|
|
73
73
|
sapiens_write: {
|
|
74
|
-
description: "Artigos self-serve do PRÓPRIO usuário (qualquer conta logada, não só admin) — espaço pessoal, aparece em /u/<username>, NÃO é o blog editorial. Sub-actions: generate (gera 1 artigo na voz Sapiens a partir de brief livre, ou reescrevendo um artigo publicado/texto teu; custa 400 Sinapses, reembolsa se falhar; salva como rascunho. Capa: por padrão gera uma capa-cortesia grátis; se você JÁ tem a imagem (gerou via sapiens_image, ou o artigo é sobre ela), passe coverImageId (id da tua galeria) ou coverImageUrl (host Sapiens) pra ELA virar a capa em vez da cortesia), list (teus artigos), get (1 artigo teu por id, corpo completo), update (edita title/content/excerpt/tldr), publish (publish=true publica no teu perfil, false volta pra rascunho). Identidade vem do sessionToken; cobra as Sinapses do dono do token. Pra blog editorial curado (owner-only) use sapiens_article.",
|
|
74
|
+
description: "Artigos self-serve do PRÓPRIO usuário (qualquer conta logada, não só admin) — espaço pessoal, aparece em /u/<username>, NÃO é o blog editorial. Sub-actions: generate (gera 1 artigo na voz Sapiens a partir de brief livre, ou reescrevendo um artigo publicado/texto teu; custa 400 Sinapses, reembolsa se falhar; salva como rascunho. Capa: por padrão gera uma capa-cortesia grátis; se você JÁ tem a imagem (gerou via sapiens_image, ou o artigo é sobre ela), passe coverImageId (id da tua galeria) ou coverImageUrl (host Sapiens) pra ELA virar a capa em vez da cortesia), list (teus artigos), get (1 artigo teu por id, corpo completo), update (edita title/content/excerpt/tldr), publish (publish=true publica no teu perfil, false volta pra rascunho). Identidade vem do sessionToken; cobra as Sinapses do dono do token. Pra blog editorial curado (owner-only) use sapiens_article. NOTA (generate): é SÍNCRONA (texto + capa) e pode passar do teto de ~120s do cliente, voltando 'Timeout' MESMO tendo gerado e cobrado 400 (o artigo fica salvo como rascunho). Como não tem idempotência, repetir às cegas gera um 2º rascunho e cobra 400 de novo: cheque sapiens_write action=list antes de repetir.",
|
|
75
75
|
schema: writeSchema,
|
|
76
76
|
handler: write,
|
|
77
77
|
},
|
|
@@ -106,12 +106,12 @@ const TOOLS = {
|
|
|
106
106
|
handler: musicator,
|
|
107
107
|
},
|
|
108
108
|
sapiens_shorts: {
|
|
109
|
-
description: "Sapiens Shorts — render vertical 9:16 via VEO com brief structured (v1.5, admin-only). Sub-action: render. Args: imageId (persona pré-existente em generatedImages, descubra via sapiens_gallery), styleId ('ugc'/'unboxing'/'app-demo'/'reflexao'), brief (product+hook+shots+vibe), references opcionais.
|
|
109
|
+
description: "Sapiens Shorts — render vertical 9:16 via VEO com brief structured (v1.5, admin-only). Sub-action: render. Args: imageId (persona pré-existente em generatedImages, descubra via sapiens_gallery), styleId ('ugc'/'unboxing'/'app-demo'/'reflexao'), brief (product+hook+shots+vibe), references opcionais. render é ASSÍNCRONO: volta na hora com {imageId, status:'rendering', url:null}, e você acompanha com sapiens_video action=status imageId=<id> até status='completed' (traz a url VEO, expiração curta, baixe logo) ou 'error'. Pré-requisito: o imageId precisa ter row em generatedImages do user da sessão e cost definido. Pra criar row, use a UI primeiro (v1.6 vai cobrir requestGeneration via MCP).",
|
|
110
110
|
schema: shortsSchema,
|
|
111
111
|
handler: shorts,
|
|
112
112
|
},
|
|
113
113
|
sapiens_video: {
|
|
114
|
-
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), '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. 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.",
|
|
114
|
+
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), '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. 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. 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. 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).",
|
|
115
115
|
schema: videoSchema,
|
|
116
116
|
handler: video,
|
|
117
117
|
},
|
|
@@ -207,7 +207,7 @@ Música (sapiens_musicator) é fluxo de 4 passos, EM ORDEM:
|
|
|
207
207
|
|
|
208
208
|
Vídeo (sapiens_video) action=create EXIGE 'model': sapiens-video-seedance | kling | wan | kling-motion | lite | fast | quality | omni. Sem model, falha de cara. O 'omni' (Gemini Omni) gera clipe de 10s 720p com áudio nativo a partir de TEXTO (não aceita imagem/vídeo do user, ignora duração/resolução) e EDITA os próprios vídeos: passe editOfImageId com o imageId de um vídeo Omni já gerado e o prompt vira instrução de edição sobre a MESMA cena (troca item/personagem, preserva câmera e ambiente; cada edição debita como geração nova). É o caminho pra variações com continuidade: gera a base uma vez, edita N vezes. Vídeo é o mais caro: confirme com o usuário antes. action=shadows (ADMIN, 200 Sinapses/segundo, refund na falha): passa videoUrl (URL pública) + title (+ durationSec se souber, pra cobrar proporcional; sem ela, flat ~2000) e o servidor extrai a SOMBRA (mapa de profundidade) do vídeo e guarda no Acervo (Corpo) como deepshadow reutilizável (driving pro Shot Mimic/Kling Motion). Vitrine dos demos (sem custo): sapiens_video action=demos lista seus demo films com slug; action=showcase (slug + showcase=true/false + showcaseTag + showcaseOrder) cura o mini-cinema da /conectar-claude. FILMES DA CASA (Estúdio de Vídeo, tela /experimentos/films): são OUTRA coisa, três kinds na tabela videoSpecs: demo (UI clonada + câmera), aula-tour (telas reais + narração) e essay (fita-ensaio abstrata: partícula/tinta vira símbolo, com a logo explodindo no fim; narração da casa OPCIONAL, sai em 16:9 ou 9:16 vertical, e o filme final é limpo, sem rótulos de produção). Eles NÃO são gerados por este MCP: o user monta o spec na tela e um agente local (Claude Code, skill /film) produz o mp4 no repo da casa. Se o user pedir 'fita-ensaio' ou 'demo film' aqui, aponte pra tela e pro agente local.
|
|
209
209
|
|
|
210
|
-
Imagem (sapiens_image) action=generate: prompt + model + aspectRatio. Referência via referenceImageUrls (galeria/Acervo/personagens) e/ou sourceImageIds. templateSlug aplica um super-prompt travado da casa.
|
|
210
|
+
Imagem (sapiens_image) action=generate: prompt + model + aspectRatio. Referência via referenceImageUrls (galeria/Acervo/personagens) e/ou sourceImageIds. templateSlug aplica um super-prompt travado da casa. PROMPT na regra da casa: full-bleed, sujeito oversized (70%+ do frame), sem "tarot card"/"intimate scale"/moldura/margem. action=models (sem custo, sem login) lista os modelos ativos com o preço atual: consulte quando não tiver certeza do modelo ou do custo.
|
|
211
211
|
|
|
212
212
|
SEU STUDIO vs geração BASE (não confunda, é o ponto): o usuário tem UM "Meu Studio", único, que o servidor resolve pela SESSÃO. Você NUNCA passa id de studio: é sempre o studio dele. É a identidade configurada dele: marca + personagem-operador + por ferramenta os presets e a "vibe" (o estilo afinado).
|
|
213
213
|
- Criar SEGUINDO o studio (na cara dele): sapiens_image com useStudio=true. O servidor acha o studio e aplica marca + personagem + vibe + presets sozinho (o que você passar explícito vence). O retorno traz studioApplied=true. Use quando ele diz "no meu studio", "na minha marca", "do meu jeito", "como sempre".
|
package/dist/tools/image.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { httpUrl } from "../schema.js";
|
|
3
|
-
import { convexAction, getSessionToken } from "../convexClient.js";
|
|
3
|
+
import { convexAction, convexQuery, getSessionToken } from "../convexClient.js";
|
|
4
4
|
// IDs canônicos do catálogo (apps/sapiens/convex/shared/imageModels.ts).
|
|
5
5
|
// IDs fora dessa lista caem no fallback e o pricing vira 999. Sempre usar os
|
|
6
6
|
// IDs canônicos.
|
|
@@ -29,8 +29,11 @@ const MODELS = [
|
|
|
29
29
|
"fal-krea2-realism-v2", // Krea-2 + LoRA realismo alt (RudySen), pro A/B · 600 · txt2img
|
|
30
30
|
];
|
|
31
31
|
export const imageSchema = z.object({
|
|
32
|
-
action: z.enum(["generate", "request_generation", "compose"]),
|
|
33
|
-
prompt: z
|
|
32
|
+
action: z.enum(["generate", "request_generation", "compose", "models"]),
|
|
33
|
+
prompt: z
|
|
34
|
+
.string()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Prompt da imagem (obrigatório em generate/request_generation). Full-bleed, sujeito oversized."),
|
|
34
37
|
model: z
|
|
35
38
|
.enum(MODELS)
|
|
36
39
|
.optional()
|
|
@@ -42,7 +45,7 @@ export const imageSchema = z.object({
|
|
|
42
45
|
size: z
|
|
43
46
|
.enum(["1K", "2K", "4K"])
|
|
44
47
|
.optional()
|
|
45
|
-
.describe("Default '1K'.
|
|
48
|
+
.describe("Default '1K'. Adder de resolução só nos modelos com hasResolutionAdder: nano-banana-max e nano-banana-2 aceitam 2K (+100) e 4K (+300); grok-2-image e grok-2-image-quality aceitam só 2K (+100), sem 4K. Nos demais modelos o size é ignorado (fica em 1K)."),
|
|
46
49
|
styleId: z
|
|
47
50
|
.string()
|
|
48
51
|
.optional()
|
|
@@ -108,6 +111,32 @@ export const imageSchema = z.object({
|
|
|
108
111
|
.describe("Pra action=compose: instrução em EN pro Gemini. Ex: 'Compose a vertical 9:16 photo: persona holding a smartphone facing the camera, the phone screen displaying the provided second image (clearly visible, sharp). Mobile photography aesthetic.'"),
|
|
109
112
|
});
|
|
110
113
|
export async function image(args) {
|
|
114
|
+
// models: catálogo VIVO dos modelos de imagem (ativos + preço atual com
|
|
115
|
+
// override admin do systemConfig). READ-ONLY, sem custo e sem login — resolve o
|
|
116
|
+
// drift da lista hardcoded: o operador descobre modelo/preço/capacidade em vez
|
|
117
|
+
// de confiar no enum congelado. Antes de exigir sessão de propósito.
|
|
118
|
+
if (args.action === "models") {
|
|
119
|
+
const all = await convexQuery("imageModels:listWithOverrides", {});
|
|
120
|
+
const models = (all ?? [])
|
|
121
|
+
.filter((m) => m?.isActive)
|
|
122
|
+
.sort((a, b) => (a.order ?? 99) - (b.order ?? 99))
|
|
123
|
+
.map((m) => ({
|
|
124
|
+
id: m.id,
|
|
125
|
+
label: m.label,
|
|
126
|
+
priceSinapses: m.effectivePriceSinapses,
|
|
127
|
+
maxResolution: m.maxResolution ?? "4K",
|
|
128
|
+
resolutionAdders: m.resolutionAdders,
|
|
129
|
+
supportsReferences: !!m.supportsReferences,
|
|
130
|
+
degen: /^(civitai-|wavespeed-|fal-)/.test(String(m.id)),
|
|
131
|
+
note: m.description ?? null,
|
|
132
|
+
}));
|
|
133
|
+
return {
|
|
134
|
+
count: models.length,
|
|
135
|
+
default: "nano-banana-2",
|
|
136
|
+
models,
|
|
137
|
+
note: "priceSinapses é o base (1K); 2K/4K somam resolutionAdders quando o modelo tem teto pra isso. degen=+18 (gate na galeria). O preço já inclui override admin.",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
111
140
|
const sessionToken = getSessionToken();
|
|
112
141
|
// v1.8: compose tem args próprios, validação separada
|
|
113
142
|
if (args.action === "compose") {
|
package/dist/tools/meta.js
CHANGED
|
@@ -116,7 +116,7 @@ const FORMAT_GUIDE = {
|
|
|
116
116
|
},
|
|
117
117
|
},
|
|
118
118
|
};
|
|
119
|
-
// Curadoria do action=start: a PORTA DE ENTRADA, não
|
|
119
|
+
// Curadoria do action=start: a PORTA DE ENTRADA, não as 29 tools (despejar tudo
|
|
120
120
|
// afoga cliente fraco). 6 primeiros poderes, cada um com 1 frase pronta pra
|
|
121
121
|
// colar. Voz da casa, espelhando a vitrine /conectar-claude (mantido à mão aqui
|
|
122
122
|
// porque o MCP é pacote separado e não importa o examples.ts do app Next).
|
|
@@ -165,7 +165,17 @@ export async function meta(args) {
|
|
|
165
165
|
// ponto). Sem sessão, ensina a conectar; com sessão, personaliza com
|
|
166
166
|
// nome/tier/saldo e curadoria de primeiros poderes + um "comece por aqui".
|
|
167
167
|
if (args.action === "start") {
|
|
168
|
-
|
|
168
|
+
// start é a porta de entrada e NÃO exige login (esse é o ponto). Mas
|
|
169
|
+
// getSessionToken() LANÇA quando não há sessão (nunca retorna vazio), então
|
|
170
|
+
// sem este try/catch o primeiro contato — justo o cenário que o start existe
|
|
171
|
+
// pra resolver — estourava isError em vez de devolver o onboarding curado.
|
|
172
|
+
let token = null;
|
|
173
|
+
try {
|
|
174
|
+
token = getSessionToken();
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
token = null;
|
|
178
|
+
}
|
|
169
179
|
if (!token) {
|
|
170
180
|
return {
|
|
171
181
|
connected: false,
|
package/dist/tools/musicator.js
CHANGED
|
@@ -73,6 +73,15 @@ export const musicatorSchema = z.object({
|
|
|
73
73
|
.describe("Pra action=render: seed pra reprodutibilidade do synth."),
|
|
74
74
|
});
|
|
75
75
|
export async function musicator(args) {
|
|
76
|
+
// list_public é o Acervo público de músicas da Comunidade (sem custo, sem
|
|
77
|
+
// login): resolve ANTES de exigir sessão. Sem isto, getSessionToken() lança
|
|
78
|
+
// pra quem não está logado e mata o caminho público (mesmo bug do meta.start).
|
|
79
|
+
if (args.action === "list_public") {
|
|
80
|
+
return await convexQuery("musicator:listPublicTracks", {
|
|
81
|
+
page: args.page,
|
|
82
|
+
limit: args.limit,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
76
85
|
const sessionToken = getSessionToken();
|
|
77
86
|
if (args.action === "create") {
|
|
78
87
|
if (!args.title || !args.context) {
|
|
@@ -143,12 +152,4 @@ export async function musicator(args) {
|
|
|
143
152
|
toForum: args.toForum,
|
|
144
153
|
});
|
|
145
154
|
}
|
|
146
|
-
if (args.action === "list_public") {
|
|
147
|
-
// Acervo público de músicas da Comunidade. Query pública (sem auth), igual
|
|
148
|
-
// ao resto do Acervo (Textos/Personagens).
|
|
149
|
-
return await convexQuery("musicator:listPublicTracks", {
|
|
150
|
-
page: args.page,
|
|
151
|
-
limit: args.limit,
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
155
|
}
|
package/dist/tools/shorts.js
CHANGED
|
@@ -17,8 +17,10 @@ import { convexAction, getSessionToken } from "../convexClient.js";
|
|
|
17
17
|
* - app-demo: persona + tela
|
|
18
18
|
* - reflexao: atmosfera mais lenta, contemplativa
|
|
19
19
|
*
|
|
20
|
-
* Retorna `{ success:
|
|
21
|
-
*
|
|
20
|
+
* Retorna `{ success:true, imageId, status:'rendering', url:null }` (ASSÍNCRONO):
|
|
21
|
+
* o render VEO roda fora da chamada. Acompanhe com sapiens_video action=status
|
|
22
|
+
* imageId=<id> até status='completed' (traz a url VEO, expiração curta, baixe
|
|
23
|
+
* logo) ou 'error'/'blocked'.
|
|
22
24
|
*/
|
|
23
25
|
export const shortsSchema = z.object({
|
|
24
26
|
action: z.enum(["render"]),
|
package/dist/tools/studios.js
CHANGED
|
@@ -148,7 +148,7 @@ const STUDIOS = {
|
|
|
148
148
|
},
|
|
149
149
|
repertorio: {
|
|
150
150
|
name: "Repertório",
|
|
151
|
-
description: "Catálogo pessoal de filme/série/anime/jogo. Importa
|
|
151
|
+
description: "Catálogo pessoal de filme/série/anime/jogo/livro/música. Importa via OMDb/IGDB/AniList/Google Books/iTunes. Pode virar pop-articles (lente cultural).",
|
|
152
152
|
url: `${APP}/u/<username>/repertorio`,
|
|
153
153
|
status: "stable",
|
|
154
154
|
tags: ["acervo", "filme", "anime", "jogo", "pop"],
|
package/dist/tools/video.js
CHANGED
|
@@ -54,7 +54,7 @@ const VIDEO_MODELS = [
|
|
|
54
54
|
"sapiens-video-omni",
|
|
55
55
|
];
|
|
56
56
|
export const videoSchema = z.object({
|
|
57
|
-
action: z.enum(["create", "generate", "demos", "showcase", "shadows", "shadows-list"]),
|
|
57
|
+
action: z.enum(["create", "generate", "status", "models", "demos", "showcase", "shadows", "shadows-list"]),
|
|
58
58
|
// --- action=shadows (deepshadows: extrai o mapa de profundidade de um vídeo) ---
|
|
59
59
|
videoUrl: httpUrl()
|
|
60
60
|
.optional()
|
|
@@ -120,8 +120,8 @@ export const videoSchema = z.object({
|
|
|
120
120
|
imageId: z
|
|
121
121
|
.string()
|
|
122
122
|
.optional()
|
|
123
|
-
.describe("action=generate: generatedImages:_id
|
|
124
|
-
"Use sapiens_gallery action=list pra descobrir."),
|
|
123
|
+
.describe("action=generate ou action=status: generatedImages:_id do vídeo. O create devolve o imageId; " +
|
|
124
|
+
"ou um vídeo já criado no site (o row define modelo + custo). Use sapiens_gallery action=list pra descobrir."),
|
|
125
125
|
// --- comum ---
|
|
126
126
|
prompt: z
|
|
127
127
|
.string()
|
|
@@ -161,6 +161,33 @@ export const videoSchema = z.object({
|
|
|
161
161
|
.describe("Frame FINAL: url pública de galeria/Acervo/personagem. Vira reference role 'end' (suporte varia por modelo)."),
|
|
162
162
|
});
|
|
163
163
|
export async function video(args) {
|
|
164
|
+
// models: catálogo VIVO dos modelos de vídeo (ativos + preço-piso/config +
|
|
165
|
+
// override admin + disponibilidade). Público, sem custo e sem login — antes de
|
|
166
|
+
// exigir sessão. Espelha sapiens_image action=models.
|
|
167
|
+
if (args.action === "models") {
|
|
168
|
+
const all = await convexQuery("videoModels:listWithOverrides", {});
|
|
169
|
+
const models = (all ?? [])
|
|
170
|
+
.filter((m) => m?.isActive)
|
|
171
|
+
.map((m) => ({
|
|
172
|
+
id: m.id,
|
|
173
|
+
engine: m.engine,
|
|
174
|
+
label: m.label,
|
|
175
|
+
basePriceSinapses: m.basePriceSinapses,
|
|
176
|
+
modes: m.modes,
|
|
177
|
+
durationsSec: m.durationsSec,
|
|
178
|
+
resolutions: m.resolutions,
|
|
179
|
+
hasAudio: m.hasAudio,
|
|
180
|
+
available: m.available,
|
|
181
|
+
comingSoon: m.comingSoon,
|
|
182
|
+
note: m.description,
|
|
183
|
+
}));
|
|
184
|
+
return {
|
|
185
|
+
count: models.length,
|
|
186
|
+
default: "sapiens-video-seedance",
|
|
187
|
+
models,
|
|
188
|
+
note: "basePriceSinapses é o PISO (config mais barata, já com override admin); o preço real escala por duração x resolução [x áudio]. available=false = 'em breve' (depende de env, ex: Omni). O 'sapiens-cena-visual' (Hyperframes) não aparece: é render local, fora deste MCP.",
|
|
189
|
+
};
|
|
190
|
+
}
|
|
164
191
|
const sessionToken = getSessionToken();
|
|
165
192
|
if (args.action === "demos") {
|
|
166
193
|
return await convexQuery("videoSpecs:mcpListMyDemoFilms", { sessionToken });
|
|
@@ -180,6 +207,15 @@ export async function video(args) {
|
|
|
180
207
|
showcaseOrder: args.showcaseOrder,
|
|
181
208
|
});
|
|
182
209
|
}
|
|
210
|
+
if (args.action === "status") {
|
|
211
|
+
if (!args.imageId) {
|
|
212
|
+
throw new Error("action=status exige imageId (o que create/generate devolveu).");
|
|
213
|
+
}
|
|
214
|
+
return await convexQuery("mcpExtras:mcpVideoStatus", {
|
|
215
|
+
sessionToken,
|
|
216
|
+
imageId: args.imageId,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
183
219
|
if (args.action === "create") {
|
|
184
220
|
if (!args.model) {
|
|
185
221
|
throw new Error("action=create exige model (ex: sapiens-video-seedance, sapiens-video-kling, sapiens-video-wan, sapiens-video-kling-motion).");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.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": {
|