{"_id":"@cogitator-ai/channels","_rev":"4-90938adf5e4d76e7c20e39e3cd470a75","name":"@cogitator-ai/channels","dist-tags":{"latest":"0.2.5"},"versions":{"0.2.1":{"name":"@cogitator-ai/channels","version":"0.2.1","license":"MIT","_id":"@cogitator-ai/channels@0.2.1","maintainers":[{"name":"el1fe","email":"piuro.pavel@gmail.com"}],"homepage":"https://github.com/cogitator-ai/Cogitator-AI#readme","bugs":{"url":"https://github.com/cogitator-ai/Cogitator-AI/issues"},"dist":{"shasum":"4690bea8f79843ebbc4cbb5085de36ca4366b2f3","tarball":"https://registry.npmjs.org/@cogitator-ai/channels/-/channels-0.2.1.tgz","fileCount":138,"integrity":"sha512-ToDS0vGCPYOV5D62Lc0EZqaydM/7VomXTx6cN3fY99sfefA0pZdCGc1ztIQAaJrJRawFQ+qU7noYNqv4QyqDHw==","signatures":[{"sig":"MEQCIH8XakmSmon0yi811XBKOwoz0J7NCPxGitvH0LQj337AAiAQSlByWz+V+LyAfJLKwq5qL6NLh+4fOLoo1pMsfat7tQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":359315},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"065f1c25fc4837fbf561a31bd7bfec864705b249","scripts":{"dev":"tsc --watch","lint":"eslint src","test":"vitest run","build":"tsc","clean":"rm -rf dist","test:watch":"vitest"},"_npmUser":{"name":"el1fe","email":"piuro.pavel@gmail.com"},"repository":{"url":"git+https://github.com/cogitator-ai/Cogitator-AI.git","type":"git","directory":"packages/channels"},"_npmVersion":"10.9.0","description":"Messaging channel connectors and Gateway for Cogitator AI agents","directories":{},"_nodeVersion":"22.11.0","dependencies":{"nanoid":"^5.1.5","@cogitator-ai/core":"workspace:*","@cogitator-ai/types":"workspace:*","@cogitator-ai/config":"workspace:*","@cogitator-ai/memory":"workspace:*"},"publishConfig":{"access":"public","registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.18.2","vitest":"^4.0.18","@types/ws":"^8.18.1","typescript":"^5.3.0","@types/node":"^25.0.10"},"peerDependencies":{"ws":">=8.0.0","grammy":">=1.20.0","discord.js":">=14.0.0","@slack/bolt":">=3.0.0","ogg-opus-decoder":">=1.0.0","@cogitator-ai/mcp":"workspace:*","@cogitator-ai/rag":"workspace:*","@cogitator-ai/core":"workspace:*","@cogitator-ai/types":"workspace:*","@cogitator-ai/models":"workspace:*","@cogitator-ai/browser":"workspace:*","@whiskeysockets/baileys":">=6.0.0","@huggingface/transformers":">=3.0.0"},"peerDependenciesMeta":{"ws":{"optional":true},"grammy":{"optional":true},"discord.js":{"optional":true},"@slack/bolt":{"optional":true},"ogg-opus-decoder":{"optional":true},"@cogitator-ai/mcp":{"optional":true},"@cogitator-ai/rag":{"optional":true},"@cogitator-ai/models":{"optional":true},"@cogitator-ai/browser":{"optional":true},"@whiskeysockets/baileys":{"optional":true},"@huggingface/transformers":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/channels_0.2.1_1772552495268_0.39315953015703764","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@cogitator-ai/channels","version":"0.2.3","license":"MIT","_id":"@cogitator-ai/channels@0.2.3","maintainers":[{"name":"el1fe","email":"piuro.pavel@gmail.com"}],"homepage":"https://github.com/cogitator-ai/Cogitator-AI#readme","bugs":{"url":"https://github.com/cogitator-ai/Cogitator-AI/issues"},"dist":{"shasum":"ad3069b4f5675d987108865f554315f766c88820","tarball":"https://registry.npmjs.org/@cogitator-ai/channels/-/channels-0.2.3.tgz","fileCount":138,"integrity":"sha512-TSBCC7UkB6+Yta8nahEKrwLf0mfIF7eZOPMwB6OzJRAwUIoavKIml98osqfR3dSpRgGTeRbXzwEawz3AFBANcQ==","signatures":[{"sig":"MEUCIQDSuZqq1jej8Eh/lQI0eUoR3m3gCTlbLgtlue+tcSus7QIgZ8Dp2FQUU2yl82MYSPo+9tq46QU9e+pVbsYeUhofBE4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":359675},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"33b6a8cb29bfdd7d2255acfa240b2df5d558354e","scripts":{"dev":"tsc --watch","lint":"eslint src","test":"vitest run","build":"tsc","clean":"rm -rf dist","test:watch":"vitest"},"_npmUser":{"name":"el1fe","email":"piuro.pavel@gmail.com"},"repository":{"url":"git+https://github.com/cogitator-ai/Cogitator-AI.git","type":"git","directory":"packages/channels"},"_npmVersion":"10.9.0","description":"Messaging channel connectors and Gateway for Cogitator AI agents","directories":{},"_nodeVersion":"22.11.0","dependencies":{"nanoid":"^5.1.5","@cogitator-ai/core":"workspace:*","@cogitator-ai/types":"workspace:*","@cogitator-ai/config":"workspace:*","@cogitator-ai/memory":"workspace:*"},"publishConfig":{"access":"public","registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.18.2","vitest":"^4.0.18","@types/ws":"^8.18.1","typescript":"^5.3.0","@types/node":"^25.0.10"},"peerDependencies":{"ws":">=8.0.0","grammy":">=1.20.0","discord.js":">=14.0.0","@slack/bolt":">=3.0.0","ogg-opus-decoder":">=1.0.0","@cogitator-ai/mcp":"workspace:*","@cogitator-ai/rag":"workspace:*","@cogitator-ai/core":"workspace:*","@cogitator-ai/types":"workspace:*","@cogitator-ai/models":"workspace:*","@cogitator-ai/browser":"workspace:*","@whiskeysockets/baileys":">=6.0.0","@huggingface/transformers":">=3.0.0"},"peerDependenciesMeta":{"ws":{"optional":true},"grammy":{"optional":true},"discord.js":{"optional":true},"@slack/bolt":{"optional":true},"ogg-opus-decoder":{"optional":true},"@cogitator-ai/mcp":{"optional":true},"@cogitator-ai/rag":{"optional":true},"@cogitator-ai/models":{"optional":true},"@cogitator-ai/browser":{"optional":true},"@whiskeysockets/baileys":{"optional":true},"@huggingface/transformers":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/channels_0.2.3_1778881303111_0.19247213746948666","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@cogitator-ai/channels","version":"0.2.4","license":"MIT","_id":"@cogitator-ai/channels@0.2.4","maintainers":[{"name":"el1fe","email":"piuro.pavel@gmail.com"}],"homepage":"https://github.com/cogitator-ai/Cogitator-AI#readme","bugs":{"url":"https://github.com/cogitator-ai/Cogitator-AI/issues"},"dist":{"shasum":"6f1e90f27b688c806700e5b5426d096cd212408d","tarball":"https://registry.npmjs.org/@cogitator-ai/channels/-/channels-0.2.4.tgz","fileCount":139,"integrity":"sha512-9zyGV4DW+fZsAxEIblkR6QriIJYzKC60GbcIDA8fNLu97PYxAREw65ESBHcd1DYIyglZaZfUYTsLf29yT2kdrA==","signatures":[{"sig":"MEQCIBfRr6sNqRVNToE+R4HCtjH/ajDzwET/npWGx450L3i+AiAZrUEtRcLf9huSViaDbSNtnYRl1xjpLz7QD38qt9uxtg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":360701},"main":"./dist/index.js","type":"module","_from":"file:cogitator-ai-channels-0.2.4.tgz","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsc --watch","lint":"eslint src","test":"vitest run","build":"tsc","clean":"rm -rf dist","test:watch":"vitest"},"_npmUser":{"name":"el1fe","email":"piuro.pavel@gmail.com"},"_resolved":"/private/var/folders/20/4d95hdvj45j337gtqpbx3v1m0000gn/T/aca8565d6d8c235d043baa083a8b0989/cogitator-ai-channels-0.2.4.tgz","_integrity":"sha512-9zyGV4DW+fZsAxEIblkR6QriIJYzKC60GbcIDA8fNLu97PYxAREw65ESBHcd1DYIyglZaZfUYTsLf29yT2kdrA==","repository":{"url":"git+https://github.com/cogitator-ai/Cogitator-AI.git","type":"git","directory":"packages/channels"},"_npmVersion":"10.9.0","description":"Messaging channel connectors and Gateway for Cogitator AI agents","directories":{},"_nodeVersion":"22.11.0","dependencies":{"nanoid":"^5.1.5","@cogitator-ai/core":"0.19.3","@cogitator-ai/types":"0.22.2","@cogitator-ai/config":"0.5.5","@cogitator-ai/memory":"0.6.21"},"publishConfig":{"access":"public","registry":"https://npm.pkg.github.com"},"_hasShrinkwrap":false,"devDependencies":{"ws":"^8.18.2","vitest":"^4.0.18","@types/ws":"^8.18.1","typescript":"^5.3.0","@types/node":"^25.0.10"},"peerDependencies":{"ws":">=8.0.0","grammy":">=1.20.0","discord.js":">=14.0.0","@slack/bolt":">=3.0.0","ogg-opus-decoder":">=1.0.0","@cogitator-ai/mcp":"17.0.10","@cogitator-ai/rag":"0.1.9","@cogitator-ai/core":"0.19.3","@cogitator-ai/types":"0.22.2","@cogitator-ai/models":"17.1.8","@cogitator-ai/browser":"0.1.5","@whiskeysockets/baileys":">=6.0.0","@huggingface/transformers":">=3.0.0"},"peerDependenciesMeta":{"ws":{"optional":true},"grammy":{"optional":true},"discord.js":{"optional":true},"@slack/bolt":{"optional":true},"ogg-opus-decoder":{"optional":true},"@cogitator-ai/mcp":{"optional":true},"@cogitator-ai/rag":{"optional":true},"@cogitator-ai/models":{"optional":true},"@cogitator-ai/browser":{"optional":true},"@whiskeysockets/baileys":{"optional":true},"@huggingface/transformers":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/channels_0.2.4_1778882234616_0.24529387094766686","host":"s3://npm-registry-packages-npm-production"}},"0.2.5":{"name":"@cogitator-ai/channels","version":"0.2.5","description":"Messaging channel connectors and Gateway for Cogitator AI agents","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"dependencies":{"nanoid":"^5.1.5","@cogitator-ai/types":"0.22.3","@cogitator-ai/core":"0.19.4","@cogitator-ai/memory":"0.6.22","@cogitator-ai/config":"0.5.6"},"devDependencies":{"@types/node":"^25.0.10","@types/ws":"^8.18.1","typescript":"^5.3.0","vitest":"^4.0.18","ws":"^8.18.2"},"peerDependencies":{"grammy":">=1.20.0","discord.js":">=14.0.0","@slack/bolt":">=3.0.0","ws":">=8.0.0","@whiskeysockets/baileys":">=6.0.0","@huggingface/transformers":">=3.0.0","ogg-opus-decoder":">=1.0.0","@cogitator-ai/types":"0.22.3","@cogitator-ai/core":"0.19.4","@cogitator-ai/browser":"0.1.6","@cogitator-ai/mcp":"17.0.11","@cogitator-ai/rag":"0.1.10","@cogitator-ai/models":"17.1.9"},"peerDependenciesMeta":{"grammy":{"optional":true},"discord.js":{"optional":true},"@slack/bolt":{"optional":true},"ws":{"optional":true},"@whiskeysockets/baileys":{"optional":true},"@cogitator-ai/browser":{"optional":true},"@cogitator-ai/rag":{"optional":true},"@cogitator-ai/mcp":{"optional":true},"@cogitator-ai/models":{"optional":true},"@huggingface/transformers":{"optional":true},"ogg-opus-decoder":{"optional":true}},"engines":{"node":">=20.0.0"},"repository":{"type":"git","url":"git+https://github.com/cogitator-ai/Cogitator-AI.git","directory":"packages/channels"},"publishConfig":{"access":"public","registry":"https://npm.pkg.github.com"},"license":"MIT","scripts":{"build":"tsc","dev":"tsc --watch","test":"vitest run","test:watch":"vitest","lint":"eslint src","clean":"rm -rf dist"},"_id":"@cogitator-ai/channels@0.2.5","bugs":{"url":"https://github.com/cogitator-ai/Cogitator-AI/issues"},"homepage":"https://github.com/cogitator-ai/Cogitator-AI#readme","_integrity":"sha512-IewBjL7OEggsKs8hFcA9tPbU/3sFTsi7W6yyR6EIPtAKMuFnhP5JKfCPo5gqaCnCHL/JINuFWHTPkXbkEqCDMw==","_resolved":"/private/var/folders/20/4d95hdvj45j337gtqpbx3v1m0000gn/T/64edee00f6ba973b0412b4978bb1349b/cogitator-ai-channels-0.2.5.tgz","_from":"file:cogitator-ai-channels-0.2.5.tgz","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-IewBjL7OEggsKs8hFcA9tPbU/3sFTsi7W6yyR6EIPtAKMuFnhP5JKfCPo5gqaCnCHL/JINuFWHTPkXbkEqCDMw==","shasum":"1889411ef213f8eecd329c9fb534d0525366deb4","tarball":"https://registry.npmjs.org/@cogitator-ai/channels/-/channels-0.2.5.tgz","fileCount":139,"unpackedSize":360702,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD4cXKJ9oL1MJGvKTp9K7v6yADeb6YxtoHUfGSe9se3sAIgBLowOcu0bgV9ZH4uekXmz3FadAn/rGXGhXLjXvyKj+4="}]},"_npmUser":{"name":"el1fe","email":"piuro.pavel@gmail.com"},"directories":{},"maintainers":[{"name":"el1fe","email":"piuro.pavel@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/channels_0.2.5_1785059634954_0.9889848713741651"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-03T15:41:35.132Z","modified":"2026-07-26T09:53:55.276Z","0.2.1":"2026-03-03T15:41:35.440Z","0.2.3":"2026-05-15T21:41:43.334Z","0.2.4":"2026-05-15T21:57:14.825Z","0.2.5":"2026-07-26T09:53:55.107Z"},"bugs":{"url":"https://github.com/cogitator-ai/Cogitator-AI/issues"},"license":"MIT","homepage":"https://github.com/cogitator-ai/Cogitator-AI#readme","repository":{"type":"git","url":"git+https://github.com/cogitator-ai/Cogitator-AI.git","directory":"packages/channels"},"description":"Messaging channel connectors and Gateway for Cogitator AI agents","maintainers":[{"name":"el1fe","email":"piuro.pavel@gmail.com"}],"readme":"# @cogitator-ai/channels\n\nConnect Cogitator agents to messaging platforms. Gateway routes messages across channels, handles sessions, streaming, media, and middleware.\n\n## Install\n\n```bash\npnpm add @cogitator-ai/channels\n\n# Then install the adapters you need:\npnpm add grammy                    # Telegram\npnpm add discord.js                # Discord\npnpm add @slack/bolt               # Slack\npnpm add @whiskeysockets/baileys   # WhatsApp\npnpm add ws                        # WebChat\n```\n\n## Quick Start\n\n```typescript\nimport { Cogitator, Agent } from '@cogitator-ai/core';\nimport { Gateway, telegramChannel } from '@cogitator-ai/channels';\n\nconst cogitator = new Cogitator({ llm: { defaultModel: 'google/gemini-2.5-flash' } });\nconst agent = new Agent({ name: 'bot', instructions: 'You are a helpful assistant.' });\n\nconst gateway = new Gateway({\n  cogitator,\n  agent,\n  channels: [telegramChannel({ token: process.env.TG_TOKEN! })],\n  stream: { flushInterval: 500, minChunkSize: 20 },\n});\n\nawait gateway.start();\n```\n\n## Channels\n\n### Telegram\n\n**Get your token:** Open Telegram → search `@BotFather` → send `/newbot` → follow prompts → copy the token.\n\n```typescript\nimport { telegramChannel } from '@cogitator-ai/channels';\n\ntelegramChannel({ token: process.env.TG_TOKEN! });\n\n// Webhook mode (production):\ntelegramChannel({\n  token: process.env.TG_TOKEN!,\n  webhook: { url: 'https://example.com/telegram', port: 8443 },\n});\n```\n\nSupports: text, photos (→ vision), voice (→ STT), documents, streaming via editText, emoji reactions, 4096 char limit.\n\n### Discord\n\n**Get your token:** [Discord Developer Portal](https://discord.com/developers/applications) → 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.\n\n```typescript\nimport { discordChannel } from '@cogitator-ai/channels';\n\ndiscordChannel({\n  token: process.env.DISCORD_TOKEN!,\n  mentionOnly: true, // only respond when @mentioned in servers\n});\n```\n\nSupports: DMs, server messages, streaming, reactions, auto-chunking (2000 char limit, code-block aware).\n\n### Slack\n\n**Get your tokens (3 total):**\n\n1. [api.slack.com/apps](https://api.slack.com/apps) → Create New App → From scratch\n2. Socket Mode → enable → generate App Token (`xapp-...`) → save as `SLACK_APP_TOKEN`\n3. OAuth & Permissions → add scopes: `chat:write`, `app_mentions:read`, `im:history`, `im:read`, `im:write`\n4. Event Subscriptions → enable → add: `message.im`, `app_mention`\n5. Install App → copy Bot Token (`xoxb-...`) → save as `SLACK_BOT_TOKEN`\n6. Basic Information → copy Signing Secret → save as `SLACK_SIGNING_SECRET`\n\n```typescript\nimport { slackChannel } from '@cogitator-ai/channels';\n\nslackChannel({\n  token: process.env.SLACK_BOT_TOKEN!,\n  signingSecret: process.env.SLACK_SIGNING_SECRET!,\n  appToken: process.env.SLACK_APP_TOKEN!,\n});\n```\n\nSupports: DMs, channel messages (via @mention), Socket Mode (no public URL), streaming via chat.update.\n\n### WhatsApp\n\nNo bot API — connects as a linked device to your WhatsApp account (like WhatsApp Web).\n\n```typescript\nimport { whatsappChannel } from '@cogitator-ai/channels';\n\nwhatsappChannel({\n  sessionPath: '.cogitator/whatsapp-session',\n  printQr: true,\n});\n```\n\n**First run:** QR code prints to terminal → scan from WhatsApp → Settings → Linked Devices. Session is saved for future restarts.\n\nSupports: 1-on-1 and group chats, typing indicators, auto-reconnect, WhatsApp-native markdown. No streaming (WhatsApp doesn't support editing).\n\n### WebChat\n\nWebSocket server for custom UIs, CLI tools, or any client.\n\n```typescript\nimport { webchatChannel } from '@cogitator-ai/channels';\n\nwebchatChannel({\n  port: 3100,\n  path: '/ws',\n  auth: (token) => token === process.env.WEBCHAT_SECRET,\n});\n```\n\nConnect: `ws://localhost:3100/ws?token=YOUR_SECRET`. Send `{\"text\": \"Hello!\"}`, receive `{\"type\": \"message\", \"id\": \"...\", \"text\": \"...\"}`.\n\nSupports: streaming (via edit messages), typing indicators, token auth, no message limit.\n\n## Platform Comparison\n\n| Feature            | Telegram     | Discord | Slack     | WhatsApp | WebChat   |\n| ------------------ | ------------ | ------- | --------- | -------- | --------- |\n| Streaming (edit)   | ✅           | ✅      | ✅        | ❌       | ✅        |\n| Reactions          | ✅           | ✅      | ❌        | ❌       | ❌        |\n| Typing indicator   | ✅           | ✅      | ⚠️        | ✅       | ✅        |\n| Photos → vision    | ✅           | ❌      | ❌        | ❌       | ❌        |\n| Voice → STT        | ✅           | ❌      | ❌        | ❌       | ❌        |\n| Max message length | 4096         | 2000    | ~4000     | ~65536   | unlimited |\n| Public URL needed  | webhook only | no      | HTTP only | no       | no        |\n\n## Gateway\n\nRoutes incoming messages to your agent. Handles:\n\n- Session management (per-user, per-channel)\n- Streaming with `StreamBuffer` (chunked message editing)\n- Typing keep-alive (re-sends typing indicator every 4s)\n- Media processing (images → vision, voice → STT)\n- Middleware pipeline\n- Platform-specific markdown conversion\n- Status reactions, debouncing, envelope formatting, queue modes\n\n## Status Reactions\n\nEmoji progress indicators on the user's message:\n\n```typescript\nconst gateway = new Gateway({\n  // ...\n  reactions: {\n    enabled: true,\n    emojis: { queued: '👀', thinking: '🤔', tool: '🔥', done: '👍', error: '😱' },\n    debounceMs: 700,\n    stallSoftMs: 10000,\n    stallHardMs: 30000,\n  },\n});\n```\n\n## Inbound Debouncing\n\nMerge rapid messages into a single LLM call:\n\n```typescript\nconst gateway = new Gateway({\n  // ...\n  debounce: {\n    enabled: true,\n    delayMs: 1500,\n    byChannel: { discord: 2000 },\n  },\n});\n```\n\n## Envelope Formatting\n\nWrap messages with context so the LLM knows who's talking, on which platform, and when:\n\n`[14:23 MSK | telegram | @alice | DM | +2m30s] Hello world`\n\n```typescript\nconst gateway = new Gateway({\n  // ...\n  envelope: {\n    enabled: true,\n    includeTimestamp: true,\n    includeElapsed: true,\n    includeSender: true,\n    includeChannel: true,\n    includeChatType: true,\n    timezone: 'Europe/Moscow',\n  },\n});\n```\n\n## Queue Modes\n\nControl concurrent message handling per user:\n\n```typescript\nconst gateway = new Gateway({\n  // ...\n  queueMode: 'sequential', // 'parallel' | 'sequential' | 'interrupt' | 'collect'\n});\n```\n\n- **parallel** — default, all messages processed immediately\n- **sequential** — FIFO per thread, wait for current to finish\n- **interrupt** — abort current, start new message\n- **collect** — buffer during processing, merge on idle\n\n## Formatting Pipeline\n\nPlatform-specific markdown conversion applied automatically:\n\n- **Telegram** — `# headers` → bold, preserves code blocks\n- **Discord** — native Markdown, auto-chunks at 2000 chars with code block integrity\n- **Slack** — `**bold**` → `*bold*`, headers → bold\n- **WhatsApp** — `**bold**` → `*bold*`, `~~strike~~` → `~strike~`\n\n## Middleware\n\n```typescript\nimport { rateLimit, ownerCommands, DmPolicyMiddleware, autoExtract } from '@cogitator-ai/channels';\n\nconst gateway = new Gateway({\n  // ...\n  middleware: [\n    rateLimit({ maxPerMinute: 30 }),\n    ownerCommands({\n      ownerIds: { telegram: '123' },\n      commandLevels: { status: 'authorized', block: 'owner', help: 'public' },\n    }),\n    new DmPolicyMiddleware({\n      mode: 'pairing',\n      ownerIds: { telegram: '123' },\n      storePath: '~/.cogitator/dm-allowlist.json',\n      groupPolicy: 'open',\n    }),\n    autoExtract({ extractor }),\n  ],\n});\n```\n\n### DM Policy Modes\n\n- **open** — anyone can DM the bot\n- **allowlist** — only pre-approved users\n- **pairing** — unknown users get a code, owner approves via `/pair CODE`\n- **disabled** — DMs blocked entirely\n\n### Command Authorization Levels\n\nCommands 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.\n\n## Lifecycle Hooks\n\nSubscribe to events across the message lifecycle:\n\n```typescript\nimport { createHookRegistry } from '@cogitator-ai/channels';\n\nconst hooks = createHookRegistry();\nhooks.on('message:received', (e) => console.log('New message:', e));\nhooks.on('agent:after_run', (e) => console.log('Response:', e));\nhooks.on('agent:error', (e) => console.error('Agent failed:', e));\n\nconst gateway = new Gateway({ /* ... */ hooks });\n```\n\nAvailable hooks: `message:received`, `message:sending`, `message:sent`, `agent:before_run`, `agent:after_run`, `agent:error`, `session:created`, `session:compacted`, `stream:started`, `stream:finished`.\n\nErrors in one handler don't affect others.\n\n## Media & STT\n\nVoice messages are transcribed automatically. STT provider is selected by available env vars (highest priority first):\n\n1. **Deepgram** — set `DEEPGRAM_API_KEY` (nova-3 model, fast and accurate)\n2. **Groq** — set `GROQ_API_KEY` (free tier available)\n3. **OpenAI** — set `OPENAI_API_KEY`\n4. **Local Whisper** — downloads ~75MB model on first use, runs offline (no API key needed)\n\nImages are passed to the LLM as vision input if the model supports it.\n\n## Scheduler\n\n```typescript\nimport { HeartbeatScheduler, SimpleTimerStore } from '@cogitator-ai/channels';\n\nconst store = new SimpleTimerStore({ persistPath: '.cogitator/timers.json' });\nconst scheduler = new HeartbeatScheduler(store, {\n  onFire: (msg) => gateway.injectMessage(msg),\n  pollInterval: 30_000,\n  maxRetries: 5,\n  onRunComplete: (entry, status, error, durationMs) => {\n    console.log(`Job ${entry.id}: ${status} (${durationMs}ms)`);\n  },\n});\nscheduler.start();\n```\n\nSchedule types: `cron` (recurring), `recurring` (interval), `fixed` (one-shot). Error tracking with auto-backoff.\n\n```typescript\nawait scheduler.listJobs();\nawait scheduler.enableJob(id);\nawait scheduler.disableJob(id);\nawait scheduler.cancelJob(id);\n```\n\n## Environment Variables\n\n```bash\n# LLM Provider\nGOOGLE_API_KEY=...           # or ANTHROPIC_API_KEY, OPENAI_API_KEY\n\n# Telegram\nTG_TOKEN=7204891735:AAHr...\n\n# Discord\nDISCORD_TOKEN=MTI...\n\n# Slack (3 tokens)\nSLACK_BOT_TOKEN=xoxb-...\nSLACK_SIGNING_SECRET=...\nSLACK_APP_TOKEN=xapp-...\n\n# WhatsApp — no token, uses QR pairing\n\n# WebChat\nWEBCHAT_SECRET=your-secret\n\n# STT (optional, for voice messages — pick one)\nDEEPGRAM_API_KEY=...         # highest priority\nGROQ_API_KEY=...             # free tier\nOPENAI_API_KEY=...           # fallback\n```\n","readmeFilename":"README.md"}