feat(hooks): add pulse-monitor for token stall detection and auto-recovery

- Detect token stalls via message.part.updated heartbeat monitoring
- Support thinking/reasoning block detection with extended timeout
- Auto-recover: abort + 'continue' prompt on 5min stall
- Pause monitoring during tool execution
This commit is contained in:
YeonGyu-Kim
2025-12-06 11:17:55 +09:00
parent a763db61cf
commit 4debb57402
3 changed files with 148 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
import type { Plugin } from "@opencode-ai/plugin"
import { createBuiltinAgents } from "./agents"
import { createTodoContinuationEnforcer, createContextWindowMonitorHook, createSessionRecoveryHook, createCommentCheckerHooks, createGrepOutputTruncatorHook } from "./hooks"
import { createTodoContinuationEnforcer, createContextWindowMonitorHook, createSessionRecoveryHook, createCommentCheckerHooks, createGrepOutputTruncatorHook, createPulseMonitorHook } from "./hooks"
import { updateTerminalTitle } from "./features/terminal"
import { builtinTools } from "./tools"
import { createBuiltinMcps } from "./mcp"
@@ -43,6 +43,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
const todoContinuationEnforcer = createTodoContinuationEnforcer(ctx)
const contextWindowMonitor = createContextWindowMonitorHook(ctx)
const sessionRecovery = createSessionRecoveryHook(ctx)
const pulseMonitor = createPulseMonitorHook(ctx)
const commentChecker = createCommentCheckerHooks()
const grepOutputTruncator = createGrepOutputTruncatorHook(ctx)
@@ -80,6 +81,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
event: async (input) => {
await todoContinuationEnforcer(input)
await contextWindowMonitor.event(input)
await pulseMonitor.event(input)
const { event } = input
const props = event.properties as Record<string, unknown> | undefined
@@ -172,6 +174,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
},
"tool.execute.before": async (input, output) => {
await pulseMonitor["tool.execute.before"]()
await commentChecker["tool.execute.before"](input, output)
if (input.sessionID === mainSessionID) {
@@ -186,6 +189,7 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => {
},
"tool.execute.after": async (input, output) => {
await pulseMonitor["tool.execute.after"](input)
await grepOutputTruncator["tool.execute.after"](input, output)
await contextWindowMonitor["tool.execute.after"](input, output)
await commentChecker["tool.execute.after"](input, output)