Logo
热心市民王先生

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

技术研究 人工智能 OpenCode

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

执行摘要

本研究探讨了为 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 (推荐)

// 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

// 通知服务(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

// 通知服务(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)

// 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 插件集成

// 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

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

2. 配置环境变量

# .env
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here

3. 安装依赖

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

# 安装项目依赖
bun install

4. 启动服务

# 启动通知服务
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