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

@wsz987/channel-telegram

v0.5.0

Published

Telegram Bot API channel adapter for DeepSeek Harness (credentials seam, control-plane definition, edit streaming, file hydration)

Readme

@wsz987/channel-telegram

Telegram Bot API channel adapter for DeepSeek Harness.

Install

pnpm add @wsz987/channel-telegram

Bundled community channel

This package is part of the community-maintained @wsz987/dsh-channels bundle. It is not an official DeepSeek Harness or Telegram package. It implements the same Channel Contract as weixin / qq / dingtalk / lark, with no changes to channel-core, channel-harness or the other adapters. Setup and credentials go through the Channel Control Plane; the bot token is stored via ctx.credentials (tokenRef), never in profile config.

The bundle patch inserts this adapter as channels-telegram and the Web settings panel shows it with the other bundled channels.

Contract coverage:

  • ChannelAdapter contract (start / stop / send / getHealth / capabilities)
  • runChannelAdapterContract — the testkit's full contract suite passes
  • Cordis plugin shape (name / inject / apply via ctx.effect)
  • Schemastery Config with an injectable HttpTransport (offline fake in tests)
  • Fixture-driven mapper tests (fixtures/telegram/*.json, Bot API 10.2 shapes)
  • M4 governance: readonly manifest class field + manifest.ts for channels doctor compatibility checks

The adapter remains experimental until its real-platform live gate passes; offline contract tests and fixtures do not by themselves justify tested.

Pointing it at a real bot

In your profile config:

{
  "plugins": {
    "channel-telegram": {
      "enabled": true,
      "accountId": "main",
      "baseUrl": "https://api.telegram.org",
      "tokenRef": "TELEGRAM_BOT_TOKEN",
      "longPollTimeoutMs": 25000
    }
  }
}

The token is a secret resolved through ctx.credentials (tokenRef): it is never logged (bearer-style path segments are redacted in transport error messages) and it only ever appears in the Bot API request path built by the upstream driver. It is never written into fixture files.

Inbound delivery currently uses Telegram Bot API long polling (getUpdates), matching OpenClaw's local-install default. Startup removes an existing webhook before polling because Telegram makes webhook and getUpdates delivery mutually exclusive. This is an operational takeover of the Bot's update receiver: do not reuse the same Bot for another webhook consumer. A hosted webhook transport is not implemented yet.

Capabilities

| capability | value | | ------------ | --------- | | text / image / file / audio / video | ✅ | | markdown | ✅ Rich Markdown | | reactions | ❌ | | cards | ❌ | | threads | ✅ | | streaming | DM Rich Draft; group plain preview + rich final edit; set streaming.enabled: false for buffered |

Known limits

  • Minimum supported upstream is Telegram Bot API 10.2. Older or pinned custom Bot API servers are not supported; use formatting.mode: plain only as an explicit presentation choice, not as an old-server compatibility mode.
  • getUpdates subscribes to message and callback_query. Button interactions are currently intended only for callback queries carrying message.chat; inline-message callbacks without chat context are not a supported routing surface and require a mapper hardening change before release.
  • The ordinary message mapper still needs a complete zod trust-boundary schema; the current partial envelope validation and TypeScript casts are an identified release blocker, not evidence that arbitrary Telegram updates are supported.
  • Media sends validate the Bot API ok envelope and returned message_id; an ok: false response is surfaced as a delivery failure. Offline coverage does not replace the required real-bot live gate.
  • Inbound image, file, audio, and video media hydrate bytes through getFile/download when declared as byte-capable. Failures retain resourceRef plus ingress-failure metadata.
  • Telegram albums (media_group_id) are intentionally delivered one update at a time. Each image is downloaded, dispatched, retried and acknowledged independently; no cross-update buffering or delayed album aggregation is performed.
  • Media captions are preserved as a text part before the image or document, so the model receives both the caption and the shared attachment representation.
  • Media outbound accepts trusted localData via multipart/form-data, a public url, or a platform file_id (resourceRef). Multiple supported media parts are sent sequentially; an unsupported part fails the send rather than being silently dropped.
  • Inbound media maps Telegram file_id to the contract's resourceRef carrier (an opaque platform handle), never to urlurl is reserved for real http(s) URLs.
  • beginAuth/pollAuth are omitted: auth is token-driven (getMe() check at start).
  • Forum topics preserve message_thread_id; chat.type === 'channel' currently maps to a dm conversation.

Development

pnpm --filter @wsz987/channel-telegram build
pnpm --filter @wsz987/channel-telegram typecheck
pnpm --filter @wsz987/channel-telegram test

Related

License

MIT