codemap.md 5.9 KB

src/hooks/

This directory exposes the public hook entry points that feature code imports to tap into behavior such as workflow reminders, error recovery, rate-limit fallback, and delegation guidance.

Responsibility

Acts as a single entry point that re-exports the factory functions and types for every hook implementation underneath src/hooks/, so other modules can import from a flat namespace without needing to know subpaths.

Design

  • Aggregator/re-export pattern: index.ts consolidates all hook factories and types for the entire hooks subsystem.
  • Factory-based design: Each hook is a factory function that returns a hook object with specific hook points (e.g., 'tool.execute.after', 'experimental.chat.messages.transform', 'chat.headers').
  • Modular architecture: Each hook lives in its own subdirectory with internal components (hook implementation, patterns, guidance, etc.).
  • Event-driven hooks: Hooks respond to OpenCode plugin events and modify output before it reaches the LLM or UI.

Flow

  1. Import: Feature modules import factories from src/hooks/index.ts (e.g., createPhaseReminderHook, createJsonErrorRecoveryHook).
  2. Configure: Call factory with any required context (e.g., PluginInput for client access).
  3. Register: Hook objects are registered with OpenCode's plugin system via the feature layer.
  4. Execute: At runtime, OpenCode invokes hook functions at specific points (tool execution, message transformation, event handling).
  5. Modify: Hooks inspect input/output and apply side-effects (inject text, modify headers, append guidance).

Integration

Hook Points

Hook Point Purpose Hooks
'tool.execute.after' Modify tool output after execution post-read-nudge, delegate-task-retry, json-error-recovery
'experimental.chat.messages.transform' Transform messages before API call phase-reminder
'chat.headers' Add custom headers to API requests chat-headers
Event handlers React to OpenCode events foreground-fallback

Hook Implementations

phase-reminder

  • Location: src/hooks/phase-reminder/index.ts
  • Purpose: Injects workflow reminder before each user message for the orchestrator agent to combat instruction-following degradation.
  • Hook Point: 'experimental.chat.messages.transform'
  • Behavior: Prepend reminder text to the last user message if agent is 'orchestrator' and message doesn't contain internal initiator marker.
  • Research: Based on "LLMs Get Lost In Multi-Turn Conversation" (arXiv:2505.06120) showing ~40% compliance drop after 2-3 turns without reminders.

post-read-nudge

  • Location: src/hooks/post-read-nudge/index.ts
  • Purpose: Appends delegation reminder after file reads to catch the "read files → implement myself" anti-pattern.
  • Hook Point: 'tool.execute.after'
  • Behavior: Appends nudge text to output when tool is 'Read' or 'read'.

chat-headers

  • Location: src/hooks/chat-headers.ts
  • Purpose: Adds x-initiator: agent header for GitHub Copilot provider when internal initiator marker is detected.
  • Hook Point: 'chat.headers'
  • Behavior: Checks for internal marker via API call, only applies to Copilot provider and non-Copilot npm model.
  • Caching: Uses in-memory cache (max 1000 entries) to reduce API calls.

delegate-task-retry

  • Location: src/hooks/delegate-task-retry/
  • Purpose: Detects delegate task errors and provides actionable retry guidance.
  • Components:
    • hook.ts: Main hook that detects errors and appends guidance.
    • patterns.ts: Defines error patterns and detection logic.
    • guidance.ts: Builds retry guidance messages with available options.
  • Hook Point: 'tool.execute.after'
  • Behavior: Detects errors like missing run_in_background, invalid category/agent, unknown skills, and appends structured guidance.
  • Patterns: 8 error types with specific fix hints and available options extraction.

foreground-fallback

  • Location: src/hooks/foreground-fallback/index.ts
  • Purpose: Runtime model fallback for foreground (interactive) agent sessions experiencing rate limits.
  • Hook Point: Event-driven (not a standard hook point)
  • Behavior:
    • Monitors message.updated, session.error, session.status, and subagent.session.created events.
    • Detects rate-limit signals via regex patterns.
    • Aborts rate-limited prompt via client.session.abort().
    • Re-queues last user message via client.session.promptAsync() with fallback model.
    • Tracks tried models per session to avoid infinite loops.
    • Deduplicates triggers within 5-second window.
  • Fallback Chains: Configurable per agent (e.g., { orchestrator: ['anthropic/claude-opus-4-5', 'openai/gpt-4o'] }).
  • Cleanup: Removes session state on session.deleted events.

json-error-recovery

  • Location: src/hooks/json-error-recovery/
  • Purpose: Detects JSON parse errors and provides immediate recovery guidance.
  • Components:
    • hook.ts: Main hook that detects JSON errors and appends guidance.
    • index.ts: Re-exports hook and constants.
  • Hook Point: 'tool.execute.after'
  • Behavior: Appends structured reminder when JSON parse errors are detected in tool output (excluding bash, read, glob, webfetch, etc.).
  • Patterns: 8 regex patterns covering common JSON syntax errors.

Dependencies

  • OpenCode SDK: @opencode-ai/plugin (PluginInput type, client access)
  • OpenCode SDK: @opencode-ai/sdk (Model, UserMessage types)
  • Internal Utils: hasInternalInitiatorMarker, SLIM_INTERNAL_INITIATOR_MARKER
  • Internal Logger: utils/logger

Consumers

  • Feature modules in src/ import hook factories from src/hooks/index.ts.
  • Plugin initialization in src/index.ts registers hooks with OpenCode's plugin system.
  • No direct relations to deeper hook files from consumers (implementation details hidden).