Skip to content

feat: add HooksManager lifecycle hook system to callModel#7

Open
mattapperson wants to merge 5 commits intomainfrom
feat/hooks-manager
Open

feat: add HooksManager lifecycle hook system to callModel#7
mattapperson wants to merge 5 commits intomainfrom
feat/hooks-manager

Conversation

@mattapperson
Copy link
Copy Markdown
Collaborator

Summary

  • Adds an extensible hook system for callModel inspired by the Claude Agent SDK hooks pattern
  • Two usage modes: inline config (plain object for quick setup) and HooksManager class (custom hooks, dynamic registration, programmatic emit)
  • 8 built-in hooks: PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, Stop, PermissionRequest, SessionStart, SessionEnd
  • Features: tool matchers (string/RegExp/function), filter predicates, mutation piping, short-circuit on block/reject, async fire-and-forget handlers, configurable error handling
  • Custom hook definitions via Zod schema pairs with full TypeScript autocomplete
  • Additive API — existing onTurnStart, onTurnEnd, requireApproval remain unchanged

Re-creation of OpenRouterTeam/openrouter-web#16735 on the standalone agent SDK repo.

Test plan

  • 35 new unit tests across 4 test files (matchers, emit engine, manager class, resolver)
  • All 186 unit tests pass
  • Build (pnpm build) passes cleanly
  • Lint (pnpm lint) passes cleanly
  • E2E testing with real API calls (PreToolUse block, mutation piping, Stop forceResume)

Implements an extensible hook system for callModel inspired by the
Claude Agent SDK hooks pattern. Supports inline config for quick
declarative usage and a HooksManager class for custom hooks,
dynamic registration, and programmatic emit.

Built-in hooks: PreToolUse, PostToolUse, PostToolUseFailure,
UserPromptSubmit, Stop, PermissionRequest, SessionStart, SessionEnd.

Features: tool matchers (string/RegExp/function), filter predicates,
mutation piping, short-circuit on block/reject, async fire-and-forget
handlers, configurable error handling, and custom hook definitions
via Zod schema pairs.
81 edge-case tests covering handler chain execution, manager lifecycle,
tool matchers, resolver normalization, and async output detection.
Surfaces real issues: filter throws bypass error handling, global RegExp
stateful .test(), and function matcher lacking boolean coercion.
test: add adversarial unit tests for hooks system
Resolves conflicts in src/index.ts (keep both hooks exports and
new OpenRouter/SDKOptions exports) and src/inner-loop/call-model.ts
(keep both resolveHooks and Tool type imports).

Adapts hooks files to Biome linter rules introduced on main:
import ordering, block statements, and sparse-array/void-type
suppressions where the behavior is intentional.
Fixes CI failure on `validate` job by applying Biome's auto-fixes for
import sorting in async-params.ts and model-result.ts, and formatting
in hooks-matchers.ts, hooks-schemas.ts, model-result.ts, and
conversation-state.test.ts.
Copy link
Copy Markdown
Collaborator Author

@mattapperson mattapperson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewed, no issues found

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant