npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

atman-guru

v0.1.2

Published

Atman, um Guru Digital Interativo para conversa, journal e autoconhecimento.

Downloads

457

Readme

Atman Guru

Atman e um Guru Digital Interativo: uma experiencia web conversacional para reflexao, journal, memoria consentida e acompanhamento de jornada interior. Cada conversa funciona como uma Invocacao do Atma: uma presenca simbolica manifesta na interface para ajudar o usuario a refletir, sem se tornar autoridade absoluta sobre ele.

Instalacao Simples

Requisitos:

  • Node.js 20 ou superior;
  • Ollama instalado no sistema.

Instalacao global pelo npm:

npm install -g atman-guru
atman

Tambem e possivel executar sem instalacao global:

npx atman-guru

O comando atman:

  • inicia o Ollama quando ele ainda nao estiver ativo;
  • baixa qwen2.5:3b na primeira execucao;
  • aquece o modelo antes de abrir a interface para reduzir a espera da primeira resposta;
  • escolhe uma porta local livre a partir de 3000;
  • serve API e interface web no mesmo endereco;
  • abre o navegador automaticamente;
  • salva os dados localmente entre execucoes;
  • encerra API e o Ollama iniciado pelo CLI com Ctrl+C.

Na primeira inicializacao, o terminal exibe o aquecimento do modelo. Durante uma resposta local mais lenta, a interface informa que a geracao continua em andamento e preserva a mensagem para uma nova tentativa se houver falha.

Comandos e opcoes:

atman doctor
atman --no-open
atman --port 3001
atman --model qwen2.5:3b
atman --ollama-url http://localhost:11434
atman --help

O arquivo local fica em uma pasta de dados apropriada ao sistema operacional e recebe permissao 0600 em sistemas POSIX. Para escolher outra pasta:

ATMAN_DATA_DIR=/caminho/privado atman

O modo local nao instala Prisma, PostgreSQL, Redis ou BullMQ. Essas integracoes sao opcionais e destinadas ao modo servidor do repositorio. Para habilita-las:

npm install @prisma/client@^6.19.3 bullmq@^5.78.1

Licenca

Distribuido sob a licenca MIT. Consulte LICENSE.

Direcao Atual

O foco atual do projeto saiu de WhatsApp como canal principal e passou para uma interface web em React. O backend existente continua sendo a base de API, e a experiencia web ja organiza conversa, journal, insights, memoria e controles de privacidade como superficie principal do produto.

O Atman Guru e local-first neste momento: a experiencia prevista roda na maquina do usuario/desenvolvedor, com API local, web local, persistencia em arquivo no CLI e LLM mock ou Ollama sem depender de servicos externos. Deploy publico, cadastro aberto em producao e operacao multiusuario ficam fora do escopo atual; as protecoes de producao permanecem no codigo apenas como base futura.

A memoria do Atman e tratada como um espelho revisavel, nao como arquivo definitivo. O usuario esta juntando fragmentos de quem e; o sistema deve ajudar a lembrar sem cristalizar. Dados essenciais ficam no perfil pessoal, enquanto memorias, journal, insights e marcos de jornada permanecem corrigiveis, arquivaveis e exportaveis.

A "empatia" do Atman deve ser operacional, nao uma alegacao de consciencia literal: contexto da conversa, memoria consentida, linguagem cuidadosa, consciencia situacional e limites claros. A especificacao dessa camada esta em docs/empathetic-context.md.

Estado Atual

