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

@relatalabs/debatidor-agent

v0.6.2

Published

Debatidor Agent CLI: puente entre salas Debatidor y tu sistema de archivos local.

Downloads

991

Readme

Debatidor Agent

Terminal multifacética de Debatidor/RelataLabs: tu consola conectada a salas multi-modelo donde el "cerebro" puede ser un modelo web vía la extensión o el PAL por API. El bridge web soporta hoy Qwen Web y ChatGPT Web; otros hosts (Claude Web, DeepSeek, Kimi, …) se incorporan mediante sus adapters. Desde 0.5.6, el mismo runner local también sirve como puente para que clientes MCP autorizados operen directamente el proyecto mediante debatidor-back, sin DOM.

El comando principal es debatidor. debatidor-agent se conserva como alias de compatibilidad para instalaciones y scripts existentes.

Requisitos

  • Node.js 22+

Inicio rápido

# 1) Autenticarse (una sola vez; device flow por navegador)
debatidor auth login

# 2) Entrar al REPL desde tu proyecto
cd mi-proyecto
debatidor

Producción es el default (wss://api.debatidor.com/agent). Para desarrollo local: debatidor --local.

La cabecera del REPL muestra el logo pixelado de Debatidor, la versión efectiva del paquete, host local, versión de Node y cwd. debatidor --version imprime únicamente la versión del CLI.

Dentro del REPL

| Comando | Qué hace | |---|---| | <texto> | Habla en la sala (persistido como intervención humana). Un paste con varias líneas se envía como una sola intervención, preservando los saltos de línea internos | | /mode | Muestra el cerebro actual | | /mode web | El cerebro es el modelo de la pestaña conectada (Qwen web, ChatGPT web, …). Tu mensaje viaja con el contrato de herramientas inyectado automáticamente | | /mode api | El cerebro es el PAL (participantes API de la sala); sin DOM | | /mode both | Ambos a la vez (default) | | /host qwen | Dirige los mensajes web a Qwen (conn_dom_qwen) | | /host chatgpt | Dirige los mensajes web a ChatGPT (conn_dom_openai) | | /host all | Broadcast a todos los hosts web habilitados | | /send tools | (Re)inyecta el contrato de herramientas al modelo web, sin persistir nada | | /permissions manual\|auto\|plan | Controla la ejecución de shell.run | | /debate <id> | Vincula la sesión a una sala (vacío = desvincular) | | /status | Conexión, sala, cerebro, host, cwd, streams | | /quit | Salir (o Ctrl+C dos veces) |

Al escribir /, el REPL muestra sugerencias filtradas. El ranking favorece coincidencias exactas y de prefijo; también considera aliases y descripción. Por ejemplo, /per prioriza /permissions, /hos prioriza /host y /send t prioriza /send tools. Tab completa usando el mismo registro de comandos que alimenta /help, por lo que ayuda, autocomplete y ejecución no mantienen listas duplicadas.

La salida del agente vive en el transcript por encima del compositor. Si llega un evento mientras estás escribiendo, el CLI conserva el borrador y la posición del cursor, imprime el evento y restaura la entrada. Los snapshots DOM parciales no se imprimen por defecto; para depurar streaming crudo se puede arrancar con DEBATIDOR_STREAM_DEBUG=1. Durante una confirmación manual de shell.run (Y/n), la salida asíncrona se difiere hasta que respondas para no partir el prompt.

El host seleccionado persiste durante la sesión del REPL. Si cierras Qwen y abres ChatGPT, cambia explícitamente con /host chatgpt antes de enviar la siguiente tarea.

Herramientas (tool calling vía DOM→CLI)

En modo web, el modelo web puede operar tu proyecto emitiendo bloques:

{"tool":"fs.list","path":"src"}
{"tool":"fs.read","path":"src/app.module.ts"}
{"tool":"fs.write","path":"docs/nota.md","content":"texto"}
{"tool":"shell.run","command":"git status"}

El backend las enruta a ESTE CLI, que las ejecuta confinado al cwd actual (sin rutas absolutas, sin .., con .debatidor/protected-files.json para exclusiones) y devuelve el resultado al modelo para que continúe. Guardas: watchdog por operación (DOM_TOOL_TIMEOUT_MS, 15 s) y tope de cadena autónoma configurable mediante DOM_TOOL_MAX_HOPS.

Este camino sigue existiendo para conversaciones web controladas por la extensión.

Modo puente headless (sin REPL)

debatidor connect --remote                  # producción, filesystem habilitado
debatidor connect --remote --shell-auto     # además habilita shell.run
debatidor connect --local                   # backend local :3001

El runner atiende operaciones lead.* del backend para el mismo usuario/workspace. Además de su uso como worker desatendido, desde 0.5.6 este es el extremo local del flujo MCP nativo:

ChatGPT / Claude + Debatidor MCP
            |
       tool MCP
            |
      debatidor-back
            |
        /agent WS
            |
        debatidor
            |
      repo / filesystem
            |
     resultado al mismo chat

Cuando el trabajo se inicia desde un cliente MCP no se necesita la extensión DOM.

Shell headless

Por seguridad, shell.run está deshabilitada por defecto en connect. Con:

debatidor connect --remote

fs.list, fs.read y fs.write siguen disponibles, pero lead.execute_command responde denied_headless_shell_disabled.

Para permitir comandos no interactivos de forma consciente:

debatidor connect --remote --shell-auto

Solo entonces el agent anuncia la capability shell.run. El backend/MCP sigue tratando shell como una acción potencialmente destructiva y no idempotente. El cwd opcional de un comando shell también debe permanecer dentro del proyecto.

Confinamiento de filesystem

Las operaciones de archivo se resuelven respecto del cwd con el que arrancó el agent:

  • no se aceptan rutas absolutas Unix ni Windows;
  • no se permite traversal con .., usando / o \\;
  • .debatidor/protected-files.json puede definir exclusiones adicionales;
  • el backend valida paths antes de enviarlos al runner y fs-guard vuelve a validarlos localmente.

Memoria y proyectos de contexto

La memoria guardada en Debatidor es la fuente autoritativa. El CLI puede generar una copia local explícita para un proyecto, usando la sesión de debatidor auth login; no necesita claves BYOK. login, connect y el REPL no generan ni importan MEMORY.md automáticamente.

# Leer la memoria privada propia, sin crear archivos locales
debatidor memory preview --scope user

# Guardar o actualizar una proyección administrada en este proyecto
debatidor memory sync --scope workspace --root ./mi-proyecto --output MEMORY.md

# Seleccionar fuentes y tipos concretos; ambas opciones son repetibles
debatidor memory export --scope user --source <source-id> --kind FACT --kind DECISION

# Retirar solamente la proyección local, conservando la memoria en Debatidor
debatidor memory remove --root ./mi-proyecto --output MEMORY.md

El ámbito predeterminado es user: únicamente fuentes privadas propias. workspace selecciona fuentes compartidas. Un proyecto de contexto es una colección privada de fuentes que ya puedes leer; agruparlas no concede acceso a fuentes privadas de otra persona ni a otro workspace.

debatidor memory projects create --name "Mi proyecto"
debatidor memory projects list
debatidor memory projects sources <project-id> --source <source-id> --source <otro-id>
debatidor memory projects show <project-id>
debatidor memory sync --scope project --project <project-id> --root ./mi-proyecto
debatidor memory projects sources <project-id> --clear
debatidor memory projects remove <project-id>

projects sources reemplaza la selección completa. Vaciarla requiere --clear. projects remove elimina la colección y sus snapshots administrados, conservando las fuentes y el historial. Los identificadores de fuentes aparecen en la procedencia exportada y en el catálogo de Memoria del Hub.

preview imprime el Markdown completo seleccionado. export y sync guardan ese mismo contenido junto a MEMORY.md.debatidor.json, que contiene el hash, el ámbito y la identidad del usuario/workspace, sin credenciales. La raíz local es el directorio actual salvo --root (--cwd es alias); --output siempre es relativo a esa raíz. Una regeneración sin cambios conserva los bytes y la fecha del archivo, aunque el snapshot remoto sea nuevo.

Cada sync usa la selección de esa invocación. Repite --scope, --project, --source y --kind cuando quieras conservar los mismos filtros; el CLI no los importa del archivo local ni de su sidecar. Si omites --source o --kind, se seleccionan todas las fuentes o tipos permitidos dentro del ámbito indicado.

Sin la opción de notas de usuario descrita abajo, no se sobrescriben ni eliminan archivos desconocidos o modificados localmente. Ante un conflicto, conserva tus notas y elige otra ruta de salida. Las rutas protegidas, enlaces simbólicos, junctions y archivos con hardlinks se rechazan. Cada archivo se publica mediante un temporal y rename; una interrupción entre el Markdown y su sidecar deja un conflicto que no se repara silenciosamente. Estas comprobaciones no constituyen un sandbox frente a un proceso hostil que cambie rutas concurrentemente.

Cada exportación descarga todas las páginas admitidas (hasta 10.000 entradas y 32 MiB de Markdown) y retira su snapshot remoto al terminar, también ante fallos. Un error de página o limpieza impide publicar una copia parcial. Si se pierde la respuesta al crear el snapshot, no se reintenta automáticamente: el snapshot cuya identidad no se recibió caduca según el TTL del servidor. Borrar o revocar fuentes en Debatidor no puede retirar copias que ya descargaste; cada sync vuelve a consultar los permisos actuales.

El servidor procede de la sesión guardada. --api <origen HTTPS> o --local permiten seleccionar otro, pero una credencial guardada para otro origen se rechaza; ejecuta debatidor auth login --api <origen> para autenticarte allí. Se admite HTTP únicamente en localhost. No se siguen redirecciones con credenciales ni se ejecuta un login implícito desde estos comandos.

Notas locales editables (opcional, desde 0.5.10)

Para agregar una sección editable al final de la proyección, elige expresamente --user-notes en memory export o memory sync:

debatidor memory sync --scope project --project <project-id> --root ./mi-proyecto --user-notes

El flag crea el formato nuevo o convierte una proyección anterior intacta. No adopta archivos ajenos ni convierte ediciones de la parte exportada en notas. Repite --user-notes y los filtros de selección en cada sincronización posterior; omitir el flag en un archivo ya convertido provoca un conflicto. Los archivos previos siguen con su formato y sidecar v1 mientras no optes por la conversión.

Edita únicamente entre los dos delimitadores finales del archivo:

<!-- debatidor:user-notes:v1:start -->
Estas notas son mías y se conservan al sincronizar.
<!-- debatidor:user-notes:v1:end -->

La DB es autoritativa para la parte exportada. sync conserva los bytes exactos de tus notas, incluidos Unicode, espacios y saltos de línea. Editar sólo las notas no obliga a reescribir el archivo ni el sidecar si la DB no cambió. Las notas no se envían al Hub, no se importan y no aparecen en los resúmenes del comando. memory preview sigue mostrando únicamente el export remoto. El CLI tampoco ejecuta acciones Git sobre ninguna de las dos secciones.

El sidecar v2 guarda el hash y longitud en bytes UTF-8 de la parte generada, su scope/usuario/workspace/revisión y el origen API sin credenciales. La sección se localiza por ese límite verificado y por el cierre al final del archivo; marcadores que aparezcan dentro del contenido de la DB se tratan como datos. Los dos textos exactos de delimitador están reservados y no se admiten dentro de las notas. Cambios fuera de la sección, marcadores alterados, metadata editada, UTF-8 inválido y cambios de API o identidad/scope se rechazan. Se mantienen todos los controles de rutas, enlaces, locks y publicación descritos arriba. Evita que el editor reformatee el archivo completo o cambie sus saltos de línea: también cambiaría los bytes de la parte autoritativa y produciría un conflicto.

La parte generada admite hasta 32 MiB y las notas hasta 1 MiB, más los delimitadores. Estos límites cuentan bytes, no caracteres ni índices UTF-16. Para retirar una proyección con notas no vacías, cópialas antes si quieres conservarlas y autoriza explícitamente su eliminación local:

debatidor memory remove --root ./mi-proyecto --discard-user-notes

Sin --discard-user-notes, remove preserva las notas no vacías y devuelve un conflicto. Una sección vacía y las proyecciones v1 mantienen el borrado local habitual. Este comando no requiere credenciales ni borra memoria remota.

Sesiones y conocimiento explícito (desde 0.5.11)

Estos comandos consumen la misma API de Contexto que el Hub y MCP. Requieren un backend con las rutas de sesiones y conocimiento P11; la versión del CLI no demuestra que ese backend ya esté desplegado. Usan la sesión guardada por debatidor auth login; no aceptan --token, no abren otro login ni usan BYOK. No capturan conversaciones, archivos, el REPL o notas de MEMORY.md automáticamente.

debatidor memory sessions create --root ./mi-proyecto --input session.json
debatidor memory sessions list --project <project-id> --limit 50
debatidor memory sessions show <session-id>
debatidor memory sessions append <session-id> --root ./mi-proyecto --input event.json
debatidor memory sessions events <session-id> --limit 50
debatidor memory sessions events <session-id> --limit 50 --cursor <nextCursor>
debatidor memory sessions close <session-id>
debatidor memory declarations create --root ./mi-proyecto --input declaration.json
debatidor memory declarations show <declaration-id>
debatidor memory origin show SESSION_EVENT <event-id> --revision 1
debatidor memory status

sessions show devuelve metadatos. sessions list y sessions events consultan una página por invocación, de 50 registros por defecto y hasta 100 con --limit. Continúa con nextCursor si no es null, conservando el proyecto seleccionado o el ID de sesión. events conserva el throughSequence fijado al abrir la primera página: los eventos posteriores quedan para una consulta nueva. Una respuesta inválida, un cambio de sesión/fuente/límite o un error de acceso impide imprimir esa página. El CLI no convierte páginas incompletas en éxitos. --project en list es opcional; sin él lista las sesiones privadas propias.

Para create y append, prepara un JSON UTF-8 y selecciona su ruta relativa con --input dentro de un --root explícito (--cwd es alias). La lectura usa los controles del proyector: rechaza escapes de raíz, rutas protegidas, symlinks, junctions, hardlinks, cambios de identidad de archivo y UTF-8 inválido. No crea archivos ni directorios. El JSON completo admite hasta 256 KiB, incluidos los escapes y la procedencia; los límites de contenido siguientes son adicionales. No se aceptan campos desconocidos ni credenciales dentro del objeto JSON.

session.json:

{
  "label": "Revisión del proyecto",
  "projectId": "<project-id>",
  "clientSessionId": "revision-proyecto-001"
}

label es obligatorio (hasta 120 unidades UTF-16). projectId y clientSessionId son opcionales. El servidor crea una fuente privada propia y, si seleccionaste proyecto, la vincula a esa colección. La respuesta contiene id de sesión y sourceId; usa esos IDs en las siguientes operaciones.

event.json:

{
  "clientEventId": "revision-evento-001",
  "role": "ASSISTANT",
  "content": "Se propone revisar la decisión antes de aprobarla."
}

Los tres campos son obligatorios. role admite HUMAN, ASSISTANT, TOOL o SYSTEM; declarar un rol no activa herramientas ni cambia permisos. El texto se conserva exactamente, con hasta 32768 bytes UTF-8. append devuelve el evento aceptado, su secuencia y materialization: "queued"; esto acredita el guardado raw y la admisión de trabajo, no que ya terminó su materialización. close impide añadir nuevos eventos y conserva el historial.

declaration.json:

{
  "clientDeclarationId": "decision-001",
  "sourceId": "<source-id-de-la-sesion>",
  "kind": "DECISION",
  "content": "La revisión es necesaria antes de aprobar.",
  "origins": [
    {
      "rawType": "SESSION_EVENT",
      "rawId": "<event-id>",
      "revision": 1,
      "startUtf16": 0,
      "endUtf16": 10
    }
  ]
}

Todos estos campos son obligatorios. kind admite FACT, DECISION y CONCLUSION; la declaración sigue siendo una afirmación explícita del usuario, sin inferencia automática de ese significado. content admite 24000 bytes UTF-8. Hay entre 1 y 32 orígenes distintos (MESSAGE o SESSION_EVENT), de la misma fuente seleccionada. Cada cita usa una revisión de 1 a 2147483647 y un intervalo no vacío [startUtf16, endUtf16) del texto raw completo. Los offsets cuentan unidades UTF-16, no bytes ni caracteres visibles; el servidor comprueba que no corten pares sustitutos y que la revisión siga vigente y sea accesible. Usa origin show para consultar el texto completo y elegir los límites exactos.

Los IDs de cliente de eventos y declaraciones son obligatorios para reconocer una repetición explícita. Reutilizar el mismo ID con otro contenido genera conflicto. Cada comando envía la mutación una sola vez, incluso si pierde la respuesta: el error no prueba que el servidor haya descartado la operación. Puedes comprobar el estado o repetir deliberadamente la misma solicitud y su ID; nunca se reintenta automáticamente.

events, declarations show y origin show imprimen contenido únicamente por esas invocaciones. origin show verifica tipo/ID/revisión y SHA-256 del contenido completo (hasta 1 MiB), también para revisiones históricas disponibles. El estado declarado puede ser current, stale o forgotten: olvidar memoria derivada no borra el historial raw original. memory status imprime métricas agregadas del índice y del pipeline de conocimiento, incluidas colas, resúmenes obsoletos y pendingMessageHydration de mensajes de escritores anteriores pendientes de hidratar. Esas métricas no implican que una cola vacía contenga conocimiento completo ni que todas las declaraciones sean correctas.

Las respuestas JSON sólo incluyen los campos reconocidos; errores remotos y credenciales no se imprimen. Cada página/respuesta tiene un máximo de 24 MiB de transferencia JSON. El export conserva la procedencia canónica y valida origins y derivation cuando existen (verbatim, extractive, declared, pipeline 1), manteniendo compatibilidad con entradas anteriores sin esos campos. Los spans vacíos de un resumen representan entradas consideradas sin cita. La proyección y las notas locales v1/v2 conservan su comportamiento anterior.

Desarrollo

npm test          # node --test
node src/cli.js   # desde el repo

Media Rail (fs.get / asset.stream)

  • lead.get_file: lectura binaria inline (base64, tope DEBATIDOR_ASSET_INLINE_MAX_BYTES, default 8 MiB, máximo 32 MiB) con MIME detectado por magic bytes y dimensiones de imagen (png/jpeg/gif/webp/bmp). metadataOnly devuelve tamaño, sha256 y tipo sin transferir bytes; stream emite agent.file_chunk (DEBATIDOR_ASSET_STREAM_CHUNK_BYTES, default 256 KiB) con back-pressure sobre el WebSocket.
  • asset.begin/chunk/commit/abort se encola por uploadId: el Hub puede mantener varios chunks en vuelo (antes cualquier solapamiento respondía asset_upload_busy). El tamaño de chunk es configurable en begin (chunkSize, 4096–65536 bytes, default 16384, env DEBATIDOR_ASSET_CHUNK_BYTES) para hosts cuyo canal de I/O impone un límite de mensaje pequeño; el agente recorta el valor solicitado a ese rango y lo devuelve. Cada chunk se decodifica desde base64 (default) o hex.
  • Ambos modos (connect headless y chat interactivo) comparten src/lead-file-ops.js, por lo que fs.put, asset.* y fs.get se comportan igual en los dos.
  • Los bytes nunca se re-encodean ni se recomprimen en ninguna dirección.