diff --git a/docs/configurations.md b/docs/configurations.md index a991895a..05a37d29 100644 --- a/docs/configurations.md +++ b/docs/configurations.md @@ -768,6 +768,8 @@ Disable specific built-in hooks via `disabled_hooks` in `~/.config/opencode/oh-m Available hooks: `todo-continuation-enforcer`, `context-window-monitor`, `session-recovery`, `session-notification`, `comment-checker`, `grep-output-truncator`, `tool-output-truncator`, `directory-agents-injector`, `directory-readme-injector`, `empty-task-response-detector`, `think-mode`, `anthropic-context-window-limit-recovery`, `rules-injector`, `background-notification`, `auto-update-checker`, `startup-toast`, `keyword-detector`, `agent-usage-reminder`, `non-interactive-env`, `interactive-bash-session`, `compaction-context-injector`, `thinking-block-validator`, `claude-code-hooks`, `ralph-loop`, `preemptive-compaction` +**Note on `directory-agents-injector`**: This hook is **automatically disabled** when running on OpenCode 1.1.37+ because OpenCode now has native support for dynamically resolving AGENTS.md files from subdirectories (PR #10678). This prevents duplicate AGENTS.md injection. For older OpenCode versions, the hook remains active to provide the same functionality. + **Note on `auto-update-checker` and `startup-toast`**: The `startup-toast` hook is a sub-feature of `auto-update-checker`. To disable only the startup toast notification while keeping update checking enabled, add `"startup-toast"` to `disabled_hooks`. To disable all update checking features (including the toast), add `"auto-update-checker"` to `disabled_hooks`. ## MCPs diff --git a/docs/features.md b/docs/features.md index 1f19f4fe..c2ae0984 100644 --- a/docs/features.md +++ b/docs/features.md @@ -320,7 +320,7 @@ Hooks intercept and modify behavior at key points in the agent lifecycle. | Hook | Event | Description | |------|-------|-------------| -| **directory-agents-injector** | PostToolUse | Auto-injects AGENTS.md when reading files. Walks from file to project root, collecting all AGENTS.md files. | +| **directory-agents-injector** | PostToolUse | Auto-injects AGENTS.md when reading files. Walks from file to project root, collecting all AGENTS.md files. **Deprecated for OpenCode 1.1.37+** - Auto-disabled when native AGENTS.md injection is available. | | **directory-readme-injector** | PostToolUse | Auto-injects README.md for directory context. | | **rules-injector** | PostToolUse | Injects rules from `.claude/rules/` when conditions match. Supports globs and alwaysApply. | | **compaction-context-injector** | Stop | Preserves critical context during session compaction. | diff --git a/src/index.ts b/src/index.ts index 3d83bc66..22ed4ebb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,7 +78,7 @@ import { SkillMcpManager } from "./features/skill-mcp-manager"; import { initTaskToastManager } from "./features/task-toast-manager"; import { TmuxSessionManager } from "./features/tmux-subagent"; import { type HookName } from "./config"; -import { log, detectExternalNotificationPlugin, getNotificationConflictWarning, resetMessageCursor, includesCaseInsensitive, hasConnectedProvidersCache } from "./shared"; +import { log, detectExternalNotificationPlugin, getNotificationConflictWarning, resetMessageCursor, includesCaseInsensitive, hasConnectedProvidersCache, getOpenCodeVersion, isOpenCodeVersionAtLeast, OPENCODE_NATIVE_AGENTS_INJECTION_VERSION } from "./shared"; import { loadPluginConfig } from "./plugin-config"; import { createModelCacheState, getModelLimit } from "./plugin-state"; import { createConfigHandler } from "./plugin-handlers"; @@ -136,9 +136,26 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => { experimental: pluginConfig.experimental, }) : null; - const directoryAgentsInjector = isHookEnabled("directory-agents-injector") - ? createDirectoryAgentsInjectorHook(ctx) - : null; + // Check for native OpenCode AGENTS.md injection support before creating hook + let directoryAgentsInjector = null; + if (isHookEnabled("directory-agents-injector")) { + const currentVersion = getOpenCodeVersion(); + const hasNativeSupport = currentVersion !== null && + isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION); + + if (hasNativeSupport) { + console.warn( + `[oh-my-opencode] directory-agents-injector hook auto-disabled: ` + + `OpenCode ${currentVersion} has native AGENTS.md support (>= ${OPENCODE_NATIVE_AGENTS_INJECTION_VERSION})` + ); + log("directory-agents-injector auto-disabled due to native OpenCode support", { + currentVersion, + nativeVersion: OPENCODE_NATIVE_AGENTS_INJECTION_VERSION, + }); + } else { + directoryAgentsInjector = createDirectoryAgentsInjectorHook(ctx); + } + } const directoryReadmeInjector = isHookEnabled("directory-readme-injector") ? createDirectoryReadmeInjectorHook(ctx) : null; diff --git a/src/shared/opencode-version.test.ts b/src/shared/opencode-version.test.ts index d6b419c2..f5c57623 100644 --- a/src/shared/opencode-version.test.ts +++ b/src/shared/opencode-version.test.ts @@ -9,6 +9,7 @@ import { resetVersionCache, setVersionCache, MINIMUM_OPENCODE_VERSION, + OPENCODE_NATIVE_AGENTS_INJECTION_VERSION, } from "./opencode-version" describe("opencode-version", () => { @@ -220,4 +221,46 @@ describe("opencode-version", () => { expect(MINIMUM_OPENCODE_VERSION).toBe("1.1.1") }) }) + + describe("OPENCODE_NATIVE_AGENTS_INJECTION_VERSION", () => { + test("is set to 1.1.37", () => { + // #given the native agents injection version constant + // #when exported + // #then it should be 1.1.37 (PR #10678) + expect(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION).toBe("1.1.37") + }) + + test("version detection works correctly with native agents version", () => { + // #given OpenCode version at or above native agents injection version + setVersionCache("1.1.37") + + // #when checking against native agents version + const result = isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION) + + // #then returns true (native support available) + expect(result).toBe(true) + }) + + test("version detection returns false for older versions", () => { + // #given OpenCode version below native agents injection version + setVersionCache("1.1.36") + + // #when checking against native agents version + const result = isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION) + + // #then returns false (no native support) + expect(result).toBe(false) + }) + + test("returns true when version detection fails (fail-safe)", () => { + // #given version cannot be detected + setVersionCache(null) + + // #when checking against native agents version + const result = isOpenCodeVersionAtLeast(OPENCODE_NATIVE_AGENTS_INJECTION_VERSION) + + // #then returns true (assume latest, enable native support) + expect(result).toBe(true) + }) + }) }) diff --git a/src/shared/opencode-version.ts b/src/shared/opencode-version.ts index fab09552..dc9b8883 100644 --- a/src/shared/opencode-version.ts +++ b/src/shared/opencode-version.ts @@ -6,6 +6,15 @@ import { execSync } from "child_process" */ export const MINIMUM_OPENCODE_VERSION = "1.1.1" +/** + * OpenCode version that introduced native AGENTS.md injection. + * PR #10678 merged on Jan 26, 2026 - OpenCode now dynamically resolves + * AGENTS.md files from subdirectories as the agent explores them. + * When this version is detected, the directory-agents-injector hook + * is auto-disabled to prevent duplicate AGENTS.md loading. + */ +export const OPENCODE_NATIVE_AGENTS_INJECTION_VERSION = "1.1.37" + const NOT_CACHED = Symbol("NOT_CACHED") let cachedVersion: string | null | typeof NOT_CACHED = NOT_CACHED