Skip to content

OpenCode 通知系统:Bun + Telegram Bot 集成研究

执行摘要

本研究探讨了为 OpenCode 实现一个基于 Telegram 的实时通知系统。当 OpenCode 执行完成、失败或需要用户确认时,通过 Telegram Bot 发送即时通知。建议的方案采用 Bun 作为运行时(得益于其高性能和 WebSocket 能力),结合 Telegram Bot API 实现可靠的跨平台消息传递。该架构提供了清晰的关注点分离,允许 OpenCode 发出事件,由独立的通知服务处理消息传递,实现了松耦合、高可扩展的通知系统。

核心发现

  1. 架构设计:采用事件驱动架构,OpenCode 作为事件发射器,独立通知服务监听事件并发送 Telegram 消息
  2. 技术选型:Bun 作为运行时提供优异的性能和 WebSocket 支持,Telegram Bot API 提供可靠的消息传递
  3. 事件类型:支持任务开始、成功、失败、需要确认等核心事件
  4. 通信机制:支持本地 IPC、WebSocket、HTTP 等多种通信方式

可行性评估

技术可行性:高度可行(Highly Feasible)

  • ✅ Bun 提供优异的性能和 WebSocket 支持
  • ✅ Telegram Bot API 稳定可靠,文档完善
  • ✅ 事件驱动架构松耦合,易于维护
  • ✅ 支持多种通信机制,灵活适配
  • ⚠️ 需要配置 Telegram Bot Token
  • ⚠️ 需要管理用户 Chat ID

文档导航

  • analysis.md - 完整分析报告:架构设计、技术方案、实现细节、代码示例

核心内容

1. 系统架构

┌─────────────────┐         ┌──────────────────┐         ┌─────────────┐
│   OpenCode      │────────▶│ Notification     │────────▶│  Telegram   │
│   (事件发射器)   │  事件   │  服务 (Bun)       │  HTTP   │   Bot API   │
└─────────────────┘         └──────────────────┘         └─────────────┘


                             ┌──────────────┐
                             │  本地 IPC/   │
                             │  WebSocket   │
                             └──────────────┘

核心组件

  1. OpenCode:发出生命周期事件(开始、成功、失败、需要确认)
  2. 通知服务(Bun):订阅事件、格式化消息、调用 Telegram API
  3. Telegram Bot:向用户设备传递格式化的通知

2. 事件类型

事件名称触发条件载荷结构
opencode:start任务执行开始{ taskId, command, timestamp }
opencode:success任务成功完成{ taskId, duration, outputSummary }
opencode:failure任务失败{ taskId, error, stackTrace, exitCode }
opencode:confirm需要用户确认{ taskId, message, options }

3. 技术选型

Bun 运行时

优势:

  • 极快的启动速度和运行时性能
  • 原生 TypeScript 支持
  • 内置 WebSocket 支持
  • 轻量级 HTTP 服务器
  • 兼容 Node.js API

性能对比:

  • 启动速度:比 Node.js 快 3-4 倍
  • HTTP 请求:比 Node.js 快 2-3 倍
  • WebSocket:原生支持,性能优异

Telegram Bot API

优势:

  • 完全免费,无消息限制
  • 官方 API 稳定可靠
  • 丰富的消息格式(文本、按钮、内联键盘)
  • 支持文件传输
  • 全平台支持(iOS、Android、Web、Desktop)

核心方法:

  • sendMessage:发送文本消息
  • sendMessage + reply_markup:发送交互式按钮
  • answerCallbackQuery:响应按钮点击
  • editMessageText:编辑已发送的消息

4. 通信机制

方案 1:本地 IPC (推荐)

typescript
// OpenCode 侧
import { send } from "./ipc"

send("opencode:success", {
  taskId: "task-123",
  duration: 5000,
  outputSummary: "Successfully completed"
})

// 通知服务侧
import { listen } from "./ipc"

listen("opencode:success", async (payload) => {
  await sendTelegramMessage(payload)
})

优势:

  • 低延迟
  • 简单可靠
  • 无需网络配置

方案 2:WebSocket

typescript
// 通知服务(Bun WebSocket 服务器)
Bun.serve({
  port: 3000,
  fetch(req, server) {
    if (server.upgrade(req)) return
    return new Response("Upgrade failed", { status: 500 })
  },
  websocket: {
    message(ws, message) {
      const event = JSON.parse(message)
      handleEvent(event)
    }
  }
})

// OpenCode 侧
const ws = new WebSocket("ws://localhost:3000")
ws.send(JSON.stringify({
  type: "opencode:success",
  payload: { taskId, duration, outputSummary }
}))

优势:

  • 双向通信
  • 实时性强
  • 支持远程部署

方案 3:HTTP Webhook

typescript
// 通知服务(HTTP 服务器)
Bun.serve({
  port: 3000,
  async fetch(req) {
    const event = await req.json()
    await handleEvent(event)
    return new Response("OK")
  }
})

// OpenCode 侧
await fetch("http://localhost:3000/webhook", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    type: "opencode:success",
    payload: { taskId, duration, outputSummary }
  })
})

优势:

  • 简单直接
  • 易于调试
  • 支持负载均衡

5. 实现示例

通知服务核心代码(Bun)

