From 8febf9411f62af9b22e507720de47a54f9eebdaf Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 3 Dec 2025 11:49:33 +0900 Subject: [PATCH] feat: wire up agents and expose via opencode plugin --- src/agents/index.ts | 10 ++++ src/index.ts | 132 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/agents/index.ts create mode 100644 src/index.ts diff --git a/src/agents/index.ts b/src/agents/index.ts new file mode 100644 index 0000000..190320e --- /dev/null +++ b/src/agents/index.ts @@ -0,0 +1,10 @@ +import type { AgentConfig } from "@opencode-ai/sdk" +import { oracleAgent } from "./oracle" +import { librarianAgent } from "./librarian" +import { exploreAgent } from "./explore" + +export const builtinAgents: Record = { + oracle: oracleAgent, + librarian: librarianAgent, + explore: exploreAgent, +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..cfa30f8 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,132 @@ +import type { Plugin } from "@opencode-ai/plugin"; +import { builtinAgents } from "./agents"; +import { + createTodoContinuationEnforcer, + createContextWindowMonitorHook, +} from "./hooks"; +import { updateTerminalTitle } from "./features/terminal"; + +const OhMyOpenCodePlugin: Plugin = async (ctx) => { + const todoContinuationEnforcer = createTodoContinuationEnforcer(ctx); + const contextWindowMonitor = createContextWindowMonitorHook(ctx); + updateTerminalTitle({ sessionId: "main" }); + + let mainSessionID: string | undefined; + let currentSessionID: string | undefined; + let currentSessionTitle: string | undefined; + + return { + config: async (config) => { + if (!config) return; + config.agent = { + ...config.agent, + ...builtinAgents, + }; + }, + + event: async (input) => { + await todoContinuationEnforcer(input); + await contextWindowMonitor.event(input); + + const { event } = input; + const props = event.properties as Record | undefined; + + if (event.type === "session.created") { + const sessionInfo = props?.info as + | { id?: string; title?: string; parentID?: string } + | undefined; + if (!sessionInfo?.parentID) { + mainSessionID = sessionInfo?.id; + currentSessionID = sessionInfo?.id; + currentSessionTitle = sessionInfo?.title; + updateTerminalTitle({ + sessionId: currentSessionID || "main", + status: "idle", + directory: ctx.directory, + sessionTitle: currentSessionTitle, + }); + } + } + + if (event.type === "session.updated") { + const sessionInfo = props?.info as + | { id?: string; title?: string; parentID?: string } + | undefined; + if (!sessionInfo?.parentID) { + currentSessionID = sessionInfo?.id; + currentSessionTitle = sessionInfo?.title; + updateTerminalTitle({ + sessionId: currentSessionID || "main", + status: "processing", + directory: ctx.directory, + sessionTitle: currentSessionTitle, + }); + } + } + + if (event.type === "session.deleted") { + const sessionInfo = props?.info as { id?: string } | undefined; + if (sessionInfo?.id === mainSessionID) { + mainSessionID = undefined; + currentSessionID = undefined; + currentSessionTitle = undefined; + updateTerminalTitle({ + sessionId: "main", + status: "idle", + }); + } + } + + if (event.type === "session.error") { + const sessionID = props?.sessionID as string | undefined; + if (sessionID && sessionID === mainSessionID) { + updateTerminalTitle({ + sessionId: sessionID, + status: "error", + directory: ctx.directory, + sessionTitle: currentSessionTitle, + }); + } + } + + if (event.type === "session.idle") { + const sessionID = props?.sessionID as string | undefined; + if (sessionID && sessionID === mainSessionID) { + updateTerminalTitle({ + sessionId: sessionID, + status: "idle", + directory: ctx.directory, + sessionTitle: currentSessionTitle, + }); + } + } + }, + + "tool.execute.before": async (input, _output) => { + if (input.sessionID === mainSessionID) { + updateTerminalTitle({ + sessionId: input.sessionID, + status: "tool", + currentTool: input.tool, + directory: ctx.directory, + sessionTitle: currentSessionTitle, + }); + } + }, + + "tool.execute.after": async (input, output) => { + await contextWindowMonitor["tool.execute.after"](input, output); + + if (input.sessionID === mainSessionID) { + updateTerminalTitle({ + sessionId: input.sessionID, + status: "idle", + directory: ctx.directory, + sessionTitle: currentSessionTitle, + }); + } + }, + }; +}; + +export default OhMyOpenCodePlugin;