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

@cogitator-ai/channels

v0.2.1

Published

Messaging channel connectors and Gateway for Cogitator AI agents

Readme

@cogitator-ai/channels

Connect Cogitator agents to messaging platforms. Gateway routes messages across channels, handles sessions, streaming, media, and middleware.

Install

pnpm add @cogitator-ai/channels

# Then install the adapters you need:
pnpm add grammy                    # Telegram
pnpm add discord.js                # Discord
pnpm add @slack/bolt               # Slack
pnpm add @whiskeysockets/baileys   # WhatsApp
pnpm add ws                        # WebChat

Quick Start

import { Cogitator, Agent } from '@cogitator-ai/core';
import { Gateway, telegramChannel } from '@cogitator-ai/channels';

const cogitator = new Cogitator({ llm: { defaultModel: 'google/gemini-2.5-flash' } });
const agent = new Agent({ name: 'bot', instructions: 'You are a helpful assistant.' });

const gateway = new Gateway({
  cogitator,
  agent,
  channels: [telegramChannel({ token: process.env.TG_TOKEN! })],
  stream: { flushInterval: 500, minChunkSize: 20 },
});

await gateway.start();

Channels

Telegram

Get your token: Open Telegram → search @BotFather → send /newbot → follow prompts → copy the token.

import { telegramChannel } from '@cogitator-ai/channels';

telegramChannel({ token: process.env.TG_TOKEN! });

// Webhook mode (production):
telegramChannel({
  token: process.env.TG_TOKEN!,
  webhook: { url: 'https://example.com/telegram', port: 8443 },
});

Supports: text, photos (→ vision), voice (→ STT), documents, streaming via editText, emoji reactions, 4096 char limit.

Discord

Get your token: Discord Developer Portal → New Application → Bot → Reset Token → copy it. Enable "Message Content Intent" under Privileged Gateway Intents. Invite via OAuth2 URL Generator with bot scope + Send Messages, Read Message History, Add Reactions permissions.

import { discordChannel } from '@cogitator-ai/channels';

discordChannel({
  token: process.env.DISCORD_TOKEN!,
  mentionOnly: true, // only respond when @mentioned in servers
});

Supports: DMs, server messages, streaming, reactions, auto-chunking (2000 char limit, code-block aware).

Slack

Get your tokens (3 total):

  1. api.slack.com/apps → Create New App → From scratch
  2. Socket Mode → enable → generate App Token (xapp-...) → save as SLACK_APP_TOKEN
  3. OAuth & Permissions → add scopes: chat:write, app_mentions:read, im:history, im:read, im:write
  4. Event Subscriptions → enable → add: message.im, app_mention
  5. Install App → copy Bot Token (xoxb-...) → save as SLACK_BOT_TOKEN
  6. Basic Information → copy Signing Secret → save as SLACK_SIGNING_SECRET
import { slackChannel } from '@cogitator-ai/channels';

slackChannel({
  token: process.env.SLACK_BOT_TOKEN!,
  signingSecret: process.env.SLACK_SIGNING_SECRET!,
  appToken: process.env.SLACK_APP_TOKEN!,
});

Supports: DMs, channel messages (via @mention), Socket Mode (no public URL), streaming via chat.update.

WhatsApp

No bot API — connects as a linked device to your WhatsApp account (like WhatsApp Web).

import { whatsappChannel } from '@cogitator-ai/channels';

whatsappChannel({
  sessionPath: '.cogitator/whatsapp-session',
  printQr: true,
});

First run: QR code prints to terminal → scan from WhatsApp → Settings → Linked Devices. Session is saved for future restarts.