Implementacao inicial:

  • API Node.js + TypeScript + Express.
  • Interface web React + TypeScript em apps/web.
  • Busca local no diario e edicao inline de memorias na web.
  • GET /health.
  • POST /auth/register.
  • POST /auth/login.
  • GET /auth/me.
  • GET /users/:userId/profile.
  • PATCH /users/:userId/profile.
  • GET /me/profile.
  • PATCH /me/profile.
  • POST /chat/messages.
  • GET /conversations/:id.
  • GET /users/:userId/conversations.
  • GET /me/conversations.
  • POST /journal/entries.
  • GET /journal/entries.
  • DELETE /journal/entries/:id.
  • GET /users/:userId/insights.
  • GET /me/insights.
  • DELETE /users/:userId/insights/:id.
  • DELETE /me/insights/:id.
  • GET /users/:userId/journey.
  • GET /me/journey.
  • POST /users/:userId/journey/snapshots.
  • GET /users/:userId/journey/snapshots.
  • POST /me/journey/snapshots.
  • GET /me/journey/snapshots.
  • POST /users/:userId/journey/summaries.
  • GET /users/:userId/journey/summaries.
  • POST /me/journey/summaries.
  • GET /me/journey/summaries.
  • POST /users/:userId/memories.
  • GET /users/:userId/memories.
  • PATCH /users/:userId/memories/:id.
  • DELETE /users/:userId/memories/:id.
  • POST /me/memories.
  • GET /me/memories.
  • PATCH /me/memories/:id.
  • DELETE /me/memories/:id.
  • POST /users/:userId/reminders.
  • GET /users/:userId/reminders.
  • PATCH /users/:userId/reminders/:id.
  • POST /me/reminders.
  • GET /me/reminders.
  • PATCH /me/reminders/:id.
  • GET /practices.
  • GET /knowledge/search.
  • GET /users/:userId/export.
  • DELETE /users/:userId/data.
  • GET /me/export.
  • DELETE /me/data.
  • GET /metrics.
  • GET /webhooks/whatsapp/health.
  • POST /webhooks/whatsapp.
  • Persona do Atman versionada em codigo.
  • Interface interna de LLM.
  • Provider DeepSeek.
  • Provider mock para desenvolvimento local.
  • Guardrails locais iniciais para temas sensiveis.
  • Comando natural explicito para salvar journal pelo chat.
  • Insights iniciais gerados por worker a partir de entradas de journal.
  • Memoria consentida com CRUD, exportacao, exclusao e uso no contexto do chat.
  • Perfil pessoal persistente para nome, local atual, timezone, nascimento e notas identitarias.
  • Memorias revisaveis com confianca, fixacao e marca de correcao.
  • Contexto situacional com memorias ativas, journal recente e insights recentes.
  • Analise inicial de jornada com temas recorrentes, reflexao e prompts.
  • Filtros de journal por periodo, tag e termo, consumidos pela web.
  • Linha do tempo de jornada com journal, insights e memorias.
  • Snapshots persistidos de jornada para acompanhar evolucao no tempo.
  • Resumos semanais/mensais de jornada gerados apenas por opt-in explicito.
  • Lembretes opt-in com status active, paused e cancelled.
  • Praticas curtas in-app com notas de seguranca.
  • Base de conhecimento curada com metadados, fonte, tipo e busca simples.
  • CORS configurado por WEB_ORIGIN.
  • Rate limiting HTTP basico configuravel.
  • Metricas HTTP e LLM em /metrics, incluindo tokens, custo estimado e status de circuit breaker.
  • Protecao contra conflito entre token de sessao e userId explicito em rotas legadas.
  • Timeout e retry configuraveis para chamadas LLM.
  • Webhook WhatsApp generico com token opcional e deduplicacao por evento, mantido como canal externo opcional/legado.
  • Exportacao e exclusao de dados por usuario.
  • Base BullMQ/Redis para jobs assincronos.
  • Prisma/PostgreSQL preparado para usuarios, conversas, mensagens, journal, insights, lembretes e jobs.
  • Testes de healthcheck, auth, chat, historico de conversas, journal, memorias, jornada, metricas, dados do usuario, webhook WhatsApp, smoke test Prisma e smoke test BullMQ.

Ao executar o codigo-fonte em desenvolvimento, a persistencia usa memoria por padrao. O comando empacotado atman ativa automaticamente a persistencia local em arquivo. Para usar PostgreSQL, configure DATABASE_PROVIDER=prisma.

O repositorio inclui CI no GitHub Actions para validar Prisma, lint, typecheck, testes, teste de integracao Prisma, build da API e build da web em pushes e pull requests para main.

Politica De Contratos Autenticados

