内容
<h1 align="center">telegram-bot-skill</h1>
<p align="center">
<strong>您的本地CLI编码代理,从口袋中可访问:一个零依赖的桥梁,将任何无头代理转换为私人Telegram机器人。</strong>
</p>
<p align="center">
<img src="https://img.shields.io/badge/状态-可用_·_第_6_阶段_下一个-orange" alt="状态" />
<img src="https://img.shields.io/badge/依赖项-0-success" alt="零依赖项" />
<img src="https://img.shields.io/badge/Node-%3E%3D22.18-339933?logo=nodedotjs&logoColor=white" alt="Node >= 22.18" />
<img src="https://img.shields.io/badge/测试-83_通过-brightgreen" alt="测试" />
<img src="https://img.shields.io/badge/许可证-MIT-green" alt="MIT" />
</p>
<p align="center">
<img src="https://img.shields.io/badge/Telegram-官方_机器人_API-26A5E4?logo=telegram&logoColor=white" alt="Telegram 机器人 API" />
<img src="https://img.shields.io/badge/适配器-Claude_Code_·_Pi-D97757?logo=anthropic&logoColor=white" alt="适配器" />
<img src="https://img.shields.io/badge/本地模型-Pi_+_llama.cpp-8A2BE2" alt="本地模型" />
<img src="https://img.shields.io/badge/opencode_·_Codex_·_Gemini-计划中-lightgrey" alt="更多适配器计划中" />
<img src="https://img.shields.io/badge/TypeScript-原生_无需编译-3178C6?logo=typescript&logoColor=white" alt="TypeScript" />
</p>
---
## 这是什么
一个桥梁,而不是代理。 Telegram 消息进入,您的本地代理的答案输出,途中每一个安全决策都在任何模型看到字节之前通过确定性代码发生。它直接通过 Node 内置的 `fetch` 与官方机器人 API 通信:无需框架,无需包装器,依赖树为空。
它的存在是为了修复使基于聊天代理设置痛苦的三个问题:
- **您永远不知道机器人是否存活。** 这里,输入指示器保持亮起,代理工作时,一个状态消息跟踪进度(“🔧 Bash:npm test”),答案单独到达,每个运行都以明确的 ✅ / ⚠️ / ⏱ 结束。
- **陌生人是全有或全无的。** 这里,未知用户进入待处理队列,您获得“批准” / “访客” / “阻止”按钮,每个人都生活在不同层级:所有者,信任,访客,阻止。
- **“提示说不”不是安全。** 层级映射到代理环境的配置(权限规则,钩子),因此被拒绝的工具无论聊天用户如何诱导模型都保持被拒绝。无法诚实执行此操作的适配器会声明它,桥梁会拒绝通过非所有者流量路由。
### <a href="https://hec-ovi.github.io/telegram-bot-skill/">🗺️ 探索交互式架构地图 →</a>
整个管道的可缩放蓝图:每个模块,其输入/输出契约,其状态,以及指向其源代码的链接,都在一屏上。
## 运行它
需要 Node >= 22.18 和默认适配器的 `claude` CLI。没有安装步骤。
```bash
git clone https://github.com/hec-ovi/telegram-bot-skill
cd telegram-bot-skill
TELEGRAM_BOT_TOKEN=123456789:AAE... npm run setup # 一次:验证并写入 ./.env(模式 600)
npm start # 之后:不需要参数
```
不希望令牌出现在 shell 历史记录中?`cp .env.example .env`,将其粘贴到文件中,并运行 `npm run setup`,无需参数;它验证并完成文件。`npm start` 总是读取它自己的 `./.env`,因此配置的检查在任何重启后都是即插即用的。
第一次启动打印一次性声明链接(`https://t.me/yourbot?start=...`)和二维码(在终端中,使用我们自己的零依赖编码器)。扫描它,点击“开始”,您就是所有者。其他消息机器人的人在您点击按钮之前在门处等待。
| 环境变量 | 必需 | 默认值 | 描述 |
| --- | --- | --- | --- |
| `TELEGRAM_BOT_TOKEN` | 是 | | 来自 @BotFather 的机器人令牌 |
| `STATE_FILE` | 否 | `./bot-state.json` | 用户,层级,会话,轮询偏移 |
| `AGENT_CWD` | 否 | 当前目录 | 代理工作目录 |
| `AGENT_ADAPTER` | 否 | `claude-code` | 哪个代理回答:`claude-code` 或 `pi` |
| `PI_MODEL` | 否 | | Pi 模型参考,例如 `local/gemma-4-26b` |
| `OWNER_ID` | 否 | | 恢复模式:以所有者身份在启动时播种的数字 Telegram ID |
| `TRUSTED_IDS` / `GUEST_IDS` / `BLOCKED_IDS` | 否 | | 恢复模式:分层播种的 ID |
| `BOT_NAME` / `BOT_DESCRIPTION` / `BOT_ABOUT` | 否 | | 机器人身份,由 `npm run setup` 应用(头像保持 BotFather 独有) |
恢复模式意味着状态文件永远不是珍贵的:擦除它,重新部署,启动一个全新的机器,并使用设置的 `OWNER_ID` 启动一个已经拥有并可用的机器人。环境是命名 ID 的真相来源(过时的存储所有者被降级为受信任)。
对于一个可以重启的机器人,在重启后仍能正常运行的进程管理器下运行它:[examples/pi-gemma](examples/pi-gemma) 使用 `restart: unless-stopped` 来实现这一点(PC 重启后,它会恢复监听,状态完整);对于裸 `npm start`,请使用您选择的进程管理器(systemd 单元效果很好)。
### 完全本地,无需云
同一个桥梁在本地模型上运行:[Pi 编码代理](https://github.com/earendil-works/pi) 针对任何 llama.cpp / OpenAI 兼容服务器。[examples/pi-gemma](examples/pi-gemma) 使用一个 compose 文件和一个 `.env` 文件启动整个系统:llama.cpp 在 Vulkan 上为您的 GGUF 提供服务,Pi 连接到它,桥梁在上面。那套系统是有意作为项目的参考测试台:一个由小型本地模型驱动的小型 CLI 是最低要求,所有内容都针对最低要求进行验证。一个更强大的 CLI(Claude Code,Codex,opencode,Hermes)在更大的模型上具有严格的更多功能,在同一个桥梁后面,从不更少。
### 尚未有令牌?
两种方式:
- **您了解 Telegram 机器人:** 粘贴现有的令牌即可。
- **第一次:** 打开 Telegram,找到 `@BotFather`,发送 `/newbot`,选择一个名称,选择一个以 `bot` 结尾的用户名,复制它给出的令牌。 一分钟,免费。 或者跳过阅读:告诉您的 CLI 代理“从此存储库设置 Telegram 机器人”。 [SKILL.md](SKILL.md) 是为代理编写的,它将指导您创建令牌,启动桥梁,并为您提供声明链接。
## 安装为技能
存储库是一种可安装的代理技能(开放 SKILL.md 格式),因此任何 CLI 代理都可以对话式地运行整个设置。 四种方式:
```bash
# 任何支持 SKILL.md 格式的代码 CLI
npx skills add hec-ovi/telegram-bot-skill
# Claude Code 市场
/plugin marketplace add hec-ovi/telegram-bot-skill
/plugin install telegram-bot@telegram-bot-skill
# Codex
codex plugin marketplace add hec-ovi/telegram-bot-skill
codex plugin add telegram-bot-codex@telegram-bot-skill
# 普通 git,用于任何读取 ~/.agents/skills(pi,hermes,...)或 ~/.claude/skills
git clone https://github.com/hec-ovi/telegram-bot-skill ~/.agents/skills/telegram-bot
```
然后告诉您的代理:“设置 Telegram 机器人”。 插件路由仅携带技能文件;其步骤 0 在缺少时克隆桥梁代码。
## 与您的实时会话聊天(MCP)
`npm start` 为每个消息生成一个新的无头代理。 MCP 接口则相反:您已经打开的编码会话是回答问题的代理,具有其上下文,其工具及其权限设置。 存储库附带 `.mcp.json`,因此在 Claude Code 中打开此文件夹(或将任何 MCP 客户端指向 `node mcp/server.ts`)会将桥梁暴露为 `telegram` 服务器。 相同的 `.env`,相同状态文件,相同的门;陌生人仍然在门口等待。
消息到达代理的两种方式:
- **拉取,在任何 MCP 客户端中有效。** 代理调用 `wait_for_message`(阻塞,队列支持,期间不会丢失任何内容),用 `send_message` 回答,然后再次调用 `wait_for_message`。 告诉您的代理“提供 Telegram 桥梁”就足够了;工具描述包含循环。
- **推送,Claude Code v2.1.80+(通道,研究预览)。** 在 `.mcp.json` 中的服务器参数中添加 `--channel`,并使用 `claude --dangerously-load-development-channels server:telegram` 启动会话。 现在,传入的消息直接作为 `<channel>` 事件注入会话:无需轮询,无阻塞工具调用,它们有礼貌地排队,直到代理完成工作。 回复仍然通过 `send_message` 发送。 两个注意事项:没有那个启动标志,通知将被静默丢弃(Claude Code 仅监听它命名的服务器),并且在第一个同意对话框仍然打开时发送的消息可能会被错过;服务器在握手后等待 5 秒的宽限期,然后刷新,这涵盖了正常重启情况。
额外的工具在两种模式下都有效:`list_users`,`set_user_tier` 和 `bridge_status`(当机器人未被认领时,它带有声明链接)在不离开会话的情况下管理白名单。 一条规则成立:一个机器人令牌允许恰好一个轮询器,因此在启动 `npm start` / `npm run bg` 之前,请停止它,反之亦然。
### 从终端管理访问
实时批准只需在 Telegram 上点击一次,相同的白名单是可脚本化的:
```bash
npm run users # 列出每个人及其层级
npm run users -- set 123456 trusted # 所有者 | 受信任 | 访客 | 阻止 | 待处理
npm run users -- remove 123456
```
## 模块
每个模块都隔离在明确的输入/输出契约后面([ARCHITECTURE.md](ARCHITECTURE.md) 中有完整的详细信息);特定于代理的代码仅存在于 `src/agents/<adapter>` 中。
| 模块 | 作业 | 状态 |
| --- | --- | --- |
| `src/telegram` | 机器人 API 客户端:长轮询,429 回退,4096 字符分块 | ✅ |
| `src/agents` | 适配器契约 + Claude Code 和 Pi 适配器(实时验证模式) | ✅ |
| `src/presence` | 输入循环,节流状态编辑,分块答案,超时 | ✅ |
| `src/gate` | 确定性访问决策,所有者声明,批准 | ✅ |
| `src/store` | 平面 JSON 状态,原子写入,无数据库 | ✅ |
| `src/runner` | 聊天队列,会话恢复,能力拒绝 | ✅ |
| `src/qr` | 声明链接的零依赖二维码编码器(字节模式,EC L,v1-6) | ✅ |
| `mcp/` | MCP 服务器:您的实时会话回答,拉取或推送(通道) | ✅ |
| `src/policy` | 层级到配置映射(设置,钩子,标志) | 🔜 下一个 |
## 路线图
| 阶段 | 内容 | 状态 |
| --- | --- | --- |
| 0 至 5 | 契约,Telegram 客户端,适配器,存在,网关,可运行的机器人 | ✅ |
| 6 | 每个层级的工具强制执行(设置 + PreToolUse 钩子) | 🔜 下一个 |
| 7 | 入门:终端二维码,`npm run setup`,`.env` 配置,代理引导 SKILL.md | ✅ |
| 8 | 更多适配器:Pi 配备本地模型;opencode,Codex,Gemini 待定 | 🟡 部分 |
| 9 | 强化:速率限制,审计日志,令牌卫生 | ⬜ |
| 10 | 打包:技能安装路由,npm 发布 | ⬜ |
| 11 | MCP 接口:会话即代理,拉取 + 推送(通道) | ✅ |
完整计划及各阶段原因:[ROADMAP.md](ROADMAP.md)。
## 测试
```bash
npm test
```
Node 内置运行器上有 83 个测试:Telegram 客户端与真实的本地 `node:http` Bot API 模拟端到端测试,Claude Code 和 Pi 适配器与脚本化假二进制文件对抗,QR 编码器与规范的 Reed-Solomon 矩阵和经过独立解码器(OpenCV)交叉验证的黄金矩阵对抗,整个机器人通过完整模拟对话(声明,陌生人敲门,伪造批准被拒绝,所有者批准,代理用实时状态回答,会话恢复,巨魔被阻止),MCP 服务器作为通过 stdio 发送真实 JSON-RPC 的子进程:握手,两种双工模式,网关保持,取消,层级工具。
## 为什么是零依赖
桥梁包装了两件事:官方机器人 API 和本地代理二进制文件。 Node 24 已经提供了执行此操作所需的一切:`fetch`,测试运行器,原生 TypeScript 类型剥离。 避免的每个依赖都是一个供应链门,始终保持关闭状态,这对于一个程序来说很重要,因为它的工作是在互联网和具有 shell 能力的代理之间。 最近的 CVE 历史就是一个警示故事,发生在同一产品类别中。
```
src/
telegram/ 机器人 API 客户端,轮询器,分块,洪水控制
agents/ 契约 + claude-code 和 pi 适配器(更多待来)
presence/ “它是在思考还是已死”层
gate/ 确定性访问决策
store/ 平面文件状态
runner/ 队列 + 会话 + 能力检查
qr/ 声明链接的二维码,在终端中渲染
app.ts 连接,bot.ts:入口,daemon.ts:后台控制
setup.ts 令牌向导,用户管理:白名单管理
mcp/ MCP 服务器:rpc.ts 线,bridge.ts 粘合剂,server.ts 入口
examples/
pi-gemma/ 容器化:Pi + llama.cpp 本地模型端到端
plugins/ claude code 和 codex 插件打包
```
MIT. 由 [Hector Oviedo](https://github.com/hec-ovi) 构建。