Coding 工具 · 04

OpenCode

使用 OpenCode plugin 监听 session.idle,读取主会话最后一条 assistant message ID,并把它作为稳定的本轮身份。

当前官方事件

session.idle 是候选完成信号

OpenCode plugin 的 event 回调可以收到 session.idle。它表示某个 session 进入 idle,不保证它一定是你想提醒的顶层用户任务;复杂工作流里也可能包含子 session。

步骤 1

创建 bluebell plugin

bluebell.js
export const BluebellPlugin = async ({ client, directory }) => {
  const cli = "/Applications/bluebellMac.app/Contents/Helpers/bluebellctl"

  return {
    event: async ({ event }) => {
      if (event.type !== "session.idle") return

      const sessionID = event.properties.sessionID
      const sessionResult = await client.session.get({ path: { id: sessionID } })
      const session = sessionResult.data
      if (!session || session.parentID) return

      const messageResult = await client.session.messages({ path: { id: sessionID } })
      const messages = messageResult.data || []
      const lastAssistant = [...messages].reverse().find(
        (item) => item.info && item.info.role === "assistant"
      )
      const messageID = lastAssistant && lastAssistant.info.id
      if (!messageID) return

      const workspace = directory.split("/").filter(Boolean).pop() || "OpenCode"
      const process = Bun.spawn([
        cli, "emit",
        "--source", "OpenCode",
        "--workspace-name", workspace,
        "--session-id", sessionID,
        "--turn-id", messageID,
        "--dedupe-key", "opencode:" + sessionID + ":" + messageID,
        "--local",
      ], { stdout: "ignore", stderr: "ignore" })
      await process.exited
    },
  }
}

示例通过 OpenCode SDK 读取 session 与 message 列表,只发送 ID 和工作区显示名,不把消息正文交给 bluebell。先保留 --local。

步骤 2

选择项目级或全局安装

位置作用范围
.opencode/plugins/bluebell.js只对当前项目生效,适合先做 POC。
~/.config/opencode/plugins/bluebell.js对本机 OpenCode 项目全局生效。

不要让同一 plugin 同时出现在项目级和全局位置,否则同一 idle 可能触发两次命令。即使 dedupeKey 能合并,也会制造不必要的调用。

步骤 3

分别测试根 session 与子任务

  1. 完成一轮没有子任务的短工作,确认最近提醒只有一条 OpenCode 事件。
  2. 运行一个会创建子 session 的工作流,确认子 session 没有产生提醒。
  3. 在同一 session 发起第二轮,确认最后 assistant message ID 改变。
  4. 验证后删除 --local,再检查 Mac 总推送与真实设备。

来源

OpenCode 官方资料