hooksConfigSnapshot.ts
utils/hooks/hooksConfigSnapshot.ts
No strong subsystem tag
134
Lines
5064
Bytes
6
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 134 lines, 5 detected imports, and 6 detected exports.
Important relationships
Detected exports
shouldAllowManagedHooksOnlyshouldDisableAllHooksIncludingManagedcaptureHooksConfigSnapshotupdateHooksConfigSnapshotgetHooksConfigFromSnapshotresetHooksConfigSnapshot
Keywords
hookssettingspolicysettingsmanageddisableallhooksnon-managedallowmanagedhooksonlysettingsmoduleinitialhooksconfigonly
Detected imports
../../bootstrap/state.js../settings/pluginOnlyPolicy.js../settings/settings.js../settings/settingsCache.js../settings/types.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 { resetSdkInitState } from '../../bootstrap/state.js'
import { isRestrictedToPluginOnly } from '../settings/pluginOnlyPolicy.js'
// Import as module object so spyOn works in tests (direct imports bypass spies)
import * as settingsModule from '../settings/settings.js'
import { resetSettingsCache } from '../settings/settingsCache.js'
import type { HooksSettings } from '../settings/types.js'
let initialHooksConfig: HooksSettings | null = null
/**
* Get hooks from allowed sources.
* If allowManagedHooksOnly is set in policySettings, only managed hooks are returned.
* If disableAllHooks is set in policySettings, no hooks are returned.
* If disableAllHooks is set in non-managed settings, only managed hooks are returned
* (non-managed settings cannot disable managed hooks).
* Otherwise, returns merged hooks from all sources (backwards compatible).
*/
function getHooksFromAllowedSources(): HooksSettings {
const policySettings = settingsModule.getSettingsForSource('policySettings')
// If managed settings disables all hooks, return empty
if (policySettings?.disableAllHooks === true) {
return {}
}
// If allowManagedHooksOnly is set in managed settings, only use managed hooks
if (policySettings?.allowManagedHooksOnly === true) {
return policySettings.hooks ?? {}
}
// strictPluginOnlyCustomization: block user/project/local settings hooks.
// Plugin hooks (registered channel, hooks.ts:1391) are NOT affected —
// they're assembled separately and the managedOnly skip there is keyed
// on shouldAllowManagedHooksOnly(), not on this policy. Agent frontmatter
// hooks are gated at REGISTRATION (runAgent.ts:~535) by agent source —
// plugin/built-in/policySettings agents register normally, user-sourced
// agents skip registration under ["hooks"]. A blanket execution-time
// block here would over-kill plugin agents' hooks.
if (isRestrictedToPluginOnly('hooks')) {
return policySettings?.hooks ?? {}
}
const mergedSettings = settingsModule.getSettings_DEPRECATED()
// If disableAllHooks is set in non-managed settings, only managed hooks still run
// (non-managed settings cannot override managed hooks)
if (mergedSettings.disableAllHooks === true) {
return policySettings?.hooks ?? {}
}
// Otherwise, use all hooks (merged from all sources) - backwards compatible
return mergedSettings.hooks ?? {}
}
/**
* Check if only managed hooks should run.
* This is true when:
* - policySettings has allowManagedHooksOnly: true, OR
* - disableAllHooks is set in non-managed settings (non-managed settings
* cannot disable managed hooks, so they effectively become managed-only)
*/
export function shouldAllowManagedHooksOnly(): boolean {
const policySettings = settingsModule.getSettingsForSource('policySettings')
if (policySettings?.allowManagedHooksOnly === true) {
return true
}
// If disableAllHooks is set but NOT from managed settings,
// treat as managed-only (non-managed hooks disabled, managed hooks still run)
if (
settingsModule.getSettings_DEPRECATED().disableAllHooks === true &&
policySettings?.disableAllHooks !== true
) {
return true
}
return false
}
/**
* Check if all hooks (including managed) should be disabled.
* This is only true when managed/policy settings has disableAllHooks: true.
* When disableAllHooks is set in non-managed settings, managed hooks still run.
*/
export function shouldDisableAllHooksIncludingManaged(): boolean {
return (
settingsModule.getSettingsForSource('policySettings')?.disableAllHooks ===
true
)
}
/**
* Capture a snapshot of the current hooks configuration
* This should be called once during application startup
* Respects the allowManagedHooksOnly setting
*/
export function captureHooksConfigSnapshot(): void {
initialHooksConfig = getHooksFromAllowedSources()
}
/**
* Update the hooks configuration snapshot
* This should be called when hooks are modified through the settings
* Respects the allowManagedHooksOnly setting
*/
export function updateHooksConfigSnapshot(): void {
// Reset the session cache to ensure we read fresh settings from disk.
// Without this, the snapshot could use stale cached settings when the user
// edits settings.json externally and then runs /hooks - the session cache
// may not have been invalidated yet (e.g., if the file watcher's stability
// threshold hasn't elapsed).
resetSettingsCache()
initialHooksConfig = getHooksFromAllowedSources()
}
/**
* Get the current hooks configuration from snapshot
* Falls back to settings if no snapshot exists
* @returns The hooks configuration
*/
export function getHooksConfigFromSnapshot(): HooksSettings | null {
if (initialHooksConfig === null) {
captureHooksConfigSnapshot()
}
return initialHooksConfig
}
/**
* Reset the hooks configuration snapshot (useful for testing)
* Also resets SDK init state to prevent test pollution
*/
export function resetHooksConfigSnapshot(): void {
initialHooksConfig = null
resetSdkInitState()
}