import type { Plugin } from "@opencode-ai/plugin" import { join } from "path" import { homedir } from "os" interface Config { serviceUrl?: string } async function loadConfig(directory: string): Promise { // 1. 尝试项目级配置 try { const projectConfig = Bun.file(join(directory, ".opencode", "status-light.json")) if (await projectConfig.exists()) { return await projectConfig.json() } } catch {} // 2. 尝试全局配置 try { const globalConfig = Bun.file(join(homedir(), ".config", "opencode", "status-light.json")) if (await globalConfig.exists()) { return await globalConfig.json() } } catch {} return {} } export const StatusLightPlugin: Plugin = async ({ directory }) => { const config = await loadConfig(directory) const serviceUrl = process.env.STATUS_LIGHT_URL || config.serviceUrl || "http://localhost:8080" async function sendStatus(code: string) { try { await fetch(`${serviceUrl}/api/event`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ code, timestamp: new Date().toISOString() }), }) } catch { // 静默失败,不影响 OpenCode } } return { event: async ({ event }) => { let code = "" switch (event.type) { case "session.idle": code = "idle" break case "session.status": code = event.properties?.status?.type || "" break case "message.part.updated": { const part = event.properties?.part if (part?.type === "tool") { code = part.state?.status || "using_tool" } else if (part?.type === "reasoning") { code = "reasoning" } break } case "permission.asked": code = "permission" break case "session.error": code = "error" break } if (code) { await sendStatus(code) } }, } }