Supports: 1-on-1 and group chats, typing indicators, auto-reconnect, WhatsApp-native markdown. No streaming (WhatsApp doesn't support editing).

WebChat

WebSocket server for custom UIs, CLI tools, or any client.

import { webchatChannel } from '@cogitator-ai/channels';

webchatChannel({
  port: 3100,
  path: '/ws',
  auth: (token) => token === process.env.WEBCHAT_SECRET,
});

Connect: ws://localhost:3100/ws?token=YOUR_SECRET. Send {"text": "Hello!"}, receive {"type": "message", "id": "...", "text": "..."}.

Supports: streaming (via edit messages), typing indicators, token auth, no message limit.

Platform Comparison

| Feature | Telegram | Discord | Slack | WhatsApp | WebChat | | ------------------ | ------------ | ------- | --------- | -------- | --------- | | Streaming (edit) | ✅ | ✅ | ✅ | ❌ | ✅ | | Reactions | ✅ | ✅ | ❌ | ❌ | ❌ | | Typing indicator | ✅ | ✅ | ⚠️ | ✅ | ✅ | | Photos → vision | ✅ | ❌ | ❌ | ❌ | ❌ | | Voice → STT | ✅ | ❌ | ❌ | ❌ | ❌ | | Max message length | 4096 | 2000 | ~4000 | ~65536 | unlimited | | Public URL needed | webhook only | no | HTTP only | no | no |

Gateway

Routes incoming messages to your agent. Handles:

  • Session management (per-user, per-channel)
  • Streaming with StreamBuffer (chunked message editing)
  • Typing keep-alive (re-sends typing indicator every 4s)
  • Media processing (images → vision, voice → STT)
  • Middleware pipeline
  • Platform-specific markdown conversion
  • Status reactions, debouncing, envelope formatting, queue modes

Status Reactions

Emoji progress indicators on the user's message:

const gateway = new Gateway({
  // ...
  reactions: {
    enabled: true,
    emojis: { queued: '👀', thinking: '🤔', tool: '🔥', done: '👍', error: '😱' },
    debounceMs: 700,
    stallSoftMs: 10000,
    stallHardMs: 30000,
  },
});

Inbound Debouncing

Merge rapid messages into a single LLM call:

const gateway = new Gateway({
  // ...
  debounce: {
    enabled: true,
    delayMs: 1500,
    byChannel: { discord: 2000 },
  },
});

Envelope Formatting

Wrap messages with context so the LLM knows who's talking, on which platform, and when:

[14:23 MSK | telegram | @alice | DM | +2m30s] Hello world

const gateway = new Gateway({
  // ...
  envelope: {
    enabled: true,
    includeTimestamp: true,
    includeElapsed: true,
    includeSender: true,
    includeChannel: true,
    includeChatType: true,
    timezone: 'Europe/Moscow',
  },
});

Queue Modes

Control concurrent message handling per user:

const gateway = new Gateway({
  // ...
  queueMode: 'sequential', // 'parallel' | 'sequential' | 'interrupt' | 'collect'
});
  • parallel — default, all messages processed immediately
  • sequential — FIFO per thread, wait for current to finish
  • interrupt — abort current, start new message
  • collect — buffer during processing, merge on idle

Formatting Pipeline

Platform-specific markdown conversion applied automatically:

  • Telegram# headers → bold, preserves code blocks
  • Discord — native Markdown, auto-chunks at 2000 chars with code block integrity
  • Slack**bold***bold*, headers → bold
  • WhatsApp**bold***bold*, ~~strike~~~strike~

Middleware

import { rateLimit, ownerCommands, DmPolicyMiddleware, autoExtract } from '@cogitator-ai/channels';

const gateway = new Gateway({
  // ...
  middleware: [
    rateLimit({ maxPerMinute: 30 }),
    ownerCommands({
      ownerIds: { telegram: '123' },
      commandLevels: { status: 'authorized', block: 'owner', help: 'public' },
    }),
    new DmPolicyMiddleware({
      mode: 'pairing',
      ownerIds: { telegram: '123' },
      storePath: '~/.cogitator/dm-allowlist.json',
      groupPolicy: 'open',
    }),
    autoExtract({ extractor }),
  ],
});

DM Policy Modes

  • open — anyone can DM the bot
  • allowlist — only pre-approved users
  • pairing — unknown users get a code, owner approves via /pair CODE
  • disabled — DMs blocked entirely

Command Authorization Levels

Commands have 3 access levels: owner, authorized, public. Owner-only commands (like /block, /model) can't be run by regular users even if they're approved.

Lifecycle Hooks

Subscribe to events across the message lifecycle:

import { createHookRegistry } from '@cogitator-ai/channels';

const hooks = createHookRegistry();
hooks.on('message:received', (e) => console.log('New message:', e));
hooks.on('agent:after_run', (e) => console.log('Response:', e));
hooks.on('agent:error', (e) => console.error('Agent failed:', e));

const gateway = new Gateway({ /* ... */ hooks });

Available hooks: message:received, message:sending, message:sent, agent:before_run, agent:after_run, agent:error, session:created, session:compacted, stream:started, stream:finished.

Errors in one handler don't affect others.

Media & STT

Voice messages are transcribed automatically. STT provider is selected by available env vars (highest priority first):

  1. Deepgram — set DEEPGRAM_API_KEY (nova-3 model, fast and accurate)
  2. Groq — set GROQ_API_KEY (free tier available)
  3. OpenAI — set OPENAI_API_KEY
  4. Local Whisper — downloads ~75MB model on first use, runs offline (no API key needed)

Images are passed to the LLM as vision input if the model supports it.

Scheduler

import { HeartbeatScheduler, SimpleTimerStore } from '@cogitator-ai/channels';

const store = new SimpleTimerStore({ persistPath: '.cogitator/timers.json' });
const scheduler = new HeartbeatScheduler(store, {
  onFire: (msg) => gateway.injectMessage(msg),
  pollInterval: 30_000,
  maxRetries: 5,
  onRunComplete: (entry, status, error, durationMs) => {
    console.log(`Job ${entry.id}: ${status} (${durationMs}ms)`);
  },
});
scheduler.start();

Schedule types: cron (recurring), recurring (interval), fixed (one-shot). Error tracking with auto-backoff.

await scheduler.listJobs();
await scheduler.enableJob(id);
await scheduler.disableJob(id);
await scheduler.cancelJob(id);

Environment Variables

# LLM Provider
GOOGLE_API_KEY=...           # or ANTHROPIC_API_KEY, OPENAI_API_KEY

# Telegram
TG_TOKEN=7204891735:AAHr...

# Discord
DISCORD_TOKEN=MTI...

# Slack (3 tokens)
SLACK_BOT_TOKEN=xoxb-...
SLACK_SIGNING_SECRET=...
SLACK_APP_TOKEN=xapp-...

# WhatsApp — no token, uses QR pairing

# WebChat
WEBCHAT_SECRET=your-secret

# STT (optional, for voice messages — pick one)
DEEPGRAM_API_KEY=...         # highest priority
GROQ_API_KEY=...             # free tier
OPENAI_API_KEY=...           # fallback