PTENES
Gateway de Telegram · cola duradera

Envías una línea por el chat. El trabajo pesado ocurre automáticamente.

Bot de Telegram con cola duradera en SQLite: ejecuta skills de una etapa y flujos de varias fases con estado, portón humano y reanudación después de una caída.

inemaccbot — gateway Telegram y cola duradera
Qué es

Un operador que no pierde trabajo por el camino

El bot recibe comandos en Telegram, encola el trabajo y lo ejecuta como agente. La cola es duradera: si el proceso se cae a mitad de un renderizado, al volver a iniciarse reclama lo que quedó en vuelo antes de aceptar trabajo nuevo.

🗄️ Cola duradera de verdad

SQLite en WAL, claim atómico, lease con heartbeat y drain al apagarse. Un kill -9 en medio de un job no deja el estado indefinido: nada queda running con un lease activo.

⏸️ Flujos con aprobación humana

Pipeline con estado por fase y por objetivo, definición congelada al crearlo, pausa para que hagas tu parte (/aprovar) y reanudación selectiva con /refazer.

🧩 Nuevo dominio sin código

Una skill es un prompt + una entrada en el registry. Un flujo es un repo con flow.json + prompts/. Ninguno de los dos requiere una línea de TypeScript en el bot.

Cómo funciona

Desde el comando en el chat hasta el archivo entregado

El gateway valida quién habla (allowlist de chat), el comando se convierte en un job en la cola correcta, un worker reclama el job con un lease, el agente lo ejecuta y el notificador devuelve el resultado en el chat.

comando en Telegram→ allowlist + parse→ job en la cola (SQLite)→ el worker se queja (lease)→ el agente ejecuta→ artefacto + aviso en el chat

Cinco colas, concurrencias diferentes

io (10) · cpu (1) · texto (2) · render (1) · navegador (1). Un render pesado no bloquea la cola de texto.

Skill × flujo

Skill = una etapa, sin estado: es aceptable empezar de cero. Flujo = varias fases con estado, cuando sería absurdo descartar el trabajo parcial.

Inicio en orden

Migrations → raíz de medios → recuperación de leases vencidos → solo entonces workers y bot. Este orden permite recuperar el proceso tras una caída.

Requisitos previos

Qué debe estar en su lugar

Node con TypeScript, un bot creado en Telegram y un .env con las cinco variables obligatorias. Si falta alguna, el arranque falla de forma clara y temprana, antes de iniciar cualquier worker.

Node + dependencias

Instala y ejecuta las pruebas antes de subir cualquier cosa.

# en la raíz del repo
npm install
npm test

Bot en Telegram

Crea el bot en @BotFather y guarda el token. El valor real nunca va al git.

# .env (modo 600, fuera de git)
BOT_TOKEN=…
ALLOWED_CHAT_IDS=123,456

Estado en disco

La ruta de la base de datos de la cola, la raíz del estado y el archivo de registro — las otras tres obligatorias.

QUEUE_DB=./inemaccbot.db
STATE_DIR=./estado
LOG_FILE=./inemaccbot.log
Guía de uso · paso a paso

Iniciar el servicio y operarlo desde el chat

Todos los comandos de abajo son reales: los de shell se ejecutan en el repo, los que empiezan con barra los escribes en Telegram.

1

Instala, prueba y compila

El registry de skills y flujos se valida al iniciar: una entrada inválida hace que el servicio se detenga a propósito.

npm install
npm test          # vitest run
npm run typecheck  # tsc --noEmit
npm run build      # tsc -> dist/index.js
2

Inicia el proceso

En producción mediante systemd, con el .env en el mismo directorio de trabajo (deploy/inemaccbot.service).

node dist/index.js                       # directo
systemctl --user start inemaccbot       # como servicio
3

Confirma que estás activo

En el chat autorizado. /ajuda lista todo; /skills e /fluxos son los dos catálogos.

/ping
/ajuda
/skills   # una etapa, sin estado
/fluxos   # varias fases, con estado
4

Ejecuta una skill

El formato es <skill>: <entrada> [| campo]*. Campos genéricos: livesN (destino), modelo=haiku, esforco=high.

transcrever: https://…                  # audio → texto
explicativo: <assunto> | vertical       # video 9:16
imagem: uma raposa ruiva na neve | ratio=16:9
5

Ejecuta un flujo: primero siempre en modo sombra

| sombra imprime fase × objetivo × cola × tarea y no pone nada en cola. Es la forma barata de descubrir que ibas a enviar por error a 12 públicos.

/promoavatar <assunto> | sombra
/promoavatar <assunto> --alvo=jovens
/promoavatar <assunto> | alvos=mulheres | legenda
6

Sigue y libera el portón

/status es el panel de los flujos ABIERTOS; /completos lista los que terminaron. A#9, a#9, A9 e a9 son lo mismo — solo números (13) siempre es job.