typescript
// notification-service.ts
const BOT_TOKEN = process.env.TELEGRAM_BOT_TOKEN
const CHAT_ID = process.env.TELEGRAM_CHAT_ID

async function sendTelegramMessage(text: string, buttons?: any) {
  const url = `https://api.telegram.org/bot${BOT_TOKEN}/sendMessage`
  const payload = {
    chat_id: CHAT_ID,
    text,
    parse_mode: "Markdown",
    ...(buttons && { reply_markup: buttons })
  }
  
  const response = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload)
  })
  
  return response.json()
}

// 事件处理器
async function handleSuccess(payload: any) {
  const message = `
✅ *OpenCode Task Completed*

Task ID: \`${payload.taskId}\`
Duration: ${payload.duration}ms
Output: ${payload.outputSummary}
  `
  await sendTelegramMessage(message)
}

async function handleFailure(payload: any) {
  const message = `
❌ *OpenCode Task Failed*

Task ID: \`${payload.taskId}\`
Error: \`${payload.error}\`
Exit Code: ${payload.exitCode}
  `
  await sendTelegramMessage(message)
}

async function handleConfirm(payload: any) {
  const message = `
🔔 *OpenCode Needs Your Confirmation*

${payload.message}
  `
  const buttons = {
    inline_keyboard: [[
      { text: "✅ Approve", callback_data: `approve:${payload.taskId}` },
      { text: "❌ Reject", callback_data: `reject:${payload.taskId}` }
    ]]
  }
  await sendTelegramMessage(message, buttons)
}

OpenCode 插件集成

typescript
// opencode-notification-plugin.ts
import type { Plugin } from "@opencode-ai/plugin"

export const NotificationPlugin: Plugin = async (ctx) => {
  const notifyService = await connectToNotificationService()
  
  return {
    "session.created": async (input, output) => {
      await notifyService.emit("opencode:start", {
        taskId: output.sessionID,
        command: input.prompt,
        timestamp: Date.now()
      })
    },
    
    "session.completed": async (input, output) => {
      await notifyService.emit("opencode:success", {
        taskId: output.sessionID,
        duration: output.duration,
        outputSummary: output.summary
      })
    },
    
    "session.failed": async (input, output) => {
      await notifyService.emit("opencode:failure", {
        taskId: output.sessionID,
        error: output.error,
        stackTrace: output.stackTrace,
        exitCode: output.exitCode
      })
    },
    
    "permission.requested": async (input, output) => {
      await notifyService.emit("opencode:confirm", {
        taskId: output.sessionID,
        message: input.message,
        options: input.options
      })
    }
  }
}

部署与配置

1. 创建 Telegram Bot

bash
# 1. 在 Telegram 中找到 @BotFather
# 2. 发送 /newbot 创建新机器人
# 3. 获取 Bot Token
# 4. 发送消息到机器人获取 Chat ID

2. 配置环境变量

bash
# .env
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here

3. 安装依赖

bash
# 安装 Bun
curl -fsSL https://bun.sh/install | bash

# 安装项目依赖
bun install

4. 启动服务

bash
# 启动通知服务
bun run notification-service.ts

# 在 OpenCode 中启用插件
# 编辑 opencode.config.ts
import { NotificationPlugin } from "./opencode-notification-plugin"

export default {
  plugins: [NotificationPlugin]
}

最佳实践

1. 消息格式设计

  • 使用 Markdown 格式化消息
  • 添加清晰的状态指示器(✅❌🔔)
  • 包含关键信息(Task ID、时间、错误等)
  • 保持消息简洁,避免过长

2. 错误处理

  • 实现重试机制(网络失败时)
  • 记录失败的通知以便后续处理
  • 提供降级方案(如日志文件)
  • 监控通知服务健康状态

3. 性能优化

  • 使用消息队列处理高并发
  • 批量发送非紧急通知
  • 实现消息去重
  • 限制消息发送频率

4. 安全考虑

  • 保护 Bot Token 和 Chat ID
  • 验证事件来源
  • 限制 API 访问(白名单)
  • 加密敏感信息

扩展方向

1. 多用户支持

  • 支持多个用户订阅通知
  • 基于用户偏好过滤事件
  • 用户权限管理

2. 丰富的消息类型

  • 发送代码片段(使用 Telegram 代码格式)
  • 发送文件(日志、报告等)
  • 发送图片(图表、截图等)

3. 交互式功能

  • 通过 Telegram 控制 OpenCode
  • 远程批准/拒绝操作
  • 查询任务状态
  • 取消正在运行的任务

4. 集成其他通知渠道

  • Slack
  • Discord
  • Email
  • 企业微信/钉钉

适用场景

适合使用的场景

  • 长时间运行的 OpenCode 任务
  • 需要远程监控的自动化流程
  • 团队协作开发环境
  • CI/CD 集成场景
  • 需要即时反馈的交互式任务

不适合使用的场景

  • 短时间完成的简单任务
  • 本地开发的轻量级使用
  • 不希望依赖外部服务的场景
  • 对隐私有严格要求的环境(需自建服务)

核心参考资料

官方文档

技术资源

相关研究


研究日期:2026-01-19
技术栈:Bun + Telegram Bot API
研究类型:技术方案研究
文档版本:1.0