registerFrontmatterHooks.ts
utils/hooks/registerFrontmatterHooks.ts
No strong subsystem tag
68
Lines
2277
Bytes
1
Exports
5
Imports
10
Keywords
What this is
This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.
Beginner explanation
This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.
How it is used
Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.
Expert explanation
Architecturally, this file intersects with general runtime concerns. It contains 68 lines, 5 detected imports, and 1 detected exports.
Important relationships
Detected exports
registerFrontmatterHooks
Keywords
hookssubagentstopagentsessionparamstopappstatesessionidsourcenamehookcount
Detected imports
src/entrypoints/agentSdkTypes.jssrc/state/AppState.js../debug.js../settings/types.js./sessionHooks.js
Source notes
This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.
Full source
import { HOOK_EVENTS, type HookEvent } from 'src/entrypoints/agentSdkTypes.js'
import type { AppState } from 'src/state/AppState.js'
import { logForDebugging } from '../debug.js'
import type { HooksSettings } from '../settings/types.js'
import { addSessionHook } from './sessionHooks.js'
/**
* Register hooks from frontmatter (agent or skill) into session-scoped hooks.
* These hooks will be active for the duration of the session/agent and cleaned up
* when the session/agent ends.
*
* @param setAppState Function to update app state
* @param sessionId Session ID to scope the hooks (agent ID for agents, session ID for skills)
* @param hooks The hooks settings from frontmatter
* @param sourceName Human-readable source name for logging (e.g., "agent 'my-agent'")
* @param isAgent If true, converts Stop hooks to SubagentStop (since subagents trigger SubagentStop, not Stop)
*/
export function registerFrontmatterHooks(
setAppState: (updater: (prev: AppState) => AppState) => void,
sessionId: string,
hooks: HooksSettings,
sourceName: string,
isAgent: boolean = false,
): void {
if (!hooks || Object.keys(hooks).length === 0) {
return
}
let hookCount = 0
for (const event of HOOK_EVENTS) {
const matchers = hooks[event]
if (!matchers || matchers.length === 0) {
continue
}
// For agents, convert Stop hooks to SubagentStop since that's what fires when an agent completes
// (executeStopHooks uses SubagentStop when called with an agentId)
let targetEvent: HookEvent = event
if (isAgent && event === 'Stop') {
targetEvent = 'SubagentStop'
logForDebugging(
`Converting Stop hook to SubagentStop for ${sourceName} (subagents trigger SubagentStop)`,
)
}
for (const matcherConfig of matchers) {
const matcher = matcherConfig.matcher ?? ''
const hooksArray = matcherConfig.hooks
if (!hooksArray || hooksArray.length === 0) {
continue
}
for (const hook of hooksArray) {
addSessionHook(setAppState, sessionId, targetEvent, matcher, hook)
hookCount++
}
}
}
if (hookCount > 0) {
logForDebugging(
`Registered ${hookCount} frontmatter hook(s) from ${sourceName} for session ${sessionId}`,
)
}
}