/status            # flujos abiertos
/status A#9        # detalle fase × objetivo
/fila              # en ejecución, pendientes, errores en 24h
/pronto A#9        # = /aprovar — abre la puerta
7

Corrige lo que falló, sin rehacerlo todo

/refazer en un flujo, retoma desde la fase que falló; en un objetivo único, vuelve a procesar ese objetivo. /cancelar quita de la lista sin borrar nada de lo que ya se creó fuera.

/refazer A#9 mulheres   # solo el público que falló
/cancelar A#9           # desaparece de /status; el flujo sigue existiendo
/furar j13              # pone un job pendiente al frente
8

Libera espacio con una simulación en seco

Sin la palabra confirmar al final, solo muestra lo que saldría y cuánto libera. El bot solo toca lo que ÉL publicó dentro de ~/projetos/output.

/espaco                  # disco por área (bot × skills)
/limpar A#8              # dry-run
/limpar A#8 confirmar    # ejecuta
9

Antes de reiniciar, revisa la cola

claude saiu com código 143 é 128 + 15 = SIGTERM: el job fue terminado por un reinicio del servicio, no por un error del agente. Un render de reel tarda 10–15 min — dos reinicios seguidos agotan los dos intentos del mismo job.

sqlite3 inemaccbot.db \
  "select id,fila,tarefa,status,flow_ref from jobs
   where status in ('queued','running');"
# vacío → reinicia cuando quieras. Con un render en curso → espera.
Dominio nuevo

Agregar trabajo sin tocar el bot

Esta es la prueba del diseño: un dominio nuevo no debe exigir líneas de código en el bot. Elige entre skill y flujo según el criterio del trabajo parcial.

Una SKILL — una etapa, sin estado

Aplica cuando «volver a ejecutarlo desde cero» es aceptable. Escribe el prompt, decláralo en el registry y ejecuta las pruebas. Los campos declarados deben usarse en el prompt, y las variables del prompt deben declararse; hay pruebas para ambos casos.

# 1. prompts/minhaskill.md — usa {{input}} y {{saida}},
# y la última línea del agente es RESULT: <caminho>
# 2. config/skills.json
{ "command": "minhaskill", "fila": "texto", "kind": "agent",
  "prompt": "prompts/minhaskill.md", "artefato_exts": ["txt"],
  "max_tentativas": 2, "timeout_segundos": 3600 }
# 3. npm test

Un FLUJO: varias fases, con estado

Aplica cuando hay trabajo parcial que sería absurdo descartar. Gana /status, /refazer selectivo, reanudación y definición congelada. El dominio dice PARA QUIÉN; el bot sabe DÓNDE — nunca pongas la ruta en flow.json.

# 1. repo ~/projetos/<nome> con flow.json + prompts/
# 2. flow.json: nombre, prefijo (la P de P#16), versao_def,
# objetivos y fases (id, alcance, cola, tipo, tarea…)
# 3. config/fluxos.json: { command, repo, descricao, exemplo }
# 4. comprueba sin gastar nada:
/<fluxo> <assunto> | sombra

Todo dominio que entra en el catálogo responde ayuda — no por disciplina, sino por diseño: quien entiende, escribe (HELP.md en el flujo, <prompt>.help.md en la skill) y, si no se escribió, la ayuda se deriva del mismo registro que el bot usa para ejecutar. Una prueba recorre ambos catálogos y falla si algún dominio no responde con ayuda utilizable.

promoavatar (A#)· promoavatar3 (C#)
Estado

Qué está listo y qué no existe a propósito

Etapas 0 a 5 completadas, más los flujos de dominio. La v1 (inemaccvbot, mkivideos, mkitexto) está desactivado.

Listo
Cola duraderaSQLite en WAL, lease con heartbeat, drain, claim atómico, recuperación al iniciar.
Listo
Gateway de TelegramLista de permitidos del chat, análisis puro de comandos (sin grammy), límite de mensajes y notificación cuando termina un job.
Listo
Skills como agentetranscribir · doblar · explicativo · curso · demo · reel · reelinematds · historia · imagen.
Listo
Motor de flujosEstado por fase y objetivo, definición congelada, puerta de control humana y reanudación.
Abierto
Salir de TelegramWhatsApp, correo electrónico o chatbot: la integración del gateway ya existe; lo que bloquea es chat_id ser INTEGER. Recomendación en análisis: no reemplazar, agregar.
Abierto
Imagen y enlace como materialAceptar imágenes y enlaces como entrada de un flujo — análisis escrito, decisión no tomada.
Afuera
Qué no existe a propósitoBarrera entre fases, preempción de jobs, límite global de agentes, multiusuario — cada uno con el detonante documentado para reconsiderarlo.