A interface web deve preferir sessao de usuario: rotas /me/* e endpoints que aceitam omitir userId quando ha Authorization: Bearer <session-token>. Endpoints com /users/:userId/* permanecem por compatibilidade com scripts, testes e integracoes locais, mas sao tratados como legado controlado.

Quando uma rota legada com userId manual tiver equivalente autenticado, a resposta inclui:

  • X-Atman-Legacy-User-Route: true
  • Link: </me/...>; rel="successor-version"

Se uma sessao for enviada junto com userId explicito divergente, a API retorna 403 para evitar acesso cruzado.

Requisitos

  • Node.js 20 ou superior.
  • npm 10 ou superior.

Setup Local

npm install
cp .env.example .env
npm run dev

Em outro terminal, suba a interface web:

npm run web:dev

Por padrao, a API roda em http://localhost:3000 e a web em http://localhost:5173. A variavel WEB_ORIGIN controla a origem aceita pelo CORS da API.

Checklist local recomendado antes de consolidar mudancas:

npm run lint
npm run typecheck
npm test
npm run web:test
npm run build
npm run web:build

Os assets de marca da interface ficam em apps/web/public/assets/brand. O app usa derivados leves para favicon e sidebar, mantendo os PNGs originais como fonte visual dentro do repositorio. Os assets dos 22 Arcanos Maiores ficam em apps/web/public/assets/tarot/major, com PNGs fonte em source, WebP para desktop em desktop, WebP para mobile em mobile e WebP de alta resolucao para contemplacao em detail, seguindo o processo descrito em docs/tarot-asset-workflow.md.

Por padrao, LLM_PROVIDER=mock, entao a API funciona sem chave externa.

Para usar LLM local com Qwen via Ollama:

ollama serve
ollama pull qwen2.5:3b
LLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=qwen2.5:3b
OLLAMA_NUM_CTX=4096
LLM_TIMEOUT_MS=90000
LLM_MAX_RETRIES=1
LLM_RECENT_MESSAGE_LIMIT=8
LLM_CONTEXT_MEMORY_LIMIT=5
LLM_CONTEXT_JOURNAL_LIMIT=3
LLM_CONTEXT_INSIGHT_LIMIT=3
LLM_MAX_PROMPT_CHARS=10000
LLM_MAX_OUTPUT_TOKENS=700
LLM_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
LLM_CIRCUIT_BREAKER_COOLDOWN_MS=30000

No hardware atual analisado para desenvolvimento local (Xeon E5-2680 v4, 32 GiB RAM, RX 550 4 GiB), trate o Qwen local como CPU-first. A GPU AMD pode continuar sendo usada pelo sistema, mas nao deve ser dependencia do MVP de LLM local. O qwen3:4b foi testado, mas nesta instalacao consumiu a geracao em modo thinking e nao entregou resposta final em tempo adequado. Para chat rapido, o padrao local recomendado passou a ser qwen2.5:3b.

Para medir o provedor local configurado:

LLM_PROVIDER=ollama OLLAMA_MODEL=qwen2.5:3b npm run llm:benchmark

Benchmark recente com qwen2.5:3b: resposta curta em cerca de 8,3s com 58 tokens de saida; resposta mais longa com maxOutputTokens=700 em cerca de 12,1s com 195 tokens de saida. Os testes automatizados forcam LLM_PROVIDER=mock para nao depender do Ollama real durante validacao.

Astrologia usa um motor local de efemerides por padrao:

ASTROLOGY_EPHEMERIS_PROVIDER=astronomy-engine

Com esse provider ativo, o modo invocationMode=astrology injeta no prompt o ceu geocentrico tropical calculado para o momento atual. Use ASTROLOGY_EPHEMERIS_PROVIDER=none para desativar essa capacidade. Casas, ascendente, mapa natal, sinastria e retorno solar ainda exigem data, hora e local do usuario. Na web, o modo Astrologia inclui um painel guiado para ceu atual, mapa natal, transito, sinastria, retorno solar e simbolismo geral. Data, hora e local aparecem apenas quando a leitura exige esses dados.

Para usar DeepSeek:

LLM_PROVIDER=deepseek
DEEPSEEK_API_KEY=sua-chave
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat
LLM_TIMEOUT_MS=30000
LLM_MAX_RETRIES=1
LLM_RECENT_MESSAGE_LIMIT=12
LLM_CONTEXT_MEMORY_LIMIT=8
LLM_CONTEXT_JOURNAL_LIMIT=5
LLM_CONTEXT_INSIGHT_LIMIT=5
LLM_MAX_PROMPT_CHARS=24000
LLM_MAX_OUTPUT_TOKENS=700
LLM_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5
LLM_CIRCUIT_BREAKER_COOLDOWN_MS=30000
DEEPSEEK_INPUT_COST_PER_1M_TOKENS_USD=0
DEEPSEEK_OUTPUT_COST_PER_1M_TOKENS_USD=0

Os limites LLM_RECENT_MESSAGE_LIMIT, LLM_CONTEXT_*, LLM_MAX_PROMPT_CHARS e LLM_MAX_OUTPUT_TOKENS controlam custo e latencia do prompt. O Atman preserva persona e contexto consentido primeiro, depois mantem as mensagens mais recentes ate caber no orcamento configurado.

O chat tambem usa politica de saida por modo: Reflexao, Taro, Astrologia, Meditacao e Journal recebem tetos diferentes dentro do limite global. O botao Continuar envia uma continuacao contextual: o backend ancora a nova resposta no trecho final da resposta anterior para evitar repeticao e perda do fio. Na interface web, a continuacao usa rotulos por modo, e o chat possui scroll com pin inteligente: se o usuario estiver no fim, acompanha a resposta; se ele subir para ler, aparece Ir ao fim sem puxar a tela agressivamente.

No modo Taro, a interface web pode enviar tarotContext junto da mensagem: baralho/tradicao, tiragem, pergunta, intencao, descricao visual de baralho autoral e cartas com posicao/orientacao/notas. Esse contexto entra no prompt como orientacao operacional e nao altera a mensagem salva no historico. A aba Taro tambem inclui um ritual visual local focado nos 22 Arcanos Maiores: embaralhar, cortar, escolher 1, 3 ou 5 cartas, preencher automaticamente a leitura e enviar ao Atman quando a tiragem se completa. Arcanos Menores ficam adiados por enquanto para nao tornar a experiencia confusa. O ritual usa assets autorais responsivos, preview recolhivel da leitura, modo de contemplacao da carta, camadas de aprofundamento e prompt ajustado para leitura simbolica em blocos curtos.

As variaveis de custo sao opcionais e devem ser preenchidas com o preco atual do modelo escolhido por 1 milhao de tokens. O Atman nao fixa uma tabela de precos no codigo; /metrics apenas calcula uma estimativa a partir do usage retornado pelo provider e dos valores configurados. O circuit breaker abre depois de LLM_CIRCUIT_BREAKER_FAILURE_THRESHOLD falhas consecutivas e volta a permitir uma tentativa depois de LLM_CIRCUIT_BREAKER_COOLDOWN_MS. Use threshold 0 para desativar.

Para usar PostgreSQL com Prisma:

DATABASE_PROVIDER=prisma
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/atman_guru

Depois rode:

docker compose up -d postgres
npm run prisma:generate
npm run prisma:migrate
npm run test:prisma

O docker-compose.yml tambem inclui Redis para fases futuras com BullMQ:

docker compose up -d redis
npm run test:queue

Para ativar enfileiramento de analise de journal:

JOB_QUEUE_PROVIDER=bullmq
REDIS_URL=redis://localhost:6379

Com esse provedor ativo, entradas de journal enfileiram jobs em journal-pattern-analysis. Para rodar workers localmente:

npm run worker

O webhook WhatsApp nao e mais o foco principal do produto, mas segue disponivel como canal externo opcional. Para protege-lo, configure um segredo:

WHATSAPP_WEBHOOK_SECRET=um-segredo-forte

Quando essa variavel existe, POST /webhooks/whatsapp exige Authorization: Bearer <segredo> ou x-webhook-secret: <segredo>.

Para proteger os endpoints de usuario (/chat, /journal, /conversations e /users), configure:

API_AUTH_TOKEN=um-token-forte

Quando essa variavel existe, esses endpoints exigem Authorization: Bearer <token> ou x-api-token: <token>. Em NODE_ENV=production, API_AUTH_TOKEN e obrigatorio.

Para sessao web, configure um segredo:

JWT_SECRET=um-segredo-com-pelo-menos-16-caracteres

Em desenvolvimento, ha um segredo local padrao. Em NODE_ENV=production, JWT_SECRET deve ser configurado.

O contrato dos endpoints consumidos pela interface web fica disponivel em:

GET /openapi.json

Esse documento declara x-api-token para protecao operacional da API e Authorization: Bearer <session-token> para a sessao web em rotas /me.

Para ajustar CORS e rate limit HTTP:

WEB_ORIGIN=http://localhost:5173
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX_REQUESTS=120

Para rotina de retencao em producao:

RETENTION_DAYS=90
RETENTION_INCLUDE_USER_CONTENT=false

Com RETENTION_DAYS=0, a rotina fica desativada. Por padrao, RETENTION_INCLUDE_USER_CONTENT=false remove apenas dados operacionais antigos: jobs finalizados, eventos de webhook antigos, memorias ja marcadas como deleted e lembretes cancelados. Defina RETENTION_INCLUDE_USER_CONTENT=true somente se a politica do produto permitir remover conversas, journal e insights mais antigos que o periodo configurado. Snapshots de jornada seguem a mesma regra de conteudo do usuario.

Scripts

npm run dev        # sobe a API em modo watch
npm run web:dev    # sobe a interface React em modo desenvolvimento
npm run web:build  # valida e gera build da interface React
npm run web:preview # serve o build da interface React
npm run web:test   # roda testes de componentes e do cliente web
npm run web:test:watch # roda testes web em modo interativo
npm run worker     # sobe workers BullMQ em modo watch
npm run start      # executa a API compilada
npm run start:worker # executa workers compilados
npm run build      # compila TypeScript
npm run typecheck  # valida tipos sem gerar dist
npm test           # roda testes
npm run test:prisma # roda smoke test com PostgreSQL local
npm run test:queue # roda smoke test com Redis/BullMQ local
npm run lint       # roda ESLint
npm run prisma:generate # gera Prisma Client
npm run prisma:validate # valida schema Prisma
npm run prisma:migrate  # aplica migration local
npm run prisma:deploy   # aplica migrations em ambiente deploy
npm run prisma:studio   # abre Prisma Studio
npm run db:backup       # gera dump PostgreSQL em BACKUP_DIR
npm run maintenance:retention # simula a rotina de retencao
npm run maintenance:retention:apply # aplica a rotina de retencao
npm run start:retention # aplica retencao usando build compilado

Producao Opcional

O caminho principal do projeto continua sendo uso local. Esta secao fica como referencia para uma eventual publicacao futura ou instalacao privada mais rigida.

Fluxo minimo de deploy da API, quando esse modo voltar a ser prioridade:

npm ci
npm run prisma:generate
npm run build
npm run web:build
npm run db:backup
npm run prisma:deploy
npm run start

Workers e manutencao devem rodar como processos separados:

npm run start:worker
npm run start:retention

Antes de agendar start:retention, execute npm run maintenance:retention para conferir o dry-run. Backups do PostgreSQL devem existir antes de usar RETENTION_INCLUDE_USER_CONTENT=true.

Para enviar erros nao tratados para uma ferramenta externa de observabilidade, configure um webhook HTTPS:

ERROR_REPORT_WEBHOOK_URL=https://observabilidade.exemplo/atman-erros

O payload enviado contem metadados tecnicos, nome/mensagem do erro e contexto de rota/processo; corpo de requests, mensagens, journal e memorias nao sao enviados.

Para avaliar alertas operacionais por /health e /metrics, configure:

ALERT_API_BASE_URL=https://api.exemplo.com
ALERT_WEBHOOK_URL=https://observabilidade.exemplo/atman-alertas
ALERT_HTTP_5XX_THRESHOLD=5
ALERT_LLM_ERROR_THRESHOLD=5
ALERT_LLM_LATENCY_RATIO=0.8
ALERT_LLM_DAILY_COST_BUDGET_USD=0

Execute uma checagem local com:

npm run monitor:alerts

Em producao, apos npm run build, use npm run start:monitor:alerts por cron/systemd. O comando sai com codigo 2 quando ha alerta ativo, permitindo integracao tambem por supervisor externo.

Autenticacao Web

Registrar usuario

POST /auth/register
Content-Type: application/json

Body:

{
  "userId": "local-user",
  "name": "Opcional",
  "password": "senha-com-8-ou-mais-caracteres"
}

Resposta:

{
  "token": "session-token",
  "user": {
    "id": "local-user",
    "name": "Opcional"
  }
}

Entrar

POST /auth/login
Content-Type: application/json

Body:

{
  "userId": "local-user",
  "password": "senha-com-8-ou-mais-caracteres"
}

Sessao atual

GET /auth/me
Authorization: Bearer <session-token>

Quando um Authorization: Bearer <session-token> valido e enviado, alguns endpoints tambem aceitam omitir userId ou usar atalhos /me:

  • GET /me/profile.
  • PATCH /me/profile.
  • POST /chat/messages pode omitir userId.
  • POST /journal/entries pode omitir userId.
  • GET /journal/entries pode omitir userId.
  • DELETE /journal/entries/:id pode omitir userId.
  • GET /me/conversations.
  • GET /me/insights.
  • DELETE /me/insights/:id.
  • GET /me/journey.
  • POST /me/memories.
  • GET /me/memories.
  • PATCH /me/memories/:id.
  • DELETE /me/memories/:id.
  • GET /me/export.
  • DELETE /me/data.

Perfil E Memorias Revisaveis

O perfil guarda dados fundamentais que o Atman deve lembrar com mais estabilidade: nome ou forma de tratamento, local atual, timezone, data/hora/local de nascimento e notas identitarias. Em modo local com DATABASE_PROVIDER=memory, esse perfil vive apenas enquanto a API esta rodando. Com DATABASE_PROVIDER=prisma, ele fica persistido no PostgreSQL.

As memorias guardam fragmentos revisaveis: preferencias, fatos, temas, limites e objetivos. Cada memoria inclui:

  • confidence: high, medium ou low.
  • pinned: marca que o fragmento deve ter prioridade no contexto.
  • correctedAt: preenchido quando o conteudo e corrigido.
  • status: active, archived ou deleted.

O prompt do Atman recebe perfil e memorias com a orientacao de tratar tudo como apoio revisavel. Se o usuario corrigir uma lembranca, a versao nova deve prevalecer; a anterior nao deve ser tratada como verdade fixa. Quando uma resposta usa memorias ativas, o contrato de chat retorna contextUsage.memories: true e a interface informa esse uso. Novas sugestoes continuam dependendo de revisao e confirmacao antes de serem salvas.

Endpoints

Healthcheck

GET /health

Resposta:

{
  "status": "ok",
  "service": "atman-guru",
  "timestamp": "2026-06-12T00:00:00.000Z"
}

Enviar mensagem

POST /chat/messages
Content-Type: application/json

Body:

{
  "userId": "local-user",
  "message": "Estou confuso sobre meu trabalho.",
  "conversationId": "opcional-uuid",
  "invocationMode": "reflection"
}

invocationMode e opcional e aceita reflection, tarot, astrology, meditation ou journal. Ele orienta a Invocacao do Atma no prompt do LLM, mas nao altera o texto da mensagem salvo no historico. Quando astrology e usado e ASTROLOGY_EPHEMERIS_PROVIDER=astronomy-engine, o prompt tambem recebe o ceu astrologico calculado pelo backend.

Resposta:

{
  "conversationId": "uuid",
  "reply": {
    "role": "assistant",
    "content": "resposta do Atman",
    "provider": "mock",
    "model": "local-reflection"
  }
}

Para resposta em tempo real na interface web, use o endpoint SSE:

POST /chat/messages/stream
Content-Type: application/json
Accept: text/event-stream

Eventos emitidos:

  • start: informa conversationId.
  • delta: traz trechos incrementais da resposta.
  • done: traz a resposta final persistida.
  • error: informa falha durante o streaming.

Para salvar uma entrada de journal pelo chat, use um comando explicito:

{
  "userId": "local-user",
  "message": "registre isso no meu diario: hoje percebi um padrao importante."
}

Quando o comando e reconhecido, a resposta inclui journalEntry e o LLM externo nao e chamado.

Consultar conversa

GET /conversations/:id?userId=local-user

Resposta:

{
  "conversation": {
    "id": "uuid",
    "userId": "local-user",
    "createdAt": "2026-06-13T00:00:00.000Z",
    "updatedAt": "2026-06-13T00:00:00.000Z",
    "messages": []
  }
}

Retorna 404 quando a conversa nao existe ou nao pertence ao userId informado.

Listar conversas do usuario

GET /users/:userId/conversations?limit=20

Resposta:

{
  "conversations": [
    {
      "id": "uuid",
      "userId": "local-user",
      "createdAt": "2026-06-13T00:00:00.000Z",
      "updatedAt": "2026-06-13T00:00:00.000Z",
      "messageCount": 2,
      "lastMessage": {
        "role": "assistant",
        "content": "resposta do Atman",
        "createdAt": "2026-06-13T00:00:00.000Z"
      }
    }
  ]
}

Criar entrada de journal

POST /journal/entries
Content-Type: application/json

Body:

{
  "userId": "local-user",
  "title": "Opcional",
  "content": "Hoje percebi um padrao importante.",
  "tags": ["disciplina", "calma"]
}

Resposta:

{
  "entry": {
    "id": "uuid",
    "userId": "local-user",
    "title": "Opcional",
    "content": "Hoje percebi um padrao importante.",
    "tags": ["disciplina", "calma"],
    "createdAt": "2026-06-13T00:00:00.000Z",
    "updatedAt": "2026-06-13T00:00:00.000Z"
  }
}

Listar journal

GET /journal/entries?userId=local-user&limit=20&from=2026-06-01&to=2026-06-30&tag=foco&q=trabalho

Filtros opcionais:

  • from e to: YYYY-MM-DD ou datetime ISO.
  • tag: tag normalizada do registro.
  • q: termo em titulo, conteudo ou tags.

Resposta:

{
  "entries": []
}

Sugerir tags de journal

POST /journal/tags/suggest
Content-Type: application/json

Body:

{
  "userId": "local-user",
  "title": "Rotina de foco",
  "content": "Hoje o trabalho pediu foco e uma pausa para respeitar meu limite.",
  "existingTags": ["trabalho"],
  "limit": 6
}

Resposta:

{
  "suggestions": [
    {
      "name": "foco",
      "confidence": "medium",
      "reason": "Um termo do registro aponta para este tema."
    }
  ],
  "method": "heuristic-keyword-match; suggestions are optional and not stored until the user saves them"
}

As sugestoes sao heuristicas, conservadoras e opt-in: nenhuma tag e salva ate o usuario aplicar a sugestao e salvar a entrada.

Excluir entrada de journal

DELETE /journal/entries/:id?userId=local-user

Retorna 204 No Content quando a entrada pertence ao usuario e foi excluida. Se existir um insight heuristico com source associado a essa entrada, ele tambem e removido.

Listar insights

GET /users/:userId/insights?limit=20

Com sessao web, tambem existe:

GET /me/insights?limit=20
Authorization: Bearer <session-token>

Cada insight inclui origin, com valores manual, heuristic ou llm, alem de source para rastrear a origem tecnica.

Apagar insight

DELETE /users/:userId/insights/:id

Com sessao web:

DELETE /me/insights/:id
Authorization: Bearer <session-token>

Retorna 204 No Content quando o insight pertence ao usuario.

Buscar base de conhecimento curada

GET /knowledge/search?q=espelho&theme=produto&limit=10

Resposta:

{
  "entries": [
    {
      "id": "atman-espelho-nao-autoridade",
      "title": "Atman como espelho, nao autoridade",
      "theme": "produto",
      "source": "Nota autoral do projeto Atman",
      "type": "author-note",
      "confidence": "high",
      "summary": "O Atman organiza reflexoes e devolve perguntas.",
      "note": "Use esta ideia para manter respostas em tom de companhia reflexiva."
    }
  ],
  "method": "curated-local-search; entries are paraphrased or authorial notes and are not automatically injected into chat prompts"
}

Tipos de entrada: canonical, interpretation, author-note. A base usa parafrases e notas autorais; ela nao reproduz textos protegidos integralmente.

Consultar ceu astrologico atual

GET /astrology/current?date=2026-07-16T19:00:00.000Z

date e opcional. Quando omitido, o backend usa o horario atual do servidor.

Resposta:

{
  "chart": {
    "calculatedAt": "2026-07-16T19:00:00.000Z",
    "zodiac": "tropical",
    "frame": "apparent-geocentric-ecliptic-of-date",
    "source": "astronomy-engine",
    "positions": [
      {
        "body": "Sol",
        "longitudeDegrees": 114.26,
        "latitudeDegrees": 0,
        "sign": "Cancer",
        "degreeInSign": 24.26,
        "retrograde": false
      }
    ],
    "moonPhaseDegrees": 32.71
  },
  "method": "astronomy-engine; apparent geocentric ecliptic longitude; tropical zodiac; houses require birth/observer data"
}

O endpoint calcula Sol, Lua, Mercurio, Venus, Marte, Jupiter, Saturno, Urano, Netuno e Plutao em longitude ecliptica geocentrica tropical. Ele nao calcula casas ou ascendente sem data, hora e local.

Analisar jornada

GET /users/:userId/journey?limit=20&from=2026-06-01&to=2026-06-30

Com sessao web:

GET /me/journey?limit=20&from=2026-06-01&to=2026-06-30
Authorization: Bearer <session-token>

from e to aceitam YYYY-MM-DD ou datetime ISO. Quando omitidos, a analise usa os registros mais recentes ate o limite informado.

Resposta:

{
  "journey": {
    "userId": "local-user",
    "generatedAt": "2026-06-13T00:00:00.000Z",
    "filters": {
      "limit": 20,
      "from": "2026-06-01T00:00:00.000Z",
      "to": "2026-06-30T23:59:59.999Z"
    },
    "period": {
      "journalEntriesAnalyzed": 0,
      "insightsAnalyzed": 0,
      "memoriesAnalyzed": 0
    },
    "method": "Leitura heuristica baseada em tags de diario, tipos de memorias ativas e volume de insights no periodo. Nao e diagnostico nem inferencia clinica.",
    "recurringThemes": [
      {
        "name": "foco",
        "count": 2,
        "sources": [
          {
            "type": "journal",
            "id": "uuid",
            "label": "Registro sem titulo",
            "createdAt": "2026-06-13T00:00:00.000Z"
          }
        ]
      }
    ],
    "reflection": "Ainda ha pouco material para observar padroes.",
    "prompts": []
  }
}

Linha do tempo de jornada

GET /users/:userId/journey/timeline?limit=50&from=2026-06-01&to=2026-06-30

Com sessao web:

GET /me/journey/timeline?limit=50&from=2026-06-01&to=2026-06-30
Authorization: Bearer <session-token>

Resposta:

{
  "timeline": [
    {
      "id": "uuid",
      "type": "journal",
      "occurredAt": "2026-06-13T00:00:00.000Z",
      "title": "Registro de diario",
      "summary": "Resumo curto do evento.",
      "metadata": {
        "tags": ["foco"]
      }
    }
  ]
}

Salvar marco de jornada

POST /users/:userId/journey/snapshots?limit=50&from=2026-06-01&to=2026-06-30

Com sessao web:

POST /me/journey/snapshots?limit=50&from=2026-06-01&to=2026-06-30
Authorization: Bearer <session-token>

Resposta:

{
  "snapshot": {
    "id": "uuid",
    "userId": "local-user",
    "createdAt": "2026-06-13T00:00:00.000Z",
    "analysis": {
      "userId": "local-user",
      "generatedAt": "2026-06-13T00:00:00.000Z",
      "period": {
        "journalEntriesAnalyzed": 1,
        "insightsAnalyzed": 0,
        "memoriesAnalyzed": 1
      },
      "recurringThemes": [],
      "reflection": "Leitura contextual da jornada.",
      "prompts": []
    }
  }
}

Listar marcos de jornada

GET /users/:userId/journey/snapshots?limit=10

Com sessao web:

GET /me/journey/snapshots?limit=10
Authorization: Bearer <session-token>

Comparar marcos de jornada

GET /users/:userId/journey/snapshots/compare

Sem parametros, compara os dois marcos mais recentes. Para escolher marcos especificos:

GET /users/:userId/journey/snapshots/compare?fromSnapshotId=<uuid>&toSnapshotId=<uuid>

Com sessao web:

GET /me/journey/snapshots/compare
Authorization: Bearer <session-token>

Resposta:

{
  "comparison": {
    "userId": "local-user",
    "generatedAt": "2026-06-13T00:00:00.000Z",
    "fromSnapshot": {
      "id": "uuid",
      "createdAt": "2026-06-01T00:00:00.000Z"
    },
    "toSnapshot": {
      "id": "uuid",
      "createdAt": "2026-06-13T00:00:00.000Z"
    },
    "periodDelta": {
      "journalEntriesAnalyzed": 2,
      "insightsAnalyzed": 0,
      "memoriesAnalyzed": 1
    },
    "themes": {
      "emerging": [],
      "intensifying": [],
      "reducing": [],
      "stable": []
    },
    "reflection": "Comparacao contextual entre marcos salvos."
  }
}

Criar resumo periodico de jornada

Resumos periodicos sao opt-in: a criacao exige optIn: true no corpo da requisicao. O periodo aceito e weekly ou monthly; referenceDate define a semana ou mes usado como referencia.

POST /users/:userId/journey/summaries
Content-Type: application/json

Com sessao web:

POST /me/journey/summaries
Authorization: Bearer <session-token>
Content-Type: application/json

Corpo:

{
  "period": "weekly",
  "optIn": true,
  "referenceDate": "2026-07-16",
  "limit": 50
}

Resposta:

{
  "summary": {
    "id": "uuid",
    "userId": "local-user",
    "period": "weekly",
    "startedAt": "2026-07-13T00:00:00.000Z",
    "endedAt": "2026-07-19T23:59:59.999Z",
    "createdAt": "2026-07-16T00:00:00.000Z",
    "analysis": {
      "userId": "local-user",
      "generatedAt": "2026-07-16T00:00:00.000Z",
      "period": {
        "journalEntriesAnalyzed": 1,
        "insightsAnalyzed": 0,
        "memoriesAnalyzed": 1
      },
      "recurringThemes": [],
      "reflection": "Leitura contextual da jornada.",
      "prompts": []
    }
  }
}

Listar resumos periodicos

GET /users/:userId/journey/summaries?limit=10&period=weekly

Com sessao web:

GET /me/journey/summaries?limit=10&period=monthly
Authorization: Bearer <session-token>

Criar memoria

POST /users/:userId/memories
Content-Type: application/json

Body:

{
  "type": "preference",
  "content": "Prefiro respostas mais diretas."
}

Tipos aceitos: preference, fact, theme, limit, goal.

Sugerir memoria derivada

POST /users/:userId/memories/suggest
Content-Type: application/json

Com sessao web:

POST /me/memories/suggest
Authorization: Bearer <session-token>
Content-Type: application/json

Body:

{
  "source": "chat",
  "text": "Prefiro respostas mais diretas quando estou sobrecarregado.",
  "limit": 3
}

Resposta:

{
  "suggestions": [
    {
      "type": "preference",
      "source": "chat-command",
      "content": "Prefiro respostas mais diretas quando estou sobrecarregado.",
      "confidence": "high",
      "reason": "O texto expressa uma preferencia explicita do usuario."
    }
  ],
  "method": "heuristic-explicit-memory-candidates; suggestions are not stored until the user confirms them"
}

Sugestoes de memoria sao conservadoras e nao sao salvas automaticamente. Para ativar uma sugestao, o cliente deve enviar POST /memories com o conteudo revisado pelo usuario.

Listar memorias

GET /users/:userId/memories?status=active&limit=50

Status aceitos: active, archived, deleted.

Atualizar memoria

PATCH /users/:userId/memories/:id
Content-Type: application/json

Body:

{
  "status": "archived",
  "content": "Prefiro respostas curtas e diretas."
}

Apagar memoria

DELETE /users/:userId/memories/:id

Retorna 204 No Content quando a memoria pertence ao usuario e foi apagada.

Criar lembrete

POST /users/:userId/reminders
Content-Type: application/json

Com sessao web:

POST /me/reminders
Authorization: Bearer <session-token>
Content-Type: application/json

Body:

{
  "text": "Escrever no diario.",
  "cron": "0 8 * * *",
  "timezone": "America/Bahia",
  "optIn": true
}

optIn: true e obrigatorio. Quando JOB_QUEUE_PROVIDER=bullmq e cron existe, o lembrete e agendado na fila reminders.

Listar lembretes

GET /users/:userId/reminders?limit=20

Com sessao web:

GET /me/reminders?limit=20
Authorization: Bearer <session-token>

Resposta:

{
  "reminders": []
}

Atualizar status do lembrete

PATCH /users/:userId/reminders/:id
Content-Type: application/json

Com sessao web:

PATCH /me/reminders/:id
Authorization: Bearer <session-token>
Content-Type: application/json

Body:

{
  "status": "paused"
}

Status aceitos: active, paused, cancelled.

Listar praticas curtas

GET /practices

Resposta:

{
  "practices": [
    {
      "id": "breathing-3-4-6",
      "type": "breathing",
      "title": "Respiracao 3-4-6",
      "durationMinutes": 3,
      "steps": ["Inspire pelo nariz contando ate 3."],
      "prompt": "O que mudou no corpo depois de alguns ciclos de respiracao?",
      "safetyNote": "Esta pratica nao substitui cuidado medico."
    }
  ]
}

As praticas sao conteudo in-app, nao lembretes. Notificacoes continuam exigindo opt-in explicito via lembretes.

Exportar dados do usuario

GET /users/:userId/export

Resposta:

{
  "data": {
    "userId": "local-user",
    "exportedAt": "2026-06-13T00:00:00.000Z",
    "conversations": [],
    "journalEntries": [],
    "insights": [],
    "journeySnapshots": [],
    "journeySummaries": [],
    "memories": [],
    "reminders": [],
    "whatsappEvents": []
  }
}

Excluir dados do usuario

DELETE /users/:userId/data

Resposta:

{
  "userId": "local-user",
  "deleted": {
    "conversations": 1,
    "journalEntries": 1,
    "insights": 1,
    "journeySnapshots": 1,
    "journeySummaries": 1,
    "memories": 1,
    "reminders": 1,
    "whatsappEvents": 0,
    "userRecord": false
  }
}

No modo Prisma, userRecord indica se o registro User tambem foi removido.

Metricas

GET /metrics

Resposta:

{
  "metrics": {
    "startedAt": "2026-06-13T00:00:00.000Z",
    "uptimeSeconds": 10,
    "http": [
      {
        "method": "GET",
        "route": "/health",
        "statusCode": 200,
        "count": 1
      }
    ],
    "llm": [
      {
        "provider": "mock",
        "model": "local-reflection",
        "status": "success",
        "count": 1,
        "totalLatencyMs": 4,
        "averageLatencyMs": 4,
        "inputTokens": 120,
        "outputTokens": 42,
        "totalTokens": 162,
        "estimatedCostUsd": 0
      }
    ]
  }
}

Para DeepSeek, inputTokens, outputTokens e totalTokens vêm do campo usage da resposta do provider. estimatedCostUsd usa DEEPSEEK_INPUT_COST_PER_1M_TOKENS_USD e DEEPSEEK_OUTPUT_COST_PER_1M_TOKENS_USD; se esses valores forem 0, a metrica continua informando uso sem estimar custo. O status de LLM pode ser success, error ou circuit-open.

Runbook de producao: docs/production-runbook.md. Checklist de seguranca: docs/security-checklist.md. Exemplos de agendamento e alertas: docs/ops.

Healthcheck WhatsApp Opcional

GET /webhooks/whatsapp/health

Resposta:

{
  "status": "ok",
  "service": "atman-guru-whatsapp",
  "timestamp": "2026-06-13T00:00:00.000Z"
}

Receber mensagem do WhatsApp Opcional

POST /webhooks/whatsapp
Content-Type: application/json

Body minimo:

{
  "eventId": "evento-unico-do-provedor",
  "phone": "+55 71 99999-0000",
  "text": "Hoje estou inquieto."
}

Campos equivalentes tambem sao aceitos para facilitar adaptacao ao provedor:

  • ID do evento: eventId, messageId, id, message.id, data.message.id.
  • Remetente: phone, from, sender, contact.phone, data.from.
  • Texto: text, body, message, message.text, data.message.text.

Resposta:

{
  "status": "processed",
  "duplicate": false,
  "userId": "whatsapp:5571999990000",
  "conversationId": "uuid",
  "reply": "resposta do Atman"
}

Eventos repetidos com o mesmo eventId retornam:

{
  "status": "duplicate",
  "duplicate": true,
  "userId": "whatsapp:5571999990000"
}

Proximos Passos

O plano operacional detalhado esta em docs/next-implementation-plan.md.

Ordem recomendada:

  1. Polir o fluxo central da conversa: sessoes longas, scroll final, controles recolhidos, botao Continuar, Markdown e mobile.
  2. Refinar a voz do Atman com testes reais de Taro, Astrologia, meditacao, reflexao e limites.
  3. Refinar Taro com assets autorais dos 22 Arcanos, area de foco da carta revelada, tiragens mais ricas e preferencia de baralho; reavaliar Arcanos Menores apenas quando houver uma UX clara.
  4. Expandir Astrologia guiada para mapa natal, transito, sinastria e retorno solar sem inventar dados pessoais.
  5. Melhorar memoria e personalizacao com preferencias simbolicas consentidas.
  6. Manter modo local limpo: sem token/auth na experiencia cotidiana.
  7. Calibrar LLM_MAX_PROMPT_CHARS, LLM_MAX_OUTPUT_TOKENS, thresholds e latencia conforme uso real.
  8. Opcional para producao: apontar ALERT_WEBHOOK_URL para o provedor real de observabilidade.
  9. Manter /openapi.json sincronizado quando novos fluxos web forem criados.