Files
oh-my-openagent/src/hooks/non-interactive-env/index.ts
YeonGyu-Kim 8d9b68d84b Prevent premature exit in non-interactive mode when tasks pending (#216) (#217)
Detects non-interactive environments (CI, opencode run) and prevents session idle when:
- Background tasks are still running
- Incomplete todos remain in the queue

Changes:
- Add isNonInteractive() detector for CI/headless environment detection
- Export detector from non-interactive-env hook module
- Enhance todo-continuation-enforcer to inject prompts BEFORE session.idle
- Pass BackgroundManager to todo-continuation-enforcer for task status checks

This fix prevents `opencode run` from exiting prematurely when work is pending.

🤖 Generated with assistance of OhMyOpenCode (https://github.com/code-yeongyu/oh-my-opencode)
2025-12-25 15:27:34 +09:00

54 lines
1.6 KiB
TypeScript

import type { PluginInput } from "@opencode-ai/plugin"
import { HOOK_NAME, NON_INTERACTIVE_ENV, SHELL_COMMAND_PATTERNS } from "./constants"
import { log } from "../../shared"
export * from "./constants"
export * from "./detector"
export * from "./types"
const BANNED_COMMAND_PATTERNS = SHELL_COMMAND_PATTERNS.banned
.filter((cmd) => !cmd.includes("("))
.map((cmd) => new RegExp(`\\b${cmd}\\b`))
function detectBannedCommand(command: string): string | undefined {
for (let i = 0; i < BANNED_COMMAND_PATTERNS.length; i++) {
if (BANNED_COMMAND_PATTERNS[i].test(command)) {
return SHELL_COMMAND_PATTERNS.banned[i]
}
}
return undefined
}
export function createNonInteractiveEnvHook(_ctx: PluginInput) {
return {
"tool.execute.before": async (
input: { tool: string; sessionID: string; callID: string },
output: { args: Record<string, unknown>; message?: string }
): Promise<void> => {
if (input.tool.toLowerCase() !== "bash") {
return
}
const command = output.args.command as string | undefined
if (!command) {
return
}
output.args.env = {
...(output.args.env as Record<string, string> | undefined),
...NON_INTERACTIVE_ENV,
}
const bannedCmd = detectBannedCommand(command)
if (bannedCmd) {
output.message = `⚠️ Warning: '${bannedCmd}' is an interactive command that may hang in non-interactive environments.`
}
log(`[${HOOK_NAME}] Set non-interactive environment variables`, {
sessionID: input.sessionID,
env: NON_INTERACTIVE_ENV,
})
},
}
}