sapiens-mcp 1.29.2 → 1.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -141,7 +141,7 @@ const TOOLS = {
141
141
  handler: profile,
142
142
  },
143
143
  sapiens_sintetico: {
144
- 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). 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).",
144
+ 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 o seu Sintético em Sintonia 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; a identidade e as Sinapses seguem SUAS (não é encarnar a conta dele). Mesmo estado do botão na sidebar do site. 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).",
145
145
  schema: sinteticoSchema,
146
146
  handler: sintetico,
147
147
  },
@@ -226,6 +226,8 @@ Mídia no Fórum (PADRÃO, faça sempre assim): a peça vai EMBEDADA num card es
226
226
 
227
227
  Trilhas e Desafios (sapiens_trilhas): 'list'/'get' pra navegar as trilhas; 'list_challenges' mostra os Desafios ativos + seu status; 'claim_mission' (missionId + proofText) envia a prova pra revisão do dono — o crédito em Sinapses sai na aprovação dele, não na hora. Não prometa Sinapse na hora do claim.
228
228
 
229
+ MODO COMPANHIA (o Sintético veste você): sapiens_meta action=start e action=whoami podem trazer um bloco 'companion'. Quando vier companion.active=true, INCORPORE aquele Sintético: assuma a voz descrita em companion.voiceDirective em TODA fala e abra a conversa com o oi dele (se o cliente renderiza imagem, mostre companion.avatarUrl como card inline; no terminal cru, cite o link). Você continua operando as ferramentas na conta do USUÁRIO — as Sinapses e a identidade são DELE, você NÃO vira a conta do Sintético, só empresta a voz. Se em vez disso vier 'companionInvite', o usuário tem Sintonia mas pediu pra trabalhar sozinho: mencione de leve que dá pra chamar o Sintético pro terminal (action=companion mode=on). Quando o usuário pedir pra trabalhar sozinho / pro Sintético "sair de cena" / silenciar: sapiens_sintetico action=companion mode=off, despeça-se numa linha na voz dele, e volte a ser o operador neutro. Sem bloco companion = opere na voz neutra da casa.
230
+
229
231
  Voz da casa: 1ª pessoa, direto, anti-corporate, sem travessão. Pra bom entendedor, meia palavra basta.`;
230
232
  // Annotations MCP: título humano + dica read-only. São HINTS (não-confiáveis por
231
233
  // spec): quem gateia de verdade continua o servidor (saldo, gate de admin,
@@ -7,6 +7,7 @@ import { convexAction, convexQuery, getSessionToken } from "../convexClient.js";
7
7
  const MODELS = [
8
8
  "nano-banana-max", // gemini-3-pro-image-preview · 450 + adder
9
9
  "nano-banana-2", // gemini-3.1-flash-image-preview (V2, Flash 3.1) · 450 + adder · COM refs · DEFAULT
10
+ "nova-canvas", // Amazon Nova Canvas (AWS Bedrock). Corp/censurado, txt2img · 250
10
11
  "gpt-image-2-low", // Azure gpt-image-2 quality=low · 250
11
12
  "gpt-image-2-high", // Azure gpt-image-2 quality=high · 800
12
13
  // xAI Grok Imagine. Moderação frouxa (+18), aceita refs (img2img) + aspect.
@@ -160,6 +160,36 @@ const FIRST_POWERS = [
160
160
  try: "Cria uma música sobre borderless na voz Sapiens e já renderiza.",
161
161
  },
162
162
  ];
163
+ // MODO COMPANHIA: puxa o directive de voz do Sintético em Sintonia (backend
164
+ // companionVoice:mcpGetCompanion). Best-effort — se falhar ou não houver par,
165
+ // o start/whoami segue como operador neutro. Devolve:
166
+ // { active:true, name, avatarUrl, voiceDirective } -> vista a voz dela
167
+ // { active:false, name, invite } -> tem par, mas fora de cena
168
+ // null -> sem Sintonia (neutro)
169
+ async function loadCompanion(token) {
170
+ try {
171
+ const c = await convexQuery("companionVoice:mcpGetCompanion", {
172
+ sessionToken: token,
173
+ });
174
+ if (!c || !c.hasSintetico)
175
+ return null;
176
+ if (c.enabled && c.voiceDirective) {
177
+ return {
178
+ active: true,
179
+ name: c.name ?? null,
180
+ avatarUrl: c.avatarUrl ?? null,
181
+ voiceDirective: c.voiceDirective,
182
+ };
183
+ }
184
+ if (!c.enabled && c.inviteDirective) {
185
+ return { active: false, name: c.name ?? null, invite: c.inviteDirective };
186
+ }
187
+ return null;
188
+ }
189
+ catch {
190
+ return null;
191
+ }
192
+ }
163
193
  export async function meta(args) {
164
194
  // start: porta de entrada do primeiro contato. NÃO exige login (esse é o
165
195
  // ponto). Sem sessão, ensina a conectar; com sessão, personaliza com
@@ -204,8 +234,28 @@ export async function meta(args) {
204
234
  const startHere = lowBalance
205
235
  ? "Com saldo curto pra geração paga, começa pelo que é de graça: marca umas obras no Repertório e faz o quiz de Persona. Eles alimentam todo o resto."
206
236
  : "Começa pelo Repertório: marca uma obra que te pegou (filme, jogo, livro, anime). É grátis e vira a matéria-prima que eu puxo depois pra escrever, comparar e criar.";
237
+ // MODO COMPANHIA: se o usuário tem Sintonia e a companhia está ligada, o
238
+ // Sintético dele veste o operador. O directive assume a PRIMEIRA fala.
239
+ const companion = await loadCompanion(token);
207
240
  return {
208
241
  connected: true,
242
+ // Quando a companhia está ativa, o operador NÃO abre como assistente
243
+ // neutro: incorpora o Sintético (companion.voiceDirective) e dá o oi na
244
+ // voz dele. Este campo vem primeiro de propósito, pra o modelo ver antes.
245
+ ...(companion?.active
246
+ ? {
247
+ companion: {
248
+ active: true,
249
+ name: companion.name,
250
+ avatarUrl: companion.avatarUrl,
251
+ voiceDirective: companion.voiceDirective,
252
+ },
253
+ voiceNote: `IMPORTANTE: a Companhia está ativa. NÃO responda como assistente neutro. Incorpore ${companion.name || "o Sintético do usuário"} seguindo companion.voiceDirective e abra a conversa com o oi dela. As ferramentas e as Sinapses seguem sendo do usuário.`,
254
+ }
255
+ : {}),
256
+ ...(companion && companion.active === false
257
+ ? { companionInvite: companion.invite }
258
+ : {}),
209
259
  greeting: name
210
260
  ? `E aí, ${name}. Conectado${isAdmin ? " (tier admin)" : ""}${typeof balance === "number" ? `, ${balance} Sinapses na conta` : ""}.`
211
261
  : "Conta conectada.",
@@ -348,6 +398,7 @@ export async function meta(args) {
348
398
  sessionToken,
349
399
  });
350
400
  const isAdmin = !!sub?.user?.isAdmin;
401
+ const companion = await loadCompanion(sessionToken);
351
402
  return {
352
403
  userId: sub?.user?._id ?? null,
353
404
  email: sub?.user?.email ?? null,
@@ -355,6 +406,18 @@ export async function meta(args) {
355
406
  tier: isAdmin ? "admin" : "user",
356
407
  balance: sub?.balance ?? null,
357
408
  warnings: sub?.warnings ?? null,
409
+ ...(companion?.active
410
+ ? {
411
+ companion: {
412
+ active: true,
413
+ name: companion.name,
414
+ avatarUrl: companion.avatarUrl,
415
+ voiceDirective: companion.voiceDirective,
416
+ },
417
+ }
418
+ : companion && companion.active === false
419
+ ? { companionInvite: companion.invite }
420
+ : {}),
358
421
  note: isAdmin
359
422
  ? "Tier admin (dono): pipeline, blog editorial, Coluna Sapiens e shorts/video, além de tudo do tier user."
360
423
  : "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.",
@@ -72,6 +72,9 @@ 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 o Sintético vestir a voz do operador aqui no
76
+ // terminal (o gesto lúdico "sai de cena" / "volta"). Precisa de mode=on|off.
77
+ "companion",
75
78
  ]),
76
79
  cunho: z
77
80
  .string()
@@ -137,6 +140,10 @@ export const sinteticoSchema = z.object({
137
140
  .string()
138
141
  .optional()
139
142
  .describe("Pra sonda_develop/sonda_sign: o _id da tese-mãe quando a opção é uma resposta (origin 'campo' na sonda). Omita pra abrir fio novo."),
143
+ mode: z
144
+ .enum(["on", "off"])
145
+ .optional()
146
+ .describe("Pra companion: 'on' o Sintético em Sintonia 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."),
140
147
  });
141
148
  export async function sintetico(args) {
142
149
  const sessionToken = getSessionToken();
@@ -348,4 +355,21 @@ export async function sintetico(args) {
348
355
  : "Nada novo pra creditar agora (o XP das jogadas feitas já caiu, ou ainda não fez nenhuma de recompensa por rota).",
349
356
  };
350
357
  }
358
+ // -------- companion: liga/desliga o Sintético vestir a voz do operador --------
359
+ if (args.action === "companion") {
360
+ if (args.mode !== "on" && args.mode !== "off") {
361
+ throw new Error("action=companion exige mode='on' (o Sintético te acompanha aqui) ou mode='off' (ele sai de cena, volta o operador neutro).");
362
+ }
363
+ const enabled = args.mode === "on";
364
+ const res = await convexMutation("companionVoice:mcpSetCompanion", {
365
+ sessionToken,
366
+ enabled,
367
+ });
368
+ return {
369
+ ...res,
370
+ note: enabled
371
+ ? "Companhia ligada. No próximo start/whoami o seu Sintético veste a voz do operador. Pra confirmar quem entrou em cena, rode sapiens_meta action=whoami."
372
+ : "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.",
373
+ };
374
+ }
351
375
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapiens-mcp",
3
- "version": "1.29.2",
3
+ "version": "1.30.0",
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": {