forked from ultraworkers/claw-code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhooksConfigSnapshot.ts
More file actions
133 lines (119 loc) · 4.95 KB
/
Copy pathhooksConfigSnapshot.ts
File metadata and controls
133 lines (119 loc) · 4.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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()
}