@google/gemini-cli-core 0.13.0-nightly.20251103.9187f6f6 → 0.13.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/dist/google-gemini-cli-core-0.13.0-nightly.20251031.c89bc30d.tgz +0 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +2 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/agents/executor.d.ts +19 -0
  6. package/dist/src/agents/executor.js +226 -32
  7. package/dist/src/agents/executor.js.map +1 -1
  8. package/dist/src/agents/executor.test.js +335 -9
  9. package/dist/src/agents/executor.test.js.map +1 -1
  10. package/dist/src/agents/types.d.ts +2 -1
  11. package/dist/src/agents/types.js +1 -0
  12. package/dist/src/agents/types.js.map +1 -1
  13. package/dist/src/code_assist/experiments/client_metadata.d.ts +12 -0
  14. package/dist/src/code_assist/experiments/client_metadata.js +49 -0
  15. package/dist/src/code_assist/experiments/client_metadata.js.map +1 -0
  16. package/dist/src/code_assist/experiments/experiments.d.ts +17 -0
  17. package/dist/src/code_assist/experiments/experiments.js +36 -0
  18. package/dist/src/code_assist/experiments/experiments.js.map +1 -0
  19. package/dist/src/code_assist/experiments/types.d.ts +35 -0
  20. package/dist/src/code_assist/experiments/types.js +7 -0
  21. package/dist/src/code_assist/experiments/types.js.map +1 -0
  22. package/dist/src/code_assist/server.d.ts +3 -1
  23. package/dist/src/code_assist/server.js +11 -0
  24. package/dist/src/code_assist/server.js.map +1 -1
  25. package/dist/src/code_assist/server.test.js +17 -0
  26. package/dist/src/code_assist/server.test.js.map +1 -1
  27. package/dist/src/code_assist/types.d.ts +1 -1
  28. package/dist/src/code_assist/types.js.map +1 -1
  29. package/dist/src/config/config.d.ts +35 -54
  30. package/dist/src/config/config.js +110 -53
  31. package/dist/src/config/config.js.map +1 -1
  32. package/dist/src/config/config.test.js +132 -1
  33. package/dist/src/config/config.test.js.map +1 -1
  34. package/dist/src/config/models.d.ts +1 -1
  35. package/dist/src/config/models.js +2 -2
  36. package/dist/src/config/models.js.map +1 -1
  37. package/dist/src/config/storage.d.ts +2 -0
  38. package/dist/src/config/storage.js +17 -0
  39. package/dist/src/config/storage.js.map +1 -1
  40. package/dist/src/core/apiKeyCredentialStorage.js +7 -7
  41. package/dist/src/core/apiKeyCredentialStorage.js.map +1 -1
  42. package/dist/src/core/apiKeyCredentialStorage.test.js +5 -0
  43. package/dist/src/core/apiKeyCredentialStorage.test.js.map +1 -1
  44. package/dist/src/core/logger.js +10 -9
  45. package/dist/src/core/logger.js.map +1 -1
  46. package/dist/src/core/prompts.js +104 -55
  47. package/dist/src/core/prompts.js.map +1 -1
  48. package/dist/src/generated/git-commit.d.ts +2 -2
  49. package/dist/src/generated/git-commit.js +2 -2
  50. package/dist/src/generated/git-commit.js.map +1 -1
  51. package/dist/src/hooks/hookPlanner.d.ts +46 -0
  52. package/dist/src/hooks/hookPlanner.js +108 -0
  53. package/dist/src/hooks/hookPlanner.js.map +1 -0
  54. package/dist/src/hooks/hookPlanner.test.d.ts +6 -0
  55. package/dist/src/hooks/hookPlanner.test.js +255 -0
  56. package/dist/src/hooks/hookPlanner.test.js.map +1 -0
  57. package/dist/src/hooks/hookRegistry.d.ts +87 -0
  58. package/dist/src/hooks/hookRegistry.js +198 -0
  59. package/dist/src/hooks/hookRegistry.js.map +1 -0
  60. package/dist/src/hooks/hookRegistry.test.d.ts +6 -0
  61. package/dist/src/hooks/hookRegistry.test.js +341 -0
  62. package/dist/src/hooks/hookRegistry.test.js.map +1 -0
  63. package/dist/src/hooks/hookTranslator.d.ts +113 -0
  64. package/dist/src/hooks/hookTranslator.js +232 -0
  65. package/dist/src/hooks/hookTranslator.js.map +1 -0
  66. package/dist/src/hooks/hookTranslator.test.d.ts +6 -0
  67. package/dist/src/hooks/hookTranslator.test.js +192 -0
  68. package/dist/src/hooks/hookTranslator.test.js.map +1 -0
  69. package/dist/src/hooks/types.d.ts +384 -0
  70. package/dist/src/hooks/types.js +284 -0
  71. package/dist/src/hooks/types.js.map +1 -0
  72. package/dist/src/hooks/types.test.d.ts +6 -0
  73. package/dist/src/hooks/types.test.js +35 -0
  74. package/dist/src/hooks/types.test.js.map +1 -0
  75. package/dist/src/index.d.ts +3 -0
  76. package/dist/src/index.js +4 -0
  77. package/dist/src/index.js.map +1 -1
  78. package/dist/src/mcp/oauth-provider.d.ts +5 -1
  79. package/dist/src/mcp/oauth-provider.js +58 -23
  80. package/dist/src/mcp/oauth-provider.js.map +1 -1
  81. package/dist/src/mcp/oauth-provider.test.js +2 -1
  82. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  83. package/dist/src/mcp/token-storage/file-token-storage.js +1 -1
  84. package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -1
  85. package/dist/src/mcp/token-storage/file-token-storage.test.js +7 -5
  86. package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -1
  87. package/dist/src/mcp/token-storage/keychain-token-storage.js +2 -2
  88. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  89. package/dist/src/policy/config.d.ts +31 -0
  90. package/dist/src/policy/config.js +197 -0
  91. package/dist/src/policy/config.js.map +1 -0
  92. package/dist/src/policy/config.test.d.ts +6 -0
  93. package/dist/src/policy/config.test.js +404 -0
  94. package/dist/src/policy/config.test.js.map +1 -0
  95. package/dist/src/policy/index.d.ts +2 -0
  96. package/dist/src/policy/index.js +2 -0
  97. package/dist/src/policy/index.js.map +1 -1
  98. package/dist/src/policy/policies/read-only.toml +56 -0
  99. package/dist/src/policy/policies/write.toml +63 -0
  100. package/dist/src/policy/policies/yolo.toml +31 -0
  101. package/dist/src/policy/toml-loader.d.ts +46 -0
  102. package/dist/src/policy/toml-loader.js +314 -0
  103. package/dist/src/policy/toml-loader.js.map +1 -0
  104. package/dist/src/policy/toml-loader.test.d.ts +6 -0
  105. package/dist/src/policy/toml-loader.test.js +522 -0
  106. package/dist/src/policy/toml-loader.test.js.map +1 -0
  107. package/dist/src/policy/types.d.ts +18 -0
  108. package/dist/src/policy/types.js +6 -0
  109. package/dist/src/policy/types.js.map +1 -1
  110. package/dist/src/services/chatCompressionService.js +2 -1
  111. package/dist/src/services/chatCompressionService.js.map +1 -1
  112. package/dist/src/services/chatRecordingService.js +9 -8
  113. package/dist/src/services/chatRecordingService.js.map +1 -1
  114. package/dist/src/services/loopDetectionService.d.ts +1 -1
  115. package/dist/src/services/loopDetectionService.js +3 -3
  116. package/dist/src/services/loopDetectionService.js.map +1 -1
  117. package/dist/src/services/loopDetectionService.test.js +69 -0
  118. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  119. package/dist/src/services/shellExecutionService.js +18 -4
  120. package/dist/src/services/shellExecutionService.js.map +1 -1
  121. package/dist/src/services/shellExecutionService.test.js +16 -4
  122. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  123. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +3 -1
  124. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +31 -0
  125. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  126. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +4 -1
  127. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +6 -0
  128. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  129. package/dist/src/telemetry/loggers.d.ts +2 -1
  130. package/dist/src/telemetry/loggers.js +13 -1
  131. package/dist/src/telemetry/loggers.js.map +1 -1
  132. package/dist/src/telemetry/loggers.test.js +10 -5
  133. package/dist/src/telemetry/loggers.test.js.map +1 -1
  134. package/dist/src/telemetry/metrics.d.ts +21 -1
  135. package/dist/src/telemetry/metrics.js +34 -0
  136. package/dist/src/telemetry/metrics.js.map +1 -1
  137. package/dist/src/telemetry/metrics.test.js +43 -126
  138. package/dist/src/telemetry/metrics.test.js.map +1 -1
  139. package/dist/src/telemetry/types.d.ts +24 -10
  140. package/dist/src/telemetry/types.js +47 -19
  141. package/dist/src/telemetry/types.js.map +1 -1
  142. package/dist/src/tools/edit.js +1 -1
  143. package/dist/src/tools/edit.js.map +1 -1
  144. package/dist/src/tools/edit.test.js +1 -1
  145. package/dist/src/tools/edit.test.js.map +1 -1
  146. package/dist/src/tools/mcp-client-manager.d.ts +31 -6
  147. package/dist/src/tools/mcp-client-manager.js +111 -41
  148. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  149. package/dist/src/tools/mcp-client-manager.test.js +130 -38
  150. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  151. package/dist/src/tools/mcp-client.d.ts +1 -0
  152. package/dist/src/tools/mcp-client.js +4 -4
  153. package/dist/src/tools/mcp-client.js.map +1 -1
  154. package/dist/src/tools/mcp-client.test.js +49 -0
  155. package/dist/src/tools/mcp-client.test.js.map +1 -1
  156. package/dist/src/tools/shell.js +1 -1
  157. package/dist/src/tools/shell.js.map +1 -1
  158. package/dist/src/tools/smart-edit.d.ts +1 -1
  159. package/dist/src/tools/smart-edit.js +12 -1
  160. package/dist/src/tools/smart-edit.js.map +1 -1
  161. package/dist/src/tools/smart-edit.test.js +2 -1
  162. package/dist/src/tools/smart-edit.test.js.map +1 -1
  163. package/dist/src/tools/tool-registry.d.ts +1 -18
  164. package/dist/src/tools/tool-registry.js +1 -44
  165. package/dist/src/tools/tool-registry.js.map +1 -1
  166. package/dist/src/tools/tool-registry.test.js +2 -24
  167. package/dist/src/tools/tool-registry.test.js.map +1 -1
  168. package/dist/src/tools/web-fetch.js +3 -6
  169. package/dist/src/tools/web-fetch.js.map +1 -1
  170. package/dist/src/tools/web-fetch.test.js +1 -1
  171. package/dist/src/tools/web-fetch.test.js.map +1 -1
  172. package/dist/src/tools/write-file.js +1 -1
  173. package/dist/src/tools/write-file.js.map +1 -1
  174. package/dist/src/tools/write-file.test.js +1 -1
  175. package/dist/src/tools/write-file.test.js.map +1 -1
  176. package/dist/src/utils/channel.d.ts +1 -0
  177. package/dist/src/utils/channel.js +4 -4
  178. package/dist/src/utils/channel.js.map +1 -1
  179. package/dist/src/utils/channel.test.js +35 -1
  180. package/dist/src/utils/channel.test.js.map +1 -1
  181. package/dist/src/utils/events.d.ts +18 -1
  182. package/dist/src/utils/events.js +8 -0
  183. package/dist/src/utils/events.js.map +1 -1
  184. package/dist/src/utils/events.test.js +10 -0
  185. package/dist/src/utils/events.test.js.map +1 -1
  186. package/dist/src/utils/extensionLoader.d.ts +67 -27
  187. package/dist/src/utils/extensionLoader.js +149 -7
  188. package/dist/src/utils/extensionLoader.js.map +1 -1
  189. package/dist/src/utils/extensionLoader.test.d.ts +6 -0
  190. package/dist/src/utils/extensionLoader.test.js +90 -0
  191. package/dist/src/utils/extensionLoader.test.js.map +1 -0
  192. package/dist/src/utils/fetch.js +1 -6
  193. package/dist/src/utils/fetch.js.map +1 -1
  194. package/dist/src/utils/llm-edit-fixer.d.ts +1 -1
  195. package/dist/src/utils/llm-edit-fixer.js +27 -3
  196. package/dist/src/utils/llm-edit-fixer.js.map +1 -1
  197. package/dist/src/utils/llm-edit-fixer.test.js +21 -0
  198. package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
  199. package/dist/src/utils/shell-utils.js +29 -1
  200. package/dist/src/utils/shell-utils.js.map +1 -1
  201. package/dist/src/utils/shell-utils.test.js +18 -0
  202. package/dist/src/utils/shell-utils.test.js.map +1 -1
  203. package/dist/tsconfig.tsbuildinfo +1 -1
  204. package/package.json +4 -2
@@ -0,0 +1,255 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
7
+ import { HookPlanner } from './hookPlanner.js';
8
+ import { HookEventName, HookType } from './types.js';
9
+ import { ConfigSource } from './hookRegistry.js';
10
+ // Mock debugLogger using vi.hoisted
11
+ const mockDebugLogger = vi.hoisted(() => ({
12
+ log: vi.fn(),
13
+ warn: vi.fn(),
14
+ error: vi.fn(),
15
+ debug: vi.fn(),
16
+ }));
17
+ vi.mock('../utils/debugLogger.js', () => ({
18
+ debugLogger: mockDebugLogger,
19
+ }));
20
+ describe('HookPlanner', () => {
21
+ let hookPlanner;
22
+ let mockHookRegistry;
23
+ beforeEach(() => {
24
+ vi.resetAllMocks();
25
+ mockHookRegistry = {
26
+ getHooksForEvent: vi.fn(),
27
+ };
28
+ hookPlanner = new HookPlanner(mockHookRegistry);
29
+ });
30
+ describe('createExecutionPlan', () => {
31
+ it('should return empty plan when no hooks registered', () => {
32
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue([]);
33
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool);
34
+ expect(plan).toBeNull();
35
+ });
36
+ it('should create plan for hooks without matchers', () => {
37
+ const mockEntries = [
38
+ {
39
+ config: { type: HookType.Command, command: './hook1.sh' },
40
+ source: ConfigSource.Project,
41
+ eventName: HookEventName.BeforeTool,
42
+ enabled: true,
43
+ },
44
+ {
45
+ config: {
46
+ type: HookType.Command,
47
+ command: './test-hook.sh',
48
+ },
49
+ source: ConfigSource.User,
50
+ eventName: HookEventName.BeforeTool,
51
+ enabled: true,
52
+ },
53
+ ];
54
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
55
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool);
56
+ expect(plan).not.toBeNull();
57
+ expect(plan.hookConfigs).toHaveLength(2);
58
+ expect(plan.hookConfigs[0].command).toBe('./hook1.sh');
59
+ expect(plan.hookConfigs[1].command).toBe('./test-hook.sh');
60
+ });
61
+ it('should filter hooks by tool name matcher', () => {
62
+ const mockEntries = [
63
+ {
64
+ config: { type: HookType.Command, command: './edit_hook.sh' },
65
+ source: ConfigSource.Project,
66
+ eventName: HookEventName.BeforeTool,
67
+ matcher: 'EditTool',
68
+ enabled: true,
69
+ },
70
+ {
71
+ config: { type: HookType.Command, command: './general_hook.sh' },
72
+ source: ConfigSource.Project,
73
+ eventName: HookEventName.BeforeTool,
74
+ enabled: true,
75
+ },
76
+ ];
77
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
78
+ // Test with EditTool context
79
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, {
80
+ toolName: 'EditTool',
81
+ });
82
+ expect(plan).not.toBeNull();
83
+ expect(plan.hookConfigs).toHaveLength(2); // Both should match (one specific, one general)
84
+ });
85
+ it('should filter hooks by regex matcher', () => {
86
+ const mockEntries = [
87
+ {
88
+ config: { type: HookType.Command, command: './edit_hook.sh' },
89
+ source: ConfigSource.Project,
90
+ eventName: HookEventName.BeforeTool,
91
+ matcher: 'Edit|Write',
92
+ enabled: true,
93
+ },
94
+ {
95
+ config: { type: HookType.Command, command: './read_hook.sh' },
96
+ source: ConfigSource.Project,
97
+ eventName: HookEventName.BeforeTool,
98
+ matcher: 'ReadTool',
99
+ enabled: true,
100
+ },
101
+ ];
102
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
103
+ // Test with EditTool - should match first hook
104
+ const editPlan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, { toolName: 'EditTool' });
105
+ expect(editPlan).not.toBeNull();
106
+ expect(editPlan.hookConfigs).toHaveLength(1);
107
+ expect(editPlan.hookConfigs[0].command).toBe('./edit_hook.sh');
108
+ // Test with WriteTool - should match first hook
109
+ const writePlan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, { toolName: 'WriteTool' });
110
+ expect(writePlan).not.toBeNull();
111
+ expect(writePlan.hookConfigs).toHaveLength(1);
112
+ expect(writePlan.hookConfigs[0].command).toBe('./edit_hook.sh');
113
+ // Test with ReadTool - should match second hook
114
+ const readPlan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, { toolName: 'ReadTool' });
115
+ expect(readPlan).not.toBeNull();
116
+ expect(readPlan.hookConfigs).toHaveLength(1);
117
+ expect(readPlan.hookConfigs[0].command).toBe('./read_hook.sh');
118
+ // Test with unmatched tool - should match no hooks
119
+ const otherPlan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, { toolName: 'OtherTool' });
120
+ expect(otherPlan).toBeNull();
121
+ });
122
+ it('should handle wildcard matcher', () => {
123
+ const mockEntries = [
124
+ {
125
+ config: { type: HookType.Command, command: './wildcard_hook.sh' },
126
+ source: ConfigSource.Project,
127
+ eventName: HookEventName.BeforeTool,
128
+ matcher: '*',
129
+ enabled: true,
130
+ },
131
+ ];
132
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
133
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, {
134
+ toolName: 'AnyTool',
135
+ });
136
+ expect(plan).not.toBeNull();
137
+ expect(plan.hookConfigs).toHaveLength(1);
138
+ });
139
+ it('should handle empty string matcher', () => {
140
+ const mockEntries = [
141
+ {
142
+ config: {
143
+ type: HookType.Command,
144
+ command: './empty_matcher_hook.sh',
145
+ },
146
+ source: ConfigSource.Project,
147
+ eventName: HookEventName.BeforeTool,
148
+ matcher: '',
149
+ enabled: true,
150
+ },
151
+ ];
152
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
153
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, {
154
+ toolName: 'AnyTool',
155
+ });
156
+ expect(plan).not.toBeNull();
157
+ expect(plan.hookConfigs).toHaveLength(1);
158
+ });
159
+ it('should handle invalid regex matcher gracefully', () => {
160
+ const mockEntries = [
161
+ {
162
+ config: {
163
+ type: HookType.Command,
164
+ command: './invalid_regex_hook.sh',
165
+ },
166
+ source: ConfigSource.Project,
167
+ eventName: HookEventName.BeforeTool,
168
+ matcher: '[invalid-regex',
169
+ enabled: true,
170
+ },
171
+ ];
172
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
173
+ // Should match when toolName exactly equals the invalid regex pattern
174
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, {
175
+ toolName: '[invalid-regex',
176
+ });
177
+ expect(plan).not.toBeNull();
178
+ expect(plan.hookConfigs).toHaveLength(1); // Should fall back to exact match
179
+ // Should not match when toolName doesn't exactly equal the pattern
180
+ const planNoMatch = hookPlanner.createExecutionPlan(HookEventName.BeforeTool, {
181
+ toolName: 'other-tool',
182
+ });
183
+ expect(planNoMatch).toBeNull();
184
+ });
185
+ it('should deduplicate identical hooks', () => {
186
+ const mockEntries = [
187
+ {
188
+ config: { type: HookType.Command, command: './same_hook.sh' },
189
+ source: ConfigSource.Project,
190
+ eventName: HookEventName.BeforeTool,
191
+ enabled: true,
192
+ },
193
+ {
194
+ config: { type: HookType.Command, command: './same_hook.sh' },
195
+ source: ConfigSource.User,
196
+ eventName: HookEventName.BeforeTool,
197
+ enabled: true,
198
+ },
199
+ {
200
+ config: {
201
+ type: HookType.Command,
202
+ command: './test-hook.sh',
203
+ },
204
+ source: ConfigSource.Project,
205
+ eventName: HookEventName.BeforeTool,
206
+ enabled: true,
207
+ },
208
+ {
209
+ config: {
210
+ type: HookType.Command,
211
+ command: './test-hook.sh',
212
+ },
213
+ source: ConfigSource.User,
214
+ eventName: HookEventName.BeforeTool,
215
+ enabled: true,
216
+ },
217
+ ];
218
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
219
+ const plan = hookPlanner.createExecutionPlan(HookEventName.BeforeTool);
220
+ expect(plan).not.toBeNull();
221
+ expect(plan.hookConfigs).toHaveLength(2); // Should be deduplicated to 2 unique hooks
222
+ expect(mockDebugLogger.debug).toHaveBeenCalledWith(expect.stringContaining('Deduplicated hook'));
223
+ });
224
+ it('should match trigger for session events', () => {
225
+ const mockEntries = [
226
+ {
227
+ config: { type: HookType.Command, command: './startup_hook.sh' },
228
+ source: ConfigSource.Project,
229
+ eventName: HookEventName.SessionStart,
230
+ matcher: 'startup',
231
+ enabled: true,
232
+ },
233
+ {
234
+ config: { type: HookType.Command, command: './resume_hook.sh' },
235
+ source: ConfigSource.Project,
236
+ eventName: HookEventName.SessionStart,
237
+ matcher: 'resume',
238
+ enabled: true,
239
+ },
240
+ ];
241
+ vi.mocked(mockHookRegistry.getHooksForEvent).mockReturnValue(mockEntries);
242
+ // Test startup trigger
243
+ const startupPlan = hookPlanner.createExecutionPlan(HookEventName.SessionStart, { trigger: 'startup' });
244
+ expect(startupPlan).not.toBeNull();
245
+ expect(startupPlan.hookConfigs).toHaveLength(1);
246
+ expect(startupPlan.hookConfigs[0].command).toBe('./startup_hook.sh');
247
+ // Test resume trigger
248
+ const resumePlan = hookPlanner.createExecutionPlan(HookEventName.SessionStart, { trigger: 'resume' });
249
+ expect(resumePlan).not.toBeNull();
250
+ expect(resumePlan.hookConfigs).toHaveLength(1);
251
+ expect(resumePlan.hookConfigs[0].command).toBe('./resume_hook.sh');
252
+ });
253
+ });
254
+ });
255
+ //# sourceMappingURL=hookPlanner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hookPlanner.test.js","sourceRoot":"","sources":["../../../src/hooks/hookPlanner.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import type { Config } from '../config/config.js';
7
+ import type { HookConfig } from './types.js';
8
+ import { HookEventName } from './types.js';
9
+ /**
10
+ * Error thrown when attempting to use HookRegistry before initialization
11
+ */
12
+ export declare class HookRegistryNotInitializedError extends Error {
13
+ constructor(message?: string);
14
+ }
15
+ /**
16
+ * Configuration source levels in precedence order (highest to lowest)
17
+ */
18
+ export declare enum ConfigSource {
19
+ Project = "project",
20
+ User = "user",
21
+ System = "system",
22
+ Extensions = "extensions"
23
+ }
24
+ /**
25
+ * Hook registry entry with source information
26
+ */
27
+ export interface HookRegistryEntry {
28
+ config: HookConfig;
29
+ source: ConfigSource;
30
+ eventName: HookEventName;
31
+ matcher?: string;
32
+ sequential?: boolean;
33
+ enabled: boolean;
34
+ }
35
+ /**
36
+ * Hook registry that loads and validates hook definitions from multiple sources
37
+ */
38
+ export declare class HookRegistry {
39
+ private readonly config;
40
+ private entries;
41
+ private initialized;
42
+ constructor(config: Config);
43
+ /**
44
+ * Initialize the registry by processing hooks from config
45
+ */
46
+ initialize(): Promise<void>;
47
+ /**
48
+ * Get all hook entries for a specific event
49
+ */
50
+ getHooksForEvent(eventName: HookEventName): HookRegistryEntry[];
51
+ /**
52
+ * Get all registered hooks
53
+ */
54
+ getAllHooks(): HookRegistryEntry[];
55
+ /**
56
+ * Enable or disable a specific hook
57
+ */
58
+ setHookEnabled(hookName: string, enabled: boolean): void;
59
+ /**
60
+ * Get hook name for display purposes
61
+ */
62
+ private getHookName;
63
+ /**
64
+ * Process hooks from the config that was already loaded by the CLI
65
+ */
66
+ private processHooksFromConfig;
67
+ /**
68
+ * Process hooks configuration and add entries
69
+ */
70
+ private processHooksConfiguration;
71
+ /**
72
+ * Process a single hook definition
73
+ */
74
+ private processHookDefinition;
75
+ /**
76
+ * Validate a hook configuration
77
+ */
78
+ private validateHookConfig;
79
+ /**
80
+ * Check if an event name is valid
81
+ */
82
+ private isValidEventName;
83
+ /**
84
+ * Get source priority (lower number = higher priority)
85
+ */
86
+ private getSourcePriority;
87
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { HookEventName } from './types.js';
7
+ import { debugLogger } from '../utils/debugLogger.js';
8
+ /**
9
+ * Error thrown when attempting to use HookRegistry before initialization
10
+ */
11
+ export class HookRegistryNotInitializedError extends Error {
12
+ constructor(message = 'Hook registry not initialized') {
13
+ super(message);
14
+ this.name = 'HookRegistryNotInitializedError';
15
+ }
16
+ }
17
+ /**
18
+ * Configuration source levels in precedence order (highest to lowest)
19
+ */
20
+ export var ConfigSource;
21
+ (function (ConfigSource) {
22
+ ConfigSource["Project"] = "project";
23
+ ConfigSource["User"] = "user";
24
+ ConfigSource["System"] = "system";
25
+ ConfigSource["Extensions"] = "extensions";
26
+ })(ConfigSource || (ConfigSource = {}));
27
+ /**
28
+ * Hook registry that loads and validates hook definitions from multiple sources
29
+ */
30
+ export class HookRegistry {
31
+ config;
32
+ entries = [];
33
+ initialized = false;
34
+ constructor(config) {
35
+ this.config = config;
36
+ }
37
+ /**
38
+ * Initialize the registry by processing hooks from config
39
+ */
40
+ async initialize() {
41
+ if (this.initialized) {
42
+ return;
43
+ }
44
+ this.entries = [];
45
+ this.processHooksFromConfig();
46
+ this.initialized = true;
47
+ debugLogger.log(`Hook registry initialized with ${this.entries.length} hook entries`);
48
+ }
49
+ /**
50
+ * Get all hook entries for a specific event
51
+ */
52
+ getHooksForEvent(eventName) {
53
+ if (!this.initialized) {
54
+ throw new HookRegistryNotInitializedError();
55
+ }
56
+ return this.entries
57
+ .filter((entry) => entry.eventName === eventName && entry.enabled)
58
+ .sort((a, b) => this.getSourcePriority(a.source) - this.getSourcePriority(b.source));
59
+ }
60
+ /**
61
+ * Get all registered hooks
62
+ */
63
+ getAllHooks() {
64
+ if (!this.initialized) {
65
+ throw new HookRegistryNotInitializedError();
66
+ }
67
+ return [...this.entries];
68
+ }
69
+ /**
70
+ * Enable or disable a specific hook
71
+ */
72
+ setHookEnabled(hookName, enabled) {
73
+ const updated = this.entries.filter((entry) => {
74
+ const name = this.getHookName(entry);
75
+ if (name === hookName) {
76
+ entry.enabled = enabled;
77
+ return true;
78
+ }
79
+ return false;
80
+ });
81
+ if (updated.length > 0) {
82
+ debugLogger.log(`${enabled ? 'Enabled' : 'Disabled'} ${updated.length} hook(s) matching "${hookName}"`);
83
+ }
84
+ else {
85
+ debugLogger.warn(`No hooks found matching "${hookName}"`);
86
+ }
87
+ }
88
+ /**
89
+ * Get hook name for display purposes
90
+ */
91
+ getHookName(entry) {
92
+ return entry.config.command || 'unknown-command';
93
+ }
94
+ /**
95
+ * Process hooks from the config that was already loaded by the CLI
96
+ */
97
+ processHooksFromConfig() {
98
+ // Get hooks from the main config (this comes from the merged settings)
99
+ const configHooks = this.config.getHooks();
100
+ if (configHooks) {
101
+ this.processHooksConfiguration(configHooks, ConfigSource.Project);
102
+ }
103
+ // Get hooks from extensions
104
+ const extensions = this.config.getExtensions() || [];
105
+ for (const extension of extensions) {
106
+ if (extension.isActive && extension.hooks) {
107
+ this.processHooksConfiguration(extension.hooks, ConfigSource.Extensions);
108
+ }
109
+ }
110
+ }
111
+ /**
112
+ * Process hooks configuration and add entries
113
+ */
114
+ processHooksConfiguration(hooksConfig, source) {
115
+ for (const [eventName, definitions] of Object.entries(hooksConfig)) {
116
+ if (!this.isValidEventName(eventName)) {
117
+ debugLogger.warn(`Invalid hook event name: ${eventName}`);
118
+ continue;
119
+ }
120
+ const typedEventName = eventName;
121
+ if (!Array.isArray(definitions)) {
122
+ debugLogger.warn(`Hook definitions for event "${eventName}" from source "${source}" is not an array. Skipping.`);
123
+ continue;
124
+ }
125
+ for (const definition of definitions) {
126
+ this.processHookDefinition(definition, typedEventName, source);
127
+ }
128
+ }
129
+ }
130
+ /**
131
+ * Process a single hook definition
132
+ */
133
+ processHookDefinition(definition, eventName, source) {
134
+ if (!definition ||
135
+ typeof definition !== 'object' ||
136
+ !Array.isArray(definition.hooks)) {
137
+ debugLogger.warn(`Discarding invalid hook definition for ${eventName} from ${source}:`, definition);
138
+ return;
139
+ }
140
+ for (const hookConfig of definition.hooks) {
141
+ if (hookConfig &&
142
+ typeof hookConfig === 'object' &&
143
+ this.validateHookConfig(hookConfig, eventName, source)) {
144
+ this.entries.push({
145
+ config: hookConfig,
146
+ source,
147
+ eventName,
148
+ matcher: definition.matcher,
149
+ sequential: definition.sequential,
150
+ enabled: true,
151
+ });
152
+ }
153
+ else {
154
+ // Invalid hooks are logged and discarded here, they won't reach HookRunner
155
+ debugLogger.warn(`Discarding invalid hook configuration for ${eventName} from ${source}:`, hookConfig);
156
+ }
157
+ }
158
+ }
159
+ /**
160
+ * Validate a hook configuration
161
+ */
162
+ validateHookConfig(config, eventName, source) {
163
+ if (!config.type || !['command', 'plugin'].includes(config.type)) {
164
+ debugLogger.warn(`Invalid hook ${eventName} from ${source} type: ${config.type}`);
165
+ return false;
166
+ }
167
+ if (config.type === 'command' && !config.command) {
168
+ debugLogger.warn(`Command hook ${eventName} from ${source} missing command field`);
169
+ return false;
170
+ }
171
+ return true;
172
+ }
173
+ /**
174
+ * Check if an event name is valid
175
+ */
176
+ isValidEventName(eventName) {
177
+ const validEventNames = Object.values(HookEventName);
178
+ return validEventNames.includes(eventName);
179
+ }
180
+ /**
181
+ * Get source priority (lower number = higher priority)
182
+ */
183
+ getSourcePriority(source) {
184
+ switch (source) {
185
+ case ConfigSource.Project:
186
+ return 1;
187
+ case ConfigSource.User:
188
+ return 2;
189
+ case ConfigSource.System:
190
+ return 3;
191
+ case ConfigSource.Extensions:
192
+ return 4;
193
+ default:
194
+ return 999;
195
+ }
196
+ }
197
+ }
198
+ //# sourceMappingURL=hookRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hookRegistry.js","sourceRoot":"","sources":["../../../src/hooks/hookRegistry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};