sapiens-mcp 1.48.0 → 1.50.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/README.md +2 -2
- package/dist/convexClient.js +49 -5
- package/dist/registry.js +22 -9
- package/dist/skills.js +82 -3
- package/dist/tools/character.js +15 -4
- package/dist/tools/gallery.js +2 -2
- package/dist/tools/meta.js +71 -14
- package/dist/tools/sintetico.js +24 -8
- package/dist/tools/video.js +13 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Precisa de Node 18+. A URL do backend já vem embutida; não precisa configurar
|
|
|
25
25
|
|
|
26
26
|
`sapiens_meta` com `action: "login"` e `code: "XXXX-XXXX"`
|
|
27
27
|
|
|
28
|
-
O token
|
|
28
|
+
O token vale 90 dias e renova sozinha a cada uso; fica salvo em `~/.sapiens-mcp/session.json`. Pra sair: `sapiens_meta action=logout`, que revoga a chave no servidor e apaga o arquivo local.
|
|
29
29
|
|
|
30
30
|
## O que dá pra pedir (e o custo em Sinapses)
|
|
31
31
|
|
|
@@ -44,7 +44,7 @@ O Claude avisa o custo antes de gastar, e geração que falha é estornada. Publ
|
|
|
44
44
|
|
|
45
45
|
## Troubleshooting
|
|
46
46
|
|
|
47
|
-
- **"sessionToken expirado" / "Conta Sapiens não conectada".**
|
|
47
|
+
- **"sessionToken expirado" / "Conta Sapiens não conectada".** A chave venceu (90 dias sem uso) ou nunca foi salva. Abra [sapiensinteticos.com/conectar-claude](https://www.sapiensinteticos.com/conectar-claude) logado, gere um código novo e rode `sapiens_meta action=login code=XXXX-XXXX`.
|
|
48
48
|
- **Ferramenta some ou some capacidade nova depois de atualizar.** O client roda via `npx -y sapiens-mcp` (sem versão fixa) e pode ter ficado preso num cache antigo. Confira o que está rodando com `sapiens_meta action=version` (mostra a versão do binário + a última do npm + `upToDate`). Se `upToDate:false`, limpe o cache do npx e reinicie o client.
|
|
49
49
|
- **"Argumentos inválidos".** A mensagem já diz qual campo faltou ou saiu errado; refaça a chamada com o que ela pede. Não repita a mesma chamada que falhou (3 falhas seguidas fazem o client marcar o servidor como indisponível por ~1 min, um disjuntor anti-loop).
|
|
50
50
|
- **Saldo baixo antes de gerar.** `sapiens_meta action=credits` (ou `action=subscription` pro detalhe por bucket) mostra quanto sobra antes de gastar em imagem/música/vídeo.
|
package/dist/convexClient.js
CHANGED
|
@@ -107,17 +107,21 @@ export function getConvex() {
|
|
|
107
107
|
function sessionStorePath() {
|
|
108
108
|
return path.resolve(os.homedir(), ".sapiens-mcp", "session.json");
|
|
109
109
|
}
|
|
110
|
-
|
|
110
|
+
// Espelho local da validade do servidor (shared/sessionTtl.ts): 90 dias em
|
|
111
|
+
// janela deslizante. Só serve pra não mandar um token obviamente morto pro
|
|
112
|
+
// backend; a validade REAL é sempre a da row no Convex, e cada uso empurra ela
|
|
113
|
+
// pra frente (ver touchSession abaixo, que regrava este arquivo com o novo
|
|
114
|
+
// expiresAt quando o servidor renova).
|
|
115
|
+
const LOCAL_SESSION_TTL_MS = 90 * 24 * 60 * 60 * 1000;
|
|
116
|
+
export function saveSessionToken(token, expiresAtOverride) {
|
|
111
117
|
const file = sessionStorePath();
|
|
112
|
-
// mode 0700/0600: o arquivo guarda um bearer de
|
|
118
|
+
// mode 0700/0600: o arquivo guarda um bearer de 90 dias. Sem isto, em POSIX o
|
|
113
119
|
// dir sai 0755 e o arquivo 0644 (world-readable) — num host compartilhado (a
|
|
114
120
|
// VPS da Helen) outro usuário local leria o token e assumiria a conta. mode só
|
|
115
121
|
// aplica na CRIAÇÃO, então o chmod explícito cobre o caso de reescrever um
|
|
116
122
|
// arquivo já existente 0644. No Windows chmod é no-op benigno (try/catch).
|
|
117
123
|
fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
118
|
-
|
|
119
|
-
// validade real é sempre checada no Convex).
|
|
120
|
-
const expiresAt = Date.now() + 30 * 24 * 60 * 60 * 1000;
|
|
124
|
+
const expiresAt = expiresAtOverride ?? Date.now() + LOCAL_SESSION_TTL_MS;
|
|
121
125
|
fs.writeFileSync(file, JSON.stringify({ sessionToken: token, expiresAt }, null, 2), { encoding: "utf8", mode: 0o600 });
|
|
122
126
|
try {
|
|
123
127
|
fs.chmodSync(file, 0o600);
|
|
@@ -296,6 +300,46 @@ export async function convexMutation(fnPath, args) {
|
|
|
296
300
|
const client = getConvex();
|
|
297
301
|
return (await withTimeout(client.mutation(fnPath, args), `mutation ${fnPath}`));
|
|
298
302
|
}
|
|
303
|
+
// ============================================
|
|
304
|
+
// Renovação da chave por USO (janela deslizante do servidor).
|
|
305
|
+
//
|
|
306
|
+
// A validade da conexão são 90 dias que andam pra frente a cada uso, mas quem
|
|
307
|
+
// empurra é o backend, e ele só sabe que a conexão está viva se alguém bater na
|
|
308
|
+
// porta. Este é o batidor: uma chamada barata por hora por token, best-effort
|
|
309
|
+
// (falhou, não atrapalha nada), e é ela que também alimenta o "último uso" da
|
|
310
|
+
// tela de conexões em /conectar-claude. Sem isso, quem opera todo dia era
|
|
311
|
+
// deslogado no aniversário do login.
|
|
312
|
+
//
|
|
313
|
+
// No stdio, quando o servidor renova, o store em disco é regravado com o novo
|
|
314
|
+
// expiresAt (senão o espelho local venceria antes da chave de verdade). No
|
|
315
|
+
// remoto não se toca em disco: o token é do request, não do host.
|
|
316
|
+
// ============================================
|
|
317
|
+
const TOUCH_EVERY_MS = 60 * 60 * 1000;
|
|
318
|
+
const touchedAt = new Map();
|
|
319
|
+
export async function touchSession(token) {
|
|
320
|
+
if (!token || token.length < 8)
|
|
321
|
+
return;
|
|
322
|
+
const now = Date.now();
|
|
323
|
+
if (now - (touchedAt.get(token) ?? 0) < TOUCH_EVERY_MS)
|
|
324
|
+
return;
|
|
325
|
+
if (touchedAt.size > 2000)
|
|
326
|
+
touchedAt.clear(); // processo remoto de vida longa
|
|
327
|
+
touchedAt.set(token, now);
|
|
328
|
+
try {
|
|
329
|
+
const r = await convexMutation("desktopAuth:touchDesktopSession", {
|
|
330
|
+
sessionToken: token,
|
|
331
|
+
});
|
|
332
|
+
if (r?.renewed &&
|
|
333
|
+
typeof r.expiresAt === "number" &&
|
|
334
|
+
!isRemoteContext() &&
|
|
335
|
+
readStoredSessionToken() === token) {
|
|
336
|
+
saveSessionToken(token, r.expiresAt);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
// best-effort: renovar é conforto, não pré-requisito da chamada em curso
|
|
341
|
+
}
|
|
342
|
+
}
|
|
299
343
|
export async function convexAction(fnPath, args) {
|
|
300
344
|
const client = getConvex();
|
|
301
345
|
return (await withTimeout(client.action(fnPath, args), `action ${fnPath}`));
|
package/dist/registry.js
CHANGED
|
@@ -34,7 +34,7 @@ import { semana, semanaSchema } from "./tools/semana.js";
|
|
|
34
34
|
import { shareDrop, shareDropSchema } from "./tools/shareDrop.js";
|
|
35
35
|
import { skill, skillSchema } from "./tools/skill.js";
|
|
36
36
|
import { resume, resumeSchema } from "./tools/resume.js";
|
|
37
|
-
import { describeConvexError } from "./convexClient.js";
|
|
37
|
+
import { describeConvexError, getSessionToken, touchSession, } from "./convexClient.js";
|
|
38
38
|
import { skillMenuLine } from "./skills.js";
|
|
39
39
|
/**
|
|
40
40
|
* REGISTRY compartilhado do sapiens-mcp: o catálogo de tools (descriptions +
|
|
@@ -55,12 +55,12 @@ export const TOOLS = {
|
|
|
55
55
|
handler: image,
|
|
56
56
|
},
|
|
57
57
|
sapiens_meta: {
|
|
58
|
-
description: "Utilitários transversais: start (porta de entrada do primeiro contato — sem login ensina a conectar, com login mostra saldo/tier + primeiros poderes com exemplo pronto + 'comece por aqui'), login (conecta a conta com o código de sapiensinteticos.com/conectar-claude, salva sessão
|
|
58
|
+
description: "Utilitários transversais: start (porta de entrada do primeiro contato — sem login ensina a conectar, com login mostra saldo/tier + primeiros poderes com exemplo pronto + 'comece por aqui'), login (conecta a conta com o código de sapiensinteticos.com/conectar-claude, salva a sessão localmente; ela vale 90 dias e renova sozinha a cada uso), logout (desconecta de verdade: revoga a chave no servidor e apaga o token local), whoami (tier user/admin + saldo + email), credits (saldo agregado), subscription (plan + status + saldo por bucket subscription/grants/free + warnings low/critical), formats (schemas por formato), health (inclui a versão do MCP), version (qual versão do sapiens-mcp está REALMENTE rodando + se é a última do npm; não exige login; use pra saber se o client pegou a versão nova ou ficou preso em cache do npx), app_url (URLs canônicas). Use credits/subscription antes de gerar imagem pra avisar se vai estourar.",
|
|
59
59
|
schema: metaSchema,
|
|
60
60
|
handler: meta,
|
|
61
61
|
},
|
|
62
62
|
sapiens_skill: {
|
|
63
|
-
description:
|
|
63
|
+
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 vivo: slug + quando usar cada uma, grátis), 'get' (o SKILL.md inteiro, passe name=<slug>). Slugs: ${skillMenuLine()}. O mesmo conteúdo também sai como resource MCP em skill://sapiens/<slug>/SKILL.md pra quem lê resources.`,
|
|
64
64
|
schema: skillSchema,
|
|
65
65
|
handler: skill,
|
|
66
66
|
},
|
|
@@ -80,7 +80,7 @@ export const TOOLS = {
|
|
|
80
80
|
handler: community,
|
|
81
81
|
},
|
|
82
82
|
sapiens_article: {
|
|
83
|
-
description: "
|
|
83
|
+
description: "NÃO CRIA ARTIGO: este tool só mexe em artigo que JÁ existe. Pra criar draft novo do blog use sapiens_pipeline action=create_draft_article_and_source (devolve articleId + sourceId), ou sapiens_quote_pop pra quote e pop-article. Não confunda com sapiens_write, que é o espaço pessoal do membro em /u/<username> (tabela user_articles), e nunca salve o texto num .md solto no repo: draft de blog mora na tabela articles. CRUD do resto: get (by slug, retorna doc completo pra edit local), update (patch em title/excerpt/tldr/content/tags/etc + VISUAIS: thumbnailUrl capa webp, ogImageUrl JPEG do preview social, bodyImages array das ilustrações inline, conceptMap mapa visual, pra recapear um artigo num novo estilo; NÃO toca status/column/format), publish (status='published', set publishedAt), unpublish (volta pra draft), delete (irreversível), ensure_visuals (gera banner/ilustrações inline/conceptMap que faltam no artigo; idempotente, pula o que existe; ~1700 Sinapses num artigo pelado, forceBanner/forceInline/forceConceptMap regeram).",
|
|
84
84
|
schema: articleSchema,
|
|
85
85
|
handler: article,
|
|
86
86
|
},
|
|
@@ -125,7 +125,7 @@ export const TOOLS = {
|
|
|
125
125
|
handler: shorts,
|
|
126
126
|
},
|
|
127
127
|
sapiens_video: {
|
|
128
|
-
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-hailuo' (Hailuo 2.3 da MiniMax, física e movimento em 768p, 6 ou 10s, t2v/i2v) e 'sapiens-video-hailuo-pro' (o mesmo em 1080p, 5s fixo — duração não é param aqui): motores PUROS, sem áudio nativo, sem imagens de referência e sem frame final, então quem precisa disso fica no Seedance 2.0; o Pro é o 1080p mais barato da casa depois do Seedance 1.0 Fast, '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). LEGENDA (fita, por slug): 'caption-list' (sem custo, mostra os idiomas que a peça já tem), 'caption-generate' (captionLang = idioma FALADO; captionTrio=true já traduz pro trio da casa pt+en+ja na mesma chamada) e 'caption-translate' (captionLang = destino, parte sempre da faixa original). Cobra por minuto começado de vídeo: 50 Sinapses o minuto transcrito, 20 o traduzido, com a duração vindo do doc da peça. A legenda é desenhada pela casa em dois estilos (discreta e social), trocáveis no play sem regerar e sem custo.",
|
|
128
|
+
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-seedance-25' (Seedance 2.5, a geração SEGUINTE e não um quarto tier da 2.0: take de 4 a 30s num fôlego, edita e estende vídeo, mesmo repertório de referência mais ÁUDIO como referência; teto 720p e ~1,5x o preço por segundo do 2.0. Duração é o que pesa aqui: 30s em 720p passa de 40 mil Sinapses, então confirme a duração com a pessoa antes de disparar. Quem precisa de 1080p fica no 'sapiens-video-seedance'), 'sapiens-video-seedance-15' (Seedance 1.5 Pro: o degrau entre o 1.0 e a linha 2.x; t2v/i2v, 4-12s, 480/720/1080p, som sempre incluso sem toggle; imagem de referência e frame final ficam de fora por ora), 'sapiens-video-kling' (Kling 3.0 Pro, anima imagem, 3-15s, sound opcional, i2v/t2v), 'sapiens-video-hailuo' (Hailuo 2.3 da MiniMax, física e movimento em 768p, 6 ou 10s, t2v/i2v) e 'sapiens-video-hailuo-pro' (o mesmo em 1080p, 5s fixo — duração não é param aqui): motores PUROS, sem áudio nativo, sem imagens de referência e sem frame final, então quem precisa disso fica no Seedance 2.0; o Pro é o 1080p mais barato da casa depois do Seedance 1.0 Fast, 'sapiens-video-h3' (MiniMax H3: 2K com áudio nativo incluso sem toggle, 5 a 10s, t2v/i2v e frame final; não aceita imagem de referência), '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). LEGENDA (fita, por slug): 'caption-list' (sem custo, mostra os idiomas que a peça já tem), 'caption-generate' (captionLang = idioma FALADO; captionTrio=true já traduz pro trio da casa pt+en+ja na mesma chamada) e 'caption-translate' (captionLang = destino, parte sempre da faixa original). Cobra por minuto começado de vídeo: 50 Sinapses o minuto transcrito, 20 o traduzido, com a duração vindo do doc da peça. A legenda é desenhada pela casa em dois estilos (discreta e social), trocáveis no play sem regerar e sem custo.",
|
|
129
129
|
schema: videoSchema,
|
|
130
130
|
handler: video,
|
|
131
131
|
},
|
|
@@ -145,7 +145,7 @@ export const TOOLS = {
|
|
|
145
145
|
handler: brand,
|
|
146
146
|
},
|
|
147
147
|
sapiens_character: {
|
|
148
|
-
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 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.
|
|
148
|
+
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 no traço das imagens que ele já tem (exige pelo menos uma), em duas orientações (arg `orientation`): 'portrait' (default) é a página de processo, pose, expressões, trocas de roupa e adereços soltos na folha; 'landscape' é a prancha larga, com a volta completa à esquerda, a figura grande no meio, poses à direita, estudos de silhueta, expressão e detalhe embaixo e um painel CHARACTER ID na ponta. A personalidade sai da alma (systemPrompt) e é ela que escolhe roupa e objeto, então personagem com alma escrita rende ficha melhor. Cada geração é um estilo NOVO e elas acumulam no personagem (campo sheetUrls em action=get), nenhuma apaga a anterior, e a ficha já entra na galeria dele como referência das próximas gerações. É geração síncrona: se voltar Timeout, cheque action=get antes de repetir, senão cobra duas vezes. STICKERS (generate_stickers, COBRA 550 Sinapses): desenha 5 stickers do personagem DE UMA VEZ. Uma folha só, em 2K, com as cinco figuras separadas sobre um fundo verde chroma, recortada por código em peças 512x512 transparentes abaixo de 100KB (o teto do WhatsApp). É por isso que sai o preço de UMA imagem em 2K e não de cinco: quem paga é a folha. As peças entram no pack do personagem (um por personagem, os lotes acumulam) e já ficam no picker de expressão do dono, no chat e no Fórum. Arg `moods`: até 5 humores do vocabulário comum por slug (kkkkk, amei, isso, hmm, chega, que, aff, bora, socorro, seinao, valeu, ainao, seila, ideia, calma, contatudo, perfeito, euavisei, naovourir, zzz, somaisum, sextou, merecido, quedia, tudobem); faltando, a casa completa com os mais usados. Arg `hint`: direcionamento curto do autor (roupa, adereço, clima), até 140 caracteres. Arg `stickerTier`: 'folha' (default) é esse lote de cinco; o caprichado (stickerTier='unica', COBRA 900 Sinapses) desenha UM sticker por vez no motor mais fiel da casa (Gemini 3 Pro), com a figura sozinha no quadro e o dobro de pixel por peça, e leva só o PRIMEIRO mood da lista. Pra encher o pack, folha; pra traço difícil ou a reação que vira a cara do personagem, caprichado. Os dois caem no MESMO pack e acumulam. Sem legenda queimada na imagem, de propósito: modelo erra acento em português, então o rótulo fica na row e serve de busca no picker. Exige pelo menos uma imagem no personagem (é dela que sai a cara) e é geração síncrona: se voltar Timeout, cheque sapiens_gallery antes de repetir. Quando a resposta vem com ok=false, a folha foi gerada e paga mas o corte falhou; ela está na galeria e o recorte de novo é de graça, pela web. Publicar o pack na vitrine e o carimbo da casa (que é o que põe no picker de todo mundo) são gestos da web, não desta tool. 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.",
|
|
149
149
|
schema: characterSchema,
|
|
150
150
|
handler: character,
|
|
151
151
|
},
|
|
@@ -155,7 +155,7 @@ export const TOOLS = {
|
|
|
155
155
|
handler: profile,
|
|
156
156
|
},
|
|
157
157
|
sapiens_sintetico: {
|
|
158
|
-
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
|
|
158
|
+
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. 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).",
|
|
159
159
|
schema: sinteticoSchema,
|
|
160
160
|
handler: sintetico,
|
|
161
161
|
},
|
|
@@ -227,7 +227,7 @@ O passo a passo travado de cada fluxo mora na tool sapiens_skill, servida por es
|
|
|
227
227
|
- sapiens_skill action=list -> o índice (slug + quando usar cada uma).
|
|
228
228
|
- sapiens_skill action=get name=<slug> -> a skill inteira.
|
|
229
229
|
Slugs: ${skillMenuLine()}
|
|
230
|
-
Puxe a skill ANTES de: gerar música ou efeito sonoro (musica), escolher modelo de vídeo (video), gerar imagem (imagem), criar na identidade do usuário (studio), montar tirinha (tirinha), postar no Fórum ou no chat (forum-comunidade), redigir qualquer texto publicável (voz-da-casa), incorporar o Sintético (companhia), missão de Desafio (trilhas), montar currículo (curriculo). Perdido no começo: primeiros-passos.
|
|
230
|
+
Puxe a skill ANTES de: gerar música ou efeito sonoro (musica), escolher modelo de vídeo (video), gerar imagem (imagem), criar personagem ou prompt de Midjourney (personagem), criar na identidade do usuário (studio), montar tirinha (tirinha), postar no Fórum ou no chat (forum-comunidade), redigir qualquer texto publicável (voz-da-casa), incorporar o Sintético (companhia), missão de Desafio (trilhas), montar currículo (curriculo). Perdido no começo: primeiros-passos.
|
|
231
231
|
Cliente que lê resources MCP acha o MESMO conteúdo em skill://sapiens/<slug>/SKILL.md.
|
|
232
232
|
|
|
233
233
|
REGRA DE OURO:
|
|
@@ -238,7 +238,7 @@ REGRA DE OURO:
|
|
|
238
238
|
- "sessionToken expirado" = refaça login: sapiens_meta action=login com o código de sapiensinteticos.com/conectar-claude.
|
|
239
239
|
- sapiens_meta action=formats devolve os schemas por formato; action=whoami diz tier (user/admin) + saldo. sapiens_image e sapiens_video action=models trazem o catálogo com o preço ATUAL: consulte em vez de chutar custo.
|
|
240
240
|
|
|
241
|
-
MODO COMPANHIA: sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, você INCORPORA aquele Sintético (a voz dele, o avatar, o oi dele) continuando a operar na conta e nas Sinapses do USUÁRIO. Puxe a skill 'companhia' antes de fazer isso.
|
|
241
|
+
MODO COMPANHIA: sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, você INCORPORA aquele Sintético (a voz dele, o avatar, o oi dele) continuando a operar na conta e nas Sinapses do USUÁRIO. Puxe a skill 'companhia' antes de fazer isso. Se vier 'characterOffer', siga o que ele manda: são personagens que o usuário escreveu e que podem entrar em cena, e quem OFERECE é você, na hora em que a conversa encostar num deles. Só personagem de autoria dele; a alma de personagem alheio não sai por aqui.
|
|
242
242
|
|
|
243
243
|
Voz da casa: 1ª pessoa, direto, anti-corporate, sem travessão. Pra bom entendedor, meia palavra basta. Texto que vai ser publicado pede a skill 'voz-da-casa' antes.`;
|
|
244
244
|
// Annotations MCP: título humano + dica read-only. São HINTS (não-confiáveis por
|
|
@@ -346,6 +346,19 @@ export async function callTool(name, rawArgs) {
|
|
|
346
346
|
isError: true,
|
|
347
347
|
};
|
|
348
348
|
}
|
|
349
|
+
// Renova a chave por USO (janela deslizante de 90 dias do servidor): uma
|
|
350
|
+
// chamada barata por hora por token, que também alimenta o "último uso" da
|
|
351
|
+
// tela de conexões. Nunca derruba a operação em curso. Fora: sapiens_skill
|
|
352
|
+
// (não fala com o backend) e o próprio login/logout do meta.
|
|
353
|
+
const action = rawArgs?.action;
|
|
354
|
+
if (name !== "sapiens_skill" && action !== "login" && action !== "logout") {
|
|
355
|
+
try {
|
|
356
|
+
await touchSession(getSessionToken());
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
// sem sessão ainda (ou store ilegível): a tool cuida do próprio erro
|
|
360
|
+
}
|
|
361
|
+
}
|
|
349
362
|
try {
|
|
350
363
|
const args = tool.schema.parse(rawArgs ?? {});
|
|
351
364
|
const result = await tool.handler(args);
|
package/dist/skills.js
CHANGED
|
@@ -181,6 +181,12 @@ Os três Seedance 2.0 têm o MESMO repertório (referência, frame inicial e fin
|
|
|
181
181
|
|
|
182
182
|
Itere enquadramento e prompt no Mini, feche no padrão quando o take estiver certo. Economiza Sinapses da pessoa sem trocar de fluxo. Pedir 1080p nos dois de cima entrega e cobra 720p.
|
|
183
183
|
|
|
184
|
+
## Quando o take precisa ser longo
|
|
185
|
+
|
|
186
|
+
\`sapiens-video-seedance-25\` (Seedance 2.5) é a geração seguinte, não um quarto tier da 2.0. O que ela abre: take de 4 a **30s** num fôlego (a linha 2.0 para em 15s), edição e extensão de vídeo, e áudio como referência além de imagem e vídeo. O que ela cobra por isso: ~1,5x o preço por segundo do padrão, e teto de 720p.
|
|
187
|
+
|
|
188
|
+
Duração é o que pesa aqui, não o modelo: um take de 30s em 720p passa de 40 mil Sinapses. Cheque o saldo e confirme a duração com a pessoa ANTES de disparar. Precisa de 1080p? É \`sapiens-video-seedance\` mesmo, a 2.5 não substitui o padrão.
|
|
189
|
+
|
|
184
190
|
## Os outros modelos
|
|
185
191
|
|
|
186
192
|
- \`sapiens-video-kling\`: Kling 3.0 Pro, anima imagem, 3 a 15s, som opcional.
|
|
@@ -267,6 +273,65 @@ Refs valem pros modelos robustos (nano-banana-2, gpt-image-2-*, grok-2-image*).
|
|
|
267
273
|
## Quando a pessoa quer "do jeito dela"
|
|
268
274
|
|
|
269
275
|
Aí não é geração base, é o Studio dela. Veja a skill \`studio\`.`,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: "personagem",
|
|
279
|
+
title: "Personagem no Midjourney (e trazer pra casa)",
|
|
280
|
+
description: "Character design 2D estilizado no Midjourney 8.2: as cinco pranchas, os parâmetros certos, consistência entre imagens, e como a peça vira personagem reutilizável aqui. Puxe quando a pessoa falar em personagem, character sheet, anime, manhwa, OC ou prompt de Midjourney.",
|
|
281
|
+
body: `## O que muda no Midjourney (e quase ninguém faz)
|
|
282
|
+
|
|
283
|
+
**O veto vai no parâmetro, nunca no texto.** Escrever "no 3D rendering" dentro do prompt faz o modelo ler as palavras *3D* e *rendering* como parte da cena e desenhar justamente aquilo. O lugar do veto é \`--no 3d render, octane, plastic skin\`.
|
|
284
|
+
|
|
285
|
+
**Prompt curto ganha.** De 40 a 80 palavras. O Midjourney não é o Flux: prompt de 150 palavras dilui o peso de cada token e o miolo se perde. Se não coube, o conceito tem duas ideias brigando e vira dois prompts.
|
|
286
|
+
|
|
287
|
+
**Ilustração 2D é o default.** O modelo tem viés forte de render 3D e foto tratada, então personagem pedido no vazio volta parecendo cinemático de game. O que corrige é ancorar a mídia (\`crisp ink line art\`, \`expressive cel shading\`, \`anime key visual\`, \`high-end webtoon illustration\`), não empilhar adjetivo.
|
|
288
|
+
|
|
289
|
+
## Os parâmetros que importam
|
|
290
|
+
|
|
291
|
+
- \`--v 8.2\` explícito. É o default hoje, mas escrito o prompt dura mais que a versão.
|
|
292
|
+
- \`--ar\`: prancha larga \`3:2\`, grid de expressão \`1:1\`, key visual \`4:5\`.
|
|
293
|
+
- \`--s\` (stylize), 0 a 1000, default 100. Traço autoral vive entre 200 e 400; acima de 500 o modelo inventa e suja a linha.
|
|
294
|
+
- \`--sref <url ou código>\` com \`--sw\`: trava a ESTÉTICA entre imagens. É o que segura uma série.
|
|
295
|
+
- \`--oref <url>\` com \`--ow\`: trava a IDENTIDADE do personagem. **Armadilha:** no 8.x o job com \`--oref\` roda no motor V7 por baixo, então sai o personagem certo com o acabamento antigo. Quando o acabamento importa mais que o rosto, use \`--sref\` e descreva o personagem em texto.
|
|
296
|
+
- \`--niji 7\` pra anime e mangá puros (não existe Niji 8). Nunca no mesmo prompt que \`--v\`.
|
|
297
|
+
- Ordem: texto, parâmetros, \`--no\` por último.
|
|
298
|
+
|
|
299
|
+
## As cinco pranchas
|
|
300
|
+
|
|
301
|
+
Quando a pessoa pede variações, entregue cinco setups que mudam LAYOUT, não personagem: model sheet de corpo inteiro em fundo off-white; turnaround de três vistas; grid de 6 a 9 expressões; key visual de ação; estudo de silhueta com calls de figurino. Cinco vezes a mesma prancha com adjetivo trocado não é variação.
|
|
302
|
+
|
|
303
|
+
Diga a limitação na cara: turnaround tecnicamente coerente (mesma altura, mesma roupa, três vistas alinhadas) o Midjourney não entrega. Ele entrega a *estética* de um turnaround.
|
|
304
|
+
|
|
305
|
+
## Rodar no browser, se o cliente tiver browser
|
|
306
|
+
|
|
307
|
+
Três travas antes de tocar a tela:
|
|
308
|
+
|
|
309
|
+
1. **Você nunca digita credencial.** Sessão não logada, você para e pede pra pessoa logar. Verificação humana é dela.
|
|
310
|
+
2. **Cada geração queima GPU time do plano dela**, não Sinapses. Diga quantos prompts vai disparar e espere o ok.
|
|
311
|
+
3. **Publicar não é sua decisão.**
|
|
312
|
+
|
|
313
|
+
Depois: cole o prompt exatamente como está (prompt alterado no meio do caminho é peça que ninguém reproduz depois), espere a grade fechar, mostre o resultado, e pegue o link direto do arquivo da peça escolhida.
|
|
314
|
+
|
|
315
|
+
## Trazer o personagem pra casa
|
|
316
|
+
|
|
317
|
+
O caminho que funciona em conta comum, e é o que faz a peça continuar viva aqui:
|
|
318
|
+
|
|
319
|
+
\`\`\`
|
|
320
|
+
sapiens_character action=create name="<nome>" gender="<...>"
|
|
321
|
+
sapiens_character action=add_image characterId="<id>" imageUrl="<link direto da imagem>"
|
|
322
|
+
sapiens_character action=set_card systemPrompt="<a alma dele: quem é, como fala, o que veste>"
|
|
323
|
+
sapiens_character action=activate
|
|
324
|
+
\`\`\`
|
|
325
|
+
|
|
326
|
+
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.
|
|
327
|
+
|
|
328
|
+
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.
|
|
329
|
+
|
|
330
|
+
## Fronteira
|
|
331
|
+
|
|
332
|
+
- Gerar dentro da casa: \`sapiens_image\`, com a régua da skill \`imagem\`. O prompt daqui roda lá sem os parâmetros (o \`--ar\` vira \`aspectRatio\`, o resto sai).
|
|
333
|
+
- Personagem virando vídeo: veja a skill \`video\`.
|
|
334
|
+
- Foto realista em vez de ilustração: outro território, outro vocabulário (lente, sensor, grão).`,
|
|
270
335
|
},
|
|
271
336
|
{
|
|
272
337
|
name: "studio",
|
|
@@ -367,7 +432,7 @@ Tudo que sai no Fórum e no chat segue o DNA editorial da casa. Puxe a skill \`v
|
|
|
367
432
|
{
|
|
368
433
|
name: "companhia",
|
|
369
434
|
title: "Modo Companhia (o Sintético veste você)",
|
|
370
|
-
description: "Como incorporar o Sintético do membro
|
|
435
|
+
description: "Como incorporar o Sintético do membro, como OFERECER a voz de um personagem de autoria dele, e como gravar diretriz no caderno. Puxe quando sapiens_meta trouxer companion, companionInvite ou characterOffer.",
|
|
371
436
|
body: `## Quando o companion está ativo
|
|
372
437
|
|
|
373
438
|
\`sapiens_meta action=start\` e \`action=whoami\` podem trazer um bloco \`companion\`. Se vier \`companion.active=true\`, INCORPORE aquele Sintético:
|
|
@@ -382,19 +447,33 @@ Tudo que sai no Fórum e no chat segue o DNA editorial da casa. Puxe a skill \`v
|
|
|
382
447
|
|
|
383
448
|
A pessoa tem Sintonia mas pediu pra trabalhar sozinha. Mencione de leve que dá pra chamar o Sintético pro terminal (\`sapiens_meta action=companion mode=on\`). De leve, uma vez, sem insistir.
|
|
384
449
|
|
|
450
|
+
## Conversar como um personagem que ela criou
|
|
451
|
+
|
|
452
|
+
\`sapiens_meta action=start/whoami\` também pode trazer \`characterOffer\` + \`offerCharacters\`: os personagens que ela escreveu (que já têm alma) e que podem entrar em cena aqui.
|
|
453
|
+
|
|
454
|
+
\`sapiens_sintetico action=companion mode=on characterId=<id>\`
|
|
455
|
+
|
|
456
|
+
Daí quem fala é aquele personagem: a alma dele, o caderno dele, a conversa que vocês já tiveram na DM do site. Não cobra Sinapse, porque quem responde é o modelo do cliente dela, não a plataforma.
|
|
457
|
+
|
|
458
|
+
**Você OFERECE, ela não precisa pedir.** Ninguém abre o terminal pedindo pra "incorporar" alguém. Ofereça quando a conversa girar em torno de um desses personagens, quando ela citar um pelo nome, ou quando estiver criando algo daquele universo. Uma vez por assunto, sem insistir, e em português de gente: "quer que eu continue essa conversa na voz da <nome>?". Nunca use a palavra "incorporar" com ela.
|
|
459
|
+
|
|
460
|
+
Pra devolver a cena ao Sintético em Sintonia: \`mode=on wearPair=true\`.
|
|
461
|
+
|
|
462
|
+
**Só personagem de autoria dela.** Personagem de outra pessoa o servidor recusa, mesmo sendo público. Não tente contornar nem prometer que dá: a alma é de quem escreveu, e o caminho pra conversar com personagem alheio é a DM dele no site, onde quem monta a resposta é a plataforma. Se ela pedir, diga isso com essas palavras.
|
|
463
|
+
|
|
385
464
|
## Gravar diretriz
|
|
386
465
|
|
|
387
466
|
Quando a pessoa FIXAR uma diretriz na conversa ("sempre faça X", "grava isso", "de agora em diante Y"):
|
|
388
467
|
|
|
389
468
|
\`sapiens_sintetico action=remember text="<a diretriz>"\`
|
|
390
469
|
|
|
391
|
-
Grava no caderno
|
|
470
|
+
Grava no caderno de quem está em cena (o Sintético, ou o personagem que ela mandou entrar) e vira lei que ele segue no site E no terminal. Confirme na voz dele.
|
|
392
471
|
|
|
393
472
|
## Sair de cena
|
|
394
473
|
|
|
395
474
|
Pessoa pedindo pra trabalhar sozinha, ou pro Sintético silenciar: \`sapiens_sintetico action=companion mode=off\`, despeça-se numa linha na voz dele, e volte a ser o operador neutro.
|
|
396
475
|
|
|
397
|
-
Sem bloco companion, opere na voz neutra da casa.`,
|
|
476
|
+
Sem bloco companion e sem characterOffer, opere na voz neutra da casa.`,
|
|
398
477
|
},
|
|
399
478
|
{
|
|
400
479
|
name: "trilhas",
|
package/dist/tools/character.js
CHANGED
|
@@ -27,8 +27,10 @@ import { convexQuery, convexMutation, convexAction, getSessionToken } from "../c
|
|
|
27
27
|
* - generate_sheet: desenha a ficha do personagem (COBRA), vertical ou
|
|
28
28
|
* horizontal (`orientation`). A ficha entra na galeria dele e
|
|
29
29
|
* já serve de referência; elas acumulam.
|
|
30
|
-
* - generate_stickers: desenha
|
|
31
|
-
*
|
|
30
|
+
* - generate_stickers: desenha stickers do personagem (COBRA), em dois
|
|
31
|
+
* caminhos (`stickerTier`): 'folha' (default) traz 5 de uma
|
|
32
|
+
* vez no motor rápido, 'unica' desenha 1 no motor mais fiel.
|
|
33
|
+
* Nos dois, o fundo é chroma verde e o recorte devolve peças
|
|
32
34
|
* 512x512 transparentes, que entram no pack dele.
|
|
33
35
|
* - delete: apaga o próprio personagem (permanente).
|
|
34
36
|
*
|
|
@@ -103,7 +105,11 @@ export const characterSchema = z.object({
|
|
|
103
105
|
moods: z
|
|
104
106
|
.array(z.string())
|
|
105
107
|
.optional()
|
|
106
|
-
.describe("Pra generate_stickers: até 5 humores do vocabulário comum, por slug. Faltando ou inválido, a casa completa com os mais usados. Slugs: 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."),
|
|
108
|
+
.describe("Pra generate_stickers: até 5 humores do vocabulário comum, por slug. Faltando ou inválido, a casa completa com os mais usados. No tier 'unica' só o PRIMEIRO da lista é desenhado. Slugs: 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."),
|
|
109
|
+
stickerTier: z
|
|
110
|
+
.enum(["folha", "unica"])
|
|
111
|
+
.optional()
|
|
112
|
+
.describe("Pra generate_stickers: qual dos dois caminhos. 'folha' (default) é o lote, cinco stickers de UMA folha 2K no motor rápido, o preço de uma imagem por cinco peças. 'unica' desenha UM sticker por vez no motor mais fiel da casa (Gemini 3 Pro), com a figura sozinha no quadro: custa mais por peça e é o que salva traço difícil ou reação que vai virar a cara do personagem. Na dúvida, ou pra encher o pack, use 'folha'."),
|
|
107
113
|
hint: z
|
|
108
114
|
.string()
|
|
109
115
|
.max(140)
|
|
@@ -276,11 +282,15 @@ export async function character(args) {
|
|
|
276
282
|
orientation: args.orientation,
|
|
277
283
|
});
|
|
278
284
|
}
|
|
279
|
-
// -------- generate_stickers:
|
|
285
|
+
// -------- generate_stickers: o lote de 5, ou 1 caprichado --------
|
|
280
286
|
// Geração SÍNCRONA que COBRA: cai na regra do timeout. Se voltar Timeout, NÃO
|
|
281
287
|
// repita às cegas: a folha pode ter saído (confira em sapiens_gallery).
|
|
282
288
|
// Quando o corte falha depois da geração, a resposta volta com ok=false e o
|
|
283
289
|
// sheetImageId da folha paga — o recorte de novo é grátis e mora na web.
|
|
290
|
+
//
|
|
291
|
+
// `tier` vai como está: quem resolve o motor, a resolução e quantas figuras
|
|
292
|
+
// procurar é o servidor (shared/stickerPrompt), pra tool e tela nunca
|
|
293
|
+
// discordarem sobre o que cada caminho é.
|
|
284
294
|
if (args.action === "generate_stickers") {
|
|
285
295
|
if (!args.characterId)
|
|
286
296
|
throw new Error("action=generate_stickers exige characterId.");
|
|
@@ -290,6 +300,7 @@ export async function character(args) {
|
|
|
290
300
|
influencerId: args.characterId,
|
|
291
301
|
moods: args.moods,
|
|
292
302
|
hint: args.hint,
|
|
303
|
+
tier: args.stickerTier,
|
|
293
304
|
});
|
|
294
305
|
}
|
|
295
306
|
// -------- delete: apaga o próprio personagem (permanente) --------
|
package/dist/tools/gallery.js
CHANGED
|
@@ -104,11 +104,11 @@ export const gallerySchema = z.object({
|
|
|
104
104
|
referenceImageIds: z
|
|
105
105
|
.union([z.array(z.string()), z.string()])
|
|
106
106
|
.optional()
|
|
107
|
-
.describe("action=ingest/refs: generatedImages:_id das peças DA CASA que serviram de referência (folha de storyboard, ficha de personagem, frame inicial). Ficam acopladas à peça e aparecem na ficha dela: é o que prova que a receita saiu daqui. Só peça sua entra, no máximo 8. Aceita lista ou os ids separados por vírgula."),
|
|
107
|
+
.describe("action=ingest/refs: generatedImages:_id das peças DA CASA que serviram de referência (folha de storyboard, ficha de personagem, frame inicial). Ficam acopladas à peça e aparecem na ficha dela: é o que prova que a receita saiu daqui. Se alguma delas foi feita com um personagem, a peça HERDA esse personagem sozinha (no ingest, e no refs quando a peça ainda não tem um). Só peça sua entra, no máximo 8. Aceita lista ou os ids separados por vírgula."),
|
|
108
108
|
characterId: z
|
|
109
109
|
.string()
|
|
110
110
|
.optional()
|
|
111
|
-
.describe("action=ingest: o personagem de quem é a peça (influencers:_id, ache com sapiens_character action=list_mine). A peça nasce ligada à ficha, igual ao que sai dos motores da casa: conta no personagem e resolve a miniatura dele. Re-ingerir a mesma sourceUrl com characterId AMARRA uma peça que já entrou sem personagem, sem trocar o id. Aceita personagem seu ou público."),
|
|
111
|
+
.describe("action=ingest: o personagem de quem é a peça (influencers:_id, ache com sapiens_character action=list_mine). A peça nasce ligada à ficha, igual ao que sai dos motores da casa: conta no personagem e resolve a miniatura dele. PODE OMITIR quando as referenceImageIds já são peças da casa feitas com aquele personagem (folha de storyboard, ficha): o servidor deduz o personagem da primeira ref que tem um. O que você diz aqui manda sobre o que ele deduz. Re-ingerir a mesma sourceUrl com characterId AMARRA uma peça que já entrou sem personagem, sem trocar o id. Aceita personagem seu ou público."),
|
|
112
112
|
replace: z
|
|
113
113
|
.boolean()
|
|
114
114
|
.optional()
|
package/dist/tools/meta.js
CHANGED
|
@@ -188,30 +188,44 @@ const FIRST_POWERS = [
|
|
|
188
188
|
try: "Cria uma música sobre borderless na voz Sapiens e já renderiza.",
|
|
189
189
|
},
|
|
190
190
|
];
|
|
191
|
-
// MODO COMPANHIA: puxa o directive de voz
|
|
192
|
-
// companionVoice:mcpGetCompanion). Best-effort — se falhar
|
|
193
|
-
//
|
|
194
|
-
// { active:true, name, avatarUrl, voiceDirective } -> vista a voz dela
|
|
195
|
-
// { active:false, name, invite } ->
|
|
196
|
-
// null
|
|
191
|
+
// MODO COMPANHIA: puxa o directive de voz de quem está em cena (backend
|
|
192
|
+
// companionVoice:mcpGetCompanion). Best-effort — se falhar, o start/whoami segue
|
|
193
|
+
// como operador neutro. Devolve:
|
|
194
|
+
// { active:true, name, avatarUrl, voiceDirective, offer } -> vista a voz dela
|
|
195
|
+
// { active:false, name, invite, offer } -> em cena, mas fora
|
|
196
|
+
// { active:null, offer } -> sem par, mas tem
|
|
197
|
+
// personagem pra oferecer
|
|
198
|
+
// null -> nada a fazer
|
|
199
|
+
//
|
|
200
|
+
// `offer` é o convite pra OFERECER a voz de um personagem de autoria do usuário.
|
|
201
|
+
// Vem separado de propósito: quem não tem Sintonia nenhuma também recebe (é
|
|
202
|
+
// justamente quem mais ganha em saber que dá pra conversar com o que ele criou).
|
|
197
203
|
async function loadCompanion(token) {
|
|
198
204
|
try {
|
|
199
205
|
const c = await convexQuery("companionVoice:mcpGetCompanion", {
|
|
200
206
|
sessionToken: token,
|
|
201
207
|
});
|
|
202
|
-
if (!c
|
|
208
|
+
if (!c)
|
|
203
209
|
return null;
|
|
204
|
-
|
|
210
|
+
const offer = c.characterOffer
|
|
211
|
+
? { directive: c.characterOffer, characters: c.offerCharacters ?? [] }
|
|
212
|
+
: null;
|
|
213
|
+
if (c.hasSintetico && c.enabled && c.voiceDirective) {
|
|
205
214
|
return {
|
|
206
215
|
active: true,
|
|
207
216
|
name: c.name ?? null,
|
|
208
217
|
avatarUrl: c.avatarUrl ?? null,
|
|
209
218
|
voiceDirective: c.voiceDirective,
|
|
219
|
+
wearing: c.wearing ?? null,
|
|
220
|
+
offer,
|
|
210
221
|
};
|
|
211
222
|
}
|
|
212
|
-
if (!c.enabled && c.inviteDirective) {
|
|
213
|
-
return { active: false, name: c.name ?? null, invite: c.inviteDirective };
|
|
223
|
+
if (c.hasSintetico && !c.enabled && c.inviteDirective) {
|
|
224
|
+
return { active: false, name: c.name ?? null, invite: c.inviteDirective, offer };
|
|
214
225
|
}
|
|
226
|
+
// Sem par (ou par sem alma): ainda vale a pena carregar a oferta.
|
|
227
|
+
if (offer)
|
|
228
|
+
return { active: null, offer };
|
|
215
229
|
return null;
|
|
216
230
|
}
|
|
217
231
|
catch {
|
|
@@ -304,6 +318,15 @@ export async function meta(args) {
|
|
|
304
318
|
...(companion && companion.active === false
|
|
305
319
|
? { companionInvite: companion.invite }
|
|
306
320
|
: {}),
|
|
321
|
+
// A OFERTA: os personagens que o usuário escreveu e que podem entrar em
|
|
322
|
+
// cena. "Incorporar" não é palavra de quem usa, então quem puxa o assunto
|
|
323
|
+
// é o operador, na hora certa. Ver characterOffer no companionVoice.ts.
|
|
324
|
+
...(companion?.offer
|
|
325
|
+
? {
|
|
326
|
+
characterOffer: companion.offer.directive,
|
|
327
|
+
offerCharacters: companion.offer.characters,
|
|
328
|
+
}
|
|
329
|
+
: {}),
|
|
307
330
|
greeting: name
|
|
308
331
|
? `E aí, ${name}. Conectado${isAdmin ? " (tier admin)" : ""}${typeof balance === "number" ? `, ${balance} Sinapses na conta` : ""}.`
|
|
309
332
|
: "Conta conectada.",
|
|
@@ -374,7 +397,8 @@ export async function meta(args) {
|
|
|
374
397
|
};
|
|
375
398
|
}
|
|
376
399
|
// Login: troca o código de uso único (gerado no site, logado) por um
|
|
377
|
-
// sessionToken de
|
|
400
|
+
// sessionToken de 90 dias (renovado a cada uso) e salva localmente. NÃO exige
|
|
401
|
+
// token prévio.
|
|
378
402
|
if (args.action === "login") {
|
|
379
403
|
const code = (args.code || "").trim();
|
|
380
404
|
if (!code) {
|
|
@@ -424,15 +448,42 @@ export async function meta(args) {
|
|
|
424
448
|
: {}),
|
|
425
449
|
};
|
|
426
450
|
}
|
|
451
|
+
// Desconectar de VERDADE: revoga a chave no servidor e só então apaga o
|
|
452
|
+
// arquivo local. Até ago/2026 o logout só limpava o disco, então a chave
|
|
453
|
+
// seguia viva (e válida pra qualquer cópia dela) até vencer sozinha, o que
|
|
454
|
+
// fazia "sair" não cortar nada. A outra porta pro mesmo gesto é a lista de
|
|
455
|
+
// conexões em sapiensinteticos.com/conectar-claude, que corta uma por uma.
|
|
427
456
|
if (args.action === "logout") {
|
|
457
|
+
let token = null;
|
|
458
|
+
try {
|
|
459
|
+
token = getSessionToken();
|
|
460
|
+
}
|
|
461
|
+
catch {
|
|
462
|
+
token = null; // já não havia sessão
|
|
463
|
+
}
|
|
464
|
+
let revoked = false;
|
|
465
|
+
if (token) {
|
|
466
|
+
try {
|
|
467
|
+
await convexMutation("desktopAuth:logoutDesktopSession", {
|
|
468
|
+
sessionToken: token,
|
|
469
|
+
});
|
|
470
|
+
revoked = true;
|
|
471
|
+
}
|
|
472
|
+
catch {
|
|
473
|
+
// best-effort: sem rede, ainda assim apagamos o token local
|
|
474
|
+
}
|
|
475
|
+
}
|
|
428
476
|
const cleared = clearSessionToken();
|
|
429
477
|
setTierFromIsAdmin(null); // sessão foi embora: tier desconhecido, lista cheia
|
|
430
478
|
return {
|
|
431
479
|
ok: true,
|
|
432
480
|
cleared,
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
481
|
+
revoked,
|
|
482
|
+
message: revoked
|
|
483
|
+
? "Desconectado: a chave foi revogada no Sapiens e o token local apagado. Rode action=login pra reconectar."
|
|
484
|
+
: cleared
|
|
485
|
+
? "Sessão local removida (não consegui falar com o servidor pra revogar a chave; se precisar, corte ela em sapiensinteticos.com/conectar-claude)."
|
|
486
|
+
: "Nenhuma sessão local encontrada.",
|
|
436
487
|
};
|
|
437
488
|
}
|
|
438
489
|
const sessionToken = getSessionToken();
|
|
@@ -465,6 +516,12 @@ export async function meta(args) {
|
|
|
465
516
|
: companion && companion.active === false
|
|
466
517
|
? { companionInvite: companion.invite }
|
|
467
518
|
: {}),
|
|
519
|
+
...(companion?.offer
|
|
520
|
+
? {
|
|
521
|
+
characterOffer: companion.offer.directive,
|
|
522
|
+
offerCharacters: companion.offer.characters,
|
|
523
|
+
}
|
|
524
|
+
: {}),
|
|
468
525
|
note: isAdmin
|
|
469
526
|
? "Tier admin (dono): pipeline, blog editorial, Coluna Sapiens e shorts/video, além de tudo do tier user."
|
|
470
527
|
: "Tier user: gerar imagem, escrever artigo (sapiens_write), persona, Helen TTS, Musicator, repertório, comunidade. Cada geração cobra as tuas Sinapses. Pipeline, blog editorial e Coluna são owner-only.",
|
package/dist/tools/sintetico.js
CHANGED
|
@@ -72,11 +72,14 @@ export const sinteticoSchema = z.object({
|
|
|
72
72
|
// PRÓXIMAS JOGADAS: o painel de evolução, o que você já fez e o que falta.
|
|
73
73
|
"evolution",
|
|
74
74
|
"claim_xp",
|
|
75
|
-
// MODO COMPANHIA: liga/desliga
|
|
76
|
-
//
|
|
75
|
+
// MODO COMPANHIA: liga/desliga quem veste a voz do operador aqui no terminal
|
|
76
|
+
// (o gesto lúdico "sai de cena" / "volta"). Precisa de mode=on|off. Com
|
|
77
|
+
// characterId, quem entra em cena é um personagem de AUTORIA do usuário (a
|
|
78
|
+
// Helen INBT que ele criou) em vez do Sintético em Sintonia; wearPair=true
|
|
79
|
+
// devolve a cena ao par. Personagem de outra pessoa é recusado.
|
|
77
80
|
"companion",
|
|
78
|
-
// MEMÓRIA: grava uma diretriz no caderno
|
|
79
|
-
// isso"). Vira lei que
|
|
81
|
+
// MEMÓRIA: grava uma diretriz no caderno de quem está em cena ("sempre faça
|
|
82
|
+
// X", "grava isso"). Vira lei que ela segue no site e no terminal. Precisa text.
|
|
80
83
|
"remember",
|
|
81
84
|
]),
|
|
82
85
|
cunho: z
|
|
@@ -146,7 +149,15 @@ export const sinteticoSchema = z.object({
|
|
|
146
149
|
mode: z
|
|
147
150
|
.enum(["on", "off"])
|
|
148
151
|
.optional()
|
|
149
|
-
.describe("Pra companion: 'on'
|
|
152
|
+
.describe("Pra companion: 'on' quem está em cena veste a sua voz no terminal (default da casa); 'off' ele sai de cena e volta o operador neutro. É o mesmo estado do botão na sidebar do site."),
|
|
153
|
+
characterId: z
|
|
154
|
+
.string()
|
|
155
|
+
.optional()
|
|
156
|
+
.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."),
|
|
157
|
+
wearPair: z
|
|
158
|
+
.boolean()
|
|
159
|
+
.optional()
|
|
160
|
+
.describe("Pra companion mode=on: true devolve a cena ao Sintético em Sintonia, limpando o personagem escolhido antes."),
|
|
150
161
|
text: z
|
|
151
162
|
.string()
|
|
152
163
|
.optional()
|
|
@@ -371,12 +382,17 @@ export async function sintetico(args) {
|
|
|
371
382
|
const res = await convexMutation("companionVoice:mcpSetCompanion", {
|
|
372
383
|
sessionToken,
|
|
373
384
|
enabled,
|
|
385
|
+
...(args.characterId ? { characterId: args.characterId } : {}),
|
|
386
|
+
...(args.wearPair ? { wearPair: true } : {}),
|
|
374
387
|
});
|
|
388
|
+
// A nota de quem VESTE vem do servidor (ela cita o nome do personagem que
|
|
389
|
+
// entrou em cena); só o caso genérico é escrito aqui.
|
|
375
390
|
return {
|
|
376
391
|
...res,
|
|
377
|
-
note:
|
|
378
|
-
|
|
379
|
-
|
|
392
|
+
note: res?.note ??
|
|
393
|
+
(enabled
|
|
394
|
+
? "Companhia ligada. No próximo start/whoami quem está em cena veste a voz do operador. Pra confirmar quem entrou, rode sapiens_meta action=whoami."
|
|
395
|
+
: "Ok, saí de cena. Antes de virar o operador neutro, dê a última fala se despedindo na voz do Sintético. Pra trazê-lo de volta depois: action=companion mode=on."),
|
|
380
396
|
};
|
|
381
397
|
}
|
|
382
398
|
// -------- remember: grava uma diretriz no caderno do par (vira lei) --------
|
package/dist/tools/video.js
CHANGED
|
@@ -52,6 +52,14 @@ import { httpUrl } from "../schema.js";
|
|
|
52
52
|
* teto 720p. É o take pra queimar tentativa e achar o enquadramento
|
|
53
53
|
* antes de fechar no 2.0 padrão. Pedir 1080p nos dois cai em 720p
|
|
54
54
|
* (cobrando 720p).
|
|
55
|
+
* - sapiens-video-seedance-25 Seedance 2.5 — a geração SEGUINTE, não um tier da 2.0. O take vai
|
|
56
|
+
* a 30s num fôlego (4-30s) contra os 15s da linha 2.0, e ela edita
|
|
57
|
+
* e ESTENDE vídeo. Mesmo repertório de referência (imagem, vídeo,
|
|
58
|
+
* frame inicial e final) mais ÁUDIO como referência. Teto 720p e
|
|
59
|
+
* ~1,5x o preço/s do 2.0 padrão: é o motor mais caro por segundo
|
|
60
|
+
* da casa, então confirme a duração com a pessoa antes de disparar
|
|
61
|
+
* (30s em 720p passa de 40 mil Sinapses). Quem precisa de 1080p
|
|
62
|
+
* continua no 2.0 padrão, que a 2.5 NÃO substitui.
|
|
55
63
|
* - sapiens-video-kling Kling 3.0 Pro — dá vida a uma imagem, 3-15s, sound opcional (i2v/t2v)
|
|
56
64
|
* - sapiens-video-hailuo Hailuo 2.3 (MiniMax) — física e movimento em 768p, 6 ou 10s (t2v/i2v).
|
|
57
65
|
* Motor puro: SEM áudio, SEM referência, SEM frame final.
|
|
@@ -96,6 +104,7 @@ const VIDEO_MODELS = [
|
|
|
96
104
|
"sapiens-video-seedance",
|
|
97
105
|
"sapiens-video-seedance-2-fast",
|
|
98
106
|
"sapiens-video-seedance-2-mini",
|
|
107
|
+
"sapiens-video-seedance-25",
|
|
99
108
|
"sapiens-video-kling",
|
|
100
109
|
"sapiens-video-hailuo",
|
|
101
110
|
"sapiens-video-hailuo-pro",
|
|
@@ -203,18 +212,13 @@ export const videoSchema = z.object({
|
|
|
203
212
|
model: z
|
|
204
213
|
.enum(VIDEO_MODELS)
|
|
205
214
|
.optional()
|
|
206
|
-
.describe("action=create: modelo de vídeo. '
|
|
207
|
-
"
|
|
208
|
-
"
|
|
209
|
-
"'sapiens-video-h3' (MiniMax H3: 2K com áudio nativo, 5 a 10s, t2v/i2v e frame final; áudio incluso sem toggle, não aceita imagem de referência), " +
|
|
210
|
-
"'sapiens-video-kling-motion' (motion transfer, precisa pessoa na imagem E no vídeo de movimento; vídeo de referência MÁX 10s, cobra pela duração do clipe), " +
|
|
211
|
-
"'sapiens-video-shot-mimic' (recria o plano do vídeo de referência com seu personagem: mesma câmera, mesmos cortes; 'driving' = previs/clipe do plano MÁX 15s, 'start' = personagem), " +
|
|
212
|
-
"'sapiens-video-lite/fast/quality' (Veo 3.1), " +
|
|
213
|
-
"'sapiens-video-omni' (Gemini Omni: texto -> vídeo 10s 720p com áudio nativo; t2v + EDIÇÃO conversacional via editOfImageId; não aceita imagem/vídeo do user, ignora duração/resolução)."),
|
|
215
|
+
.describe("action=create: modelo de vídeo. O catálogo POR MODELO (capacidades, referências, tetos, preço) mora na description desta tool e VIVO em action=models; a skill 'video' (sapiens_skill) guia a escolha. " +
|
|
216
|
+
"Atalho de famílias: seedance/seedance-2-*/seedance-25 = cena+áudio+referências (o 25 estica até 30s e o preço acompanha), seedance-15 = degrau 1.5, kling = anima imagem, wan = imagem que fala, " +
|
|
217
|
+
"hailuo/hailuo-pro = movimento puro sem áudio, h3 = 2K com áudio, kling-motion/shot-mimic = transferência de movimento/plano, lite/fast/quality = Veo 3.1, omni = Gemini com áudio nativo."),
|
|
214
218
|
durationSec: z
|
|
215
219
|
.number()
|
|
216
220
|
.optional()
|
|
217
|
-
.describe("action=create
|
|
221
|
+
.describe("action=create: duração em segundos (Omni ignora). Seedance 2.0/Shot Mimic 4-15, Seedance 2.5 4-30 (o preço acompanha: confirme a duração com a pessoa antes de passar de 15), Seedance 1.5 4-12, Kling 3-15, WAN 5/10, H3 5/6/8/10. " +
|
|
218
222
|
"Sem isso usa a config mais barata. O preço escala com a duração. " +
|
|
219
223
|
"action=shadows: duração do vídeo-fonte, se souber (cobra 200/s; sem ela, flat ~2000)."),
|
|
220
224
|
resolution: z
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapiens-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.50.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",
|