@google/gemini-cli-core 0.15.0-nightly.20251107.cd27cae8 → 0.15.0-nightly.20251111.51f952e7

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 (110) hide show
  1. package/dist/google-gemini-cli-core-0.15.0-nightly.20251107.b8eeb553.tgz +0 -0
  2. package/dist/src/config/config.d.ts +7 -1
  3. package/dist/src/config/config.js +12 -9
  4. package/dist/src/config/config.js.map +1 -1
  5. package/dist/src/config/config.test.js +0 -12
  6. package/dist/src/config/config.test.js.map +1 -1
  7. package/dist/src/config/defaultModelConfigs.js +21 -4
  8. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  9. package/dist/src/core/baseLlmClient.d.ts +4 -8
  10. package/dist/src/core/baseLlmClient.js +3 -8
  11. package/dist/src/core/baseLlmClient.js.map +1 -1
  12. package/dist/src/core/baseLlmClient.test.js +13 -20
  13. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  14. package/dist/src/core/coreToolScheduler.js +7 -1
  15. package/dist/src/core/coreToolScheduler.js.map +1 -1
  16. package/dist/src/core/coreToolScheduler.test.js +136 -357
  17. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  18. package/dist/src/generated/git-commit.d.ts +2 -2
  19. package/dist/src/generated/git-commit.js +2 -2
  20. package/dist/src/hooks/hookRunner.d.ts +42 -0
  21. package/dist/src/hooks/hookRunner.js +272 -0
  22. package/dist/src/hooks/hookRunner.js.map +1 -0
  23. package/dist/src/hooks/hookRunner.test.d.ts +6 -0
  24. package/dist/src/hooks/hookRunner.test.js +468 -0
  25. package/dist/src/hooks/hookRunner.test.js.map +1 -0
  26. package/dist/src/ide/ide-client.js +3 -3
  27. package/dist/src/ide/types.d.ts +1 -1
  28. package/dist/src/ide/types.js +1 -1
  29. package/dist/src/policy/toml-loader.test.js +26 -0
  30. package/dist/src/policy/toml-loader.test.js.map +1 -1
  31. package/dist/src/routing/strategies/classifierStrategy.js +3 -11
  32. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
  33. package/dist/src/routing/strategies/classifierStrategy.test.js +12 -10
  34. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
  35. package/dist/src/services/loopDetectionService.js +1 -2
  36. package/dist/src/services/loopDetectionService.js.map +1 -1
  37. package/dist/src/services/loopDetectionService.test.js +7 -1
  38. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  39. package/dist/src/services/test-data/resolved-aliases.golden.json +28 -0
  40. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +7 -7
  41. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +11 -20
  42. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  43. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +1 -0
  44. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +28 -1
  45. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  46. package/dist/src/telemetry/index.d.ts +2 -2
  47. package/dist/src/telemetry/index.js +2 -2
  48. package/dist/src/telemetry/index.js.map +1 -1
  49. package/dist/src/telemetry/loggers.d.ts +6 -7
  50. package/dist/src/telemetry/loggers.js +10 -21
  51. package/dist/src/telemetry/loggers.js.map +1 -1
  52. package/dist/src/telemetry/loggers.test.js +18 -18
  53. package/dist/src/telemetry/loggers.test.js.map +1 -1
  54. package/dist/src/telemetry/types.d.ts +1 -10
  55. package/dist/src/telemetry/types.js +0 -25
  56. package/dist/src/telemetry/types.js.map +1 -1
  57. package/dist/src/tools/mcp-client.js +22 -12
  58. package/dist/src/tools/mcp-client.js.map +1 -1
  59. package/dist/src/tools/mcp-client.test.js +6 -0
  60. package/dist/src/tools/mcp-client.test.js.map +1 -1
  61. package/dist/src/tools/mcp-tool.d.ts +1 -0
  62. package/dist/src/tools/mcp-tool.js +4 -1
  63. package/dist/src/tools/mcp-tool.js.map +1 -1
  64. package/dist/src/tools/modifiable-tool.d.ts +5 -1
  65. package/dist/src/tools/modifiable-tool.js +34 -13
  66. package/dist/src/tools/modifiable-tool.js.map +1 -1
  67. package/dist/src/tools/modifiable-tool.test.js +56 -22
  68. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  69. package/dist/src/tools/ripGrep.js +22 -30
  70. package/dist/src/tools/ripGrep.js.map +1 -1
  71. package/dist/src/tools/ripGrep.test.js +216 -24
  72. package/dist/src/tools/ripGrep.test.js.map +1 -1
  73. package/dist/src/tools/shell.test.js +1 -1
  74. package/dist/src/tools/shell.test.js.map +1 -1
  75. package/dist/src/tools/tool-registry.d.ts +18 -3
  76. package/dist/src/tools/tool-registry.js +61 -17
  77. package/dist/src/tools/tool-registry.js.map +1 -1
  78. package/dist/src/tools/tool-registry.test.js +64 -0
  79. package/dist/src/tools/tool-registry.test.js.map +1 -1
  80. package/dist/src/utils/editCorrector.js +4 -15
  81. package/dist/src/utils/editCorrector.js.map +1 -1
  82. package/dist/src/utils/editCorrector.test.js +16 -0
  83. package/dist/src/utils/editCorrector.test.js.map +1 -1
  84. package/dist/src/utils/events.d.ts +14 -11
  85. package/dist/src/utils/events.js +1 -14
  86. package/dist/src/utils/events.js.map +1 -1
  87. package/dist/src/utils/extensionLoader.d.ts +8 -0
  88. package/dist/src/utils/extensionLoader.js +55 -13
  89. package/dist/src/utils/extensionLoader.js.map +1 -1
  90. package/dist/src/utils/extensionLoader.test.js +83 -19
  91. package/dist/src/utils/extensionLoader.test.js.map +1 -1
  92. package/dist/src/utils/llm-edit-fixer.js +1 -2
  93. package/dist/src/utils/llm-edit-fixer.js.map +1 -1
  94. package/dist/src/utils/llm-edit-fixer.test.js +8 -0
  95. package/dist/src/utils/llm-edit-fixer.test.js.map +1 -1
  96. package/dist/src/utils/memoryDiscovery.d.ts +8 -0
  97. package/dist/src/utils/memoryDiscovery.js +24 -0
  98. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  99. package/dist/src/utils/memoryDiscovery.test.js +43 -1
  100. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  101. package/dist/src/utils/nextSpeakerChecker.js +1 -2
  102. package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
  103. package/dist/src/utils/nextSpeakerChecker.test.js +10 -4
  104. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  105. package/dist/src/utils/shell-utils.js +5 -3
  106. package/dist/src/utils/shell-utils.js.map +1 -1
  107. package/dist/src/utils/shell-utils.test.js +9 -9
  108. package/dist/src/utils/shell-utils.test.js.map +1 -1
  109. package/dist/tsconfig.tsbuildinfo +1 -1
  110. package/package.json +1 -1
@@ -0,0 +1,468 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import { spawn } from 'node:child_process';
8
+ import { HookRunner } from './hookRunner.js';
9
+ import { HookEventName, HookType } from './types.js';
10
+ // Mock child_process with importOriginal for partial mocking
11
+ vi.mock('node:child_process', async (importOriginal) => {
12
+ const actual = (await importOriginal());
13
+ return {
14
+ ...actual,
15
+ spawn: vi.fn(),
16
+ };
17
+ });
18
+ // Mock console methods
19
+ const mockConsole = {
20
+ log: vi.fn(),
21
+ warn: vi.fn(),
22
+ error: vi.fn(),
23
+ debug: vi.fn(),
24
+ };
25
+ vi.stubGlobal('console', mockConsole);
26
+ describe('HookRunner', () => {
27
+ let hookRunner;
28
+ let mockSpawn;
29
+ const mockInput = {
30
+ session_id: 'test-session',
31
+ transcript_path: '/path/to/transcript',
32
+ cwd: '/test/project',
33
+ hook_event_name: 'BeforeTool',
34
+ timestamp: '2025-01-01T00:00:00.000Z',
35
+ };
36
+ beforeEach(() => {
37
+ vi.resetAllMocks();
38
+ hookRunner = new HookRunner();
39
+ // Mock spawn with accessible mock functions
40
+ const mockStdoutOn = vi.fn();
41
+ const mockStderrOn = vi.fn();
42
+ const mockProcessOn = vi.fn();
43
+ mockSpawn = {
44
+ stdin: {
45
+ write: vi.fn(),
46
+ end: vi.fn(),
47
+ },
48
+ stdout: {
49
+ on: mockStdoutOn,
50
+ },
51
+ stderr: {
52
+ on: mockStderrOn,
53
+ },
54
+ on: mockProcessOn,
55
+ kill: vi.fn(),
56
+ killed: false,
57
+ mockStdoutOn,
58
+ mockStderrOn,
59
+ mockProcessOn,
60
+ };
61
+ vi.mocked(spawn).mockReturnValue(mockSpawn);
62
+ });
63
+ afterEach(() => {
64
+ vi.restoreAllMocks();
65
+ });
66
+ describe('executeHook', () => {
67
+ describe('command hooks', () => {
68
+ const commandConfig = {
69
+ type: HookType.Command,
70
+ command: './hooks/test.sh',
71
+ timeout: 5000,
72
+ };
73
+ it('should execute command hook successfully', async () => {
74
+ const mockOutput = { decision: 'allow', reason: 'All good' };
75
+ // Mock successful execution
76
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
77
+ if (event === 'data') {
78
+ setTimeout(() => callback(Buffer.from(JSON.stringify(mockOutput))), 10);
79
+ }
80
+ });
81
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
82
+ if (event === 'close') {
83
+ setTimeout(() => callback(0), 20);
84
+ }
85
+ });
86
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
87
+ expect(result.success).toBe(true);
88
+ expect(result.output).toEqual(mockOutput);
89
+ expect(result.exitCode).toBe(0);
90
+ expect(mockSpawn.stdin.write).toHaveBeenCalledWith(JSON.stringify(mockInput));
91
+ });
92
+ it('should handle command hook failure', async () => {
93
+ const errorMessage = 'Command failed';
94
+ mockSpawn.mockStderrOn.mockImplementation((event, callback) => {
95
+ if (event === 'data') {
96
+ setTimeout(() => callback(Buffer.from(errorMessage)), 10);
97
+ }
98
+ });
99
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
100
+ if (event === 'close') {
101
+ setTimeout(() => callback(1), 20);
102
+ }
103
+ });
104
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
105
+ expect(result.success).toBe(false);
106
+ expect(result.exitCode).toBe(1);
107
+ expect(result.stderr).toBe(errorMessage);
108
+ });
109
+ it('should handle command hook timeout', async () => {
110
+ const shortTimeoutConfig = {
111
+ type: HookType.Command,
112
+ command: './hooks/slow.sh',
113
+ timeout: 50, // Very short timeout for testing
114
+ };
115
+ let closeCallback;
116
+ let killWasCalled = false;
117
+ // Mock a hanging process that registers the close handler but doesn't call it initially
118
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
119
+ if (event === 'close') {
120
+ closeCallback = callback; // Store the callback but don't call it yet
121
+ }
122
+ });
123
+ // Mock the kill method to simulate the process being killed
124
+ mockSpawn.kill = vi.fn().mockImplementation((_signal) => {
125
+ killWasCalled = true;
126
+ // Simulate that killing the process triggers the close event
127
+ if (closeCallback) {
128
+ setTimeout(() => {
129
+ closeCallback(128); // Exit code 128 indicates process was killed by signal
130
+ }, 5);
131
+ }
132
+ return true;
133
+ });
134
+ const result = await hookRunner.executeHook(shortTimeoutConfig, HookEventName.BeforeTool, mockInput);
135
+ expect(result.success).toBe(false);
136
+ expect(killWasCalled).toBe(true);
137
+ expect(result.error?.message).toContain('timed out');
138
+ expect(mockSpawn.kill).toHaveBeenCalledWith('SIGTERM');
139
+ });
140
+ it('should expand environment variables in commands', async () => {
141
+ const configWithEnvVar = {
142
+ type: HookType.Command,
143
+ command: '$GEMINI_PROJECT_DIR/hooks/test.sh',
144
+ };
145
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
146
+ if (event === 'close') {
147
+ setTimeout(() => callback(0), 10);
148
+ }
149
+ });
150
+ await hookRunner.executeHook(configWithEnvVar, HookEventName.BeforeTool, mockInput);
151
+ expect(spawn).toHaveBeenCalledWith('/test/project/hooks/test.sh', expect.objectContaining({
152
+ shell: true,
153
+ env: expect.objectContaining({
154
+ GEMINI_PROJECT_DIR: '/test/project',
155
+ CLAUDE_PROJECT_DIR: '/test/project',
156
+ }),
157
+ }));
158
+ });
159
+ });
160
+ });
161
+ describe('executeHooksParallel', () => {
162
+ it('should execute multiple hooks in parallel', async () => {
163
+ const configs = [
164
+ { type: HookType.Command, command: './hook1.sh' },
165
+ { type: HookType.Command, command: './hook2.sh' },
166
+ ];
167
+ // Mock both commands to succeed
168
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
169
+ if (event === 'close') {
170
+ setTimeout(() => callback(0), 10);
171
+ }
172
+ });
173
+ const results = await hookRunner.executeHooksParallel(configs, HookEventName.BeforeTool, mockInput);
174
+ expect(results).toHaveLength(2);
175
+ expect(results.every((r) => r.success)).toBe(true);
176
+ expect(spawn).toHaveBeenCalledTimes(2);
177
+ });
178
+ it('should handle mixed success and failure', async () => {
179
+ const configs = [
180
+ { type: HookType.Command, command: './hook1.sh' },
181
+ { type: HookType.Command, command: './hook2.sh' },
182
+ ];
183
+ let callCount = 0;
184
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
185
+ if (event === 'close') {
186
+ const exitCode = callCount++ === 0 ? 0 : 1; // First succeeds, second fails
187
+ setTimeout(() => callback(exitCode), 10);
188
+ }
189
+ });
190
+ const results = await hookRunner.executeHooksParallel(configs, HookEventName.BeforeTool, mockInput);
191
+ expect(results).toHaveLength(2);
192
+ expect(results[0].success).toBe(true);
193
+ expect(results[1].success).toBe(false);
194
+ });
195
+ });
196
+ describe('executeHooksSequential', () => {
197
+ it('should execute multiple hooks in sequence', async () => {
198
+ const configs = [
199
+ { type: HookType.Command, command: './hook1.sh' },
200
+ { type: HookType.Command, command: './hook2.sh' },
201
+ ];
202
+ const executionOrder = [];
203
+ // Mock both commands to succeed
204
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
205
+ if (event === 'close') {
206
+ const command = vi.mocked(spawn).mock.calls[executionOrder.length][0];
207
+ executionOrder.push(command);
208
+ setTimeout(() => callback(0), 10);
209
+ }
210
+ });
211
+ const results = await hookRunner.executeHooksSequential(configs, HookEventName.BeforeTool, mockInput);
212
+ expect(results).toHaveLength(2);
213
+ expect(results.every((r) => r.success)).toBe(true);
214
+ expect(spawn).toHaveBeenCalledTimes(2);
215
+ // Verify they were called sequentially
216
+ expect(executionOrder).toEqual(['./hook1.sh', './hook2.sh']);
217
+ });
218
+ it('should continue execution even if a hook fails', async () => {
219
+ const configs = [
220
+ { type: HookType.Command, command: './hook1.sh' },
221
+ { type: HookType.Command, command: './hook2.sh' },
222
+ { type: HookType.Command, command: './hook3.sh' },
223
+ ];
224
+ let callCount = 0;
225
+ mockSpawn.mockStderrOn.mockImplementation((event, callback) => {
226
+ if (event === 'data' && callCount === 1) {
227
+ // Second hook fails
228
+ setTimeout(() => callback(Buffer.from('Hook 2 failed')), 10);
229
+ }
230
+ });
231
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
232
+ if (event === 'close') {
233
+ const exitCode = callCount++ === 1 ? 1 : 0; // Second fails, others succeed
234
+ setTimeout(() => callback(exitCode), 20);
235
+ }
236
+ });
237
+ const results = await hookRunner.executeHooksSequential(configs, HookEventName.BeforeTool, mockInput);
238
+ expect(results).toHaveLength(3);
239
+ expect(results[0].success).toBe(true);
240
+ expect(results[1].success).toBe(false);
241
+ expect(results[2].success).toBe(true);
242
+ expect(spawn).toHaveBeenCalledTimes(3);
243
+ });
244
+ it('should pass modified input from one hook to the next for BeforeAgent', async () => {
245
+ const configs = [
246
+ { type: HookType.Command, command: './hook1.sh' },
247
+ { type: HookType.Command, command: './hook2.sh' },
248
+ ];
249
+ const mockBeforeAgentInput = {
250
+ ...mockInput,
251
+ prompt: 'Original prompt',
252
+ };
253
+ const mockOutput1 = {
254
+ decision: 'allow',
255
+ hookSpecificOutput: {
256
+ additionalContext: 'Context from hook 1',
257
+ },
258
+ };
259
+ let hookCallCount = 0;
260
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
261
+ if (event === 'data') {
262
+ if (hookCallCount === 0) {
263
+ setTimeout(() => callback(Buffer.from(JSON.stringify(mockOutput1))), 10);
264
+ }
265
+ }
266
+ });
267
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
268
+ if (event === 'close') {
269
+ hookCallCount++;
270
+ setTimeout(() => callback(0), 20);
271
+ }
272
+ });
273
+ const results = await hookRunner.executeHooksSequential(configs, HookEventName.BeforeAgent, mockBeforeAgentInput);
274
+ expect(results).toHaveLength(2);
275
+ expect(results[0].success).toBe(true);
276
+ expect(results[0].output).toEqual(mockOutput1);
277
+ // Verify that the second hook received modified input
278
+ const secondHookInput = JSON.parse(vi.mocked(mockSpawn.stdin.write).mock.calls[1][0]);
279
+ expect(secondHookInput.prompt).toContain('Original prompt');
280
+ expect(secondHookInput.prompt).toContain('Context from hook 1');
281
+ });
282
+ it('should pass modified LLM request from one hook to the next for BeforeModel', async () => {
283
+ const configs = [
284
+ { type: HookType.Command, command: './hook1.sh' },
285
+ { type: HookType.Command, command: './hook2.sh' },
286
+ ];
287
+ const mockBeforeModelInput = {
288
+ ...mockInput,
289
+ llm_request: {
290
+ model: 'gemini-1.5-pro',
291
+ messages: [{ role: 'user', content: 'Hello' }],
292
+ },
293
+ };
294
+ const mockOutput1 = {
295
+ decision: 'allow',
296
+ hookSpecificOutput: {
297
+ llm_request: {
298
+ temperature: 0.7,
299
+ },
300
+ },
301
+ };
302
+ let hookCallCount = 0;
303
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
304
+ if (event === 'data') {
305
+ if (hookCallCount === 0) {
306
+ setTimeout(() => callback(Buffer.from(JSON.stringify(mockOutput1))), 10);
307
+ }
308
+ }
309
+ });
310
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
311
+ if (event === 'close') {
312
+ hookCallCount++;
313
+ setTimeout(() => callback(0), 20);
314
+ }
315
+ });
316
+ const results = await hookRunner.executeHooksSequential(configs, HookEventName.BeforeModel, mockBeforeModelInput);
317
+ expect(results).toHaveLength(2);
318
+ expect(results[0].success).toBe(true);
319
+ // Verify that the second hook received modified input
320
+ const secondHookInput = JSON.parse(vi.mocked(mockSpawn.stdin.write).mock.calls[1][0]);
321
+ expect(secondHookInput.llm_request.model).toBe('gemini-1.5-pro');
322
+ expect(secondHookInput.llm_request.temperature).toBe(0.7);
323
+ });
324
+ it('should not modify input if hook fails', async () => {
325
+ const configs = [
326
+ { type: HookType.Command, command: './hook1.sh' },
327
+ { type: HookType.Command, command: './hook2.sh' },
328
+ ];
329
+ mockSpawn.mockStderrOn.mockImplementation((event, callback) => {
330
+ if (event === 'data') {
331
+ setTimeout(() => callback(Buffer.from('Hook failed')), 10);
332
+ }
333
+ });
334
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
335
+ if (event === 'close') {
336
+ setTimeout(() => callback(1), 20); // All hooks fail
337
+ }
338
+ });
339
+ const results = await hookRunner.executeHooksSequential(configs, HookEventName.BeforeTool, mockInput);
340
+ expect(results).toHaveLength(2);
341
+ expect(results.every((r) => !r.success)).toBe(true);
342
+ // Verify that both hooks received the same original input
343
+ const firstHookInput = JSON.parse(vi.mocked(mockSpawn.stdin.write).mock.calls[0][0]);
344
+ const secondHookInput = JSON.parse(vi.mocked(mockSpawn.stdin.write).mock.calls[1][0]);
345
+ expect(firstHookInput).toEqual(secondHookInput);
346
+ });
347
+ });
348
+ describe('invalid JSON handling', () => {
349
+ const commandConfig = {
350
+ type: HookType.Command,
351
+ command: './hooks/test.sh',
352
+ };
353
+ it('should handle invalid JSON output gracefully', async () => {
354
+ const invalidJson = '{ "decision": "allow", incomplete';
355
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
356
+ if (event === 'data') {
357
+ setTimeout(() => callback(Buffer.from(invalidJson)), 10);
358
+ }
359
+ });
360
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
361
+ if (event === 'close') {
362
+ setTimeout(() => callback(0), 20);
363
+ }
364
+ });
365
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
366
+ expect(result.success).toBe(true);
367
+ expect(result.exitCode).toBe(0);
368
+ // Should convert plain text to structured output
369
+ expect(result.output).toEqual({
370
+ decision: 'allow',
371
+ systemMessage: invalidJson,
372
+ });
373
+ });
374
+ it('should handle malformed JSON with exit code 0', async () => {
375
+ const malformedJson = 'not json at all';
376
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
377
+ if (event === 'data') {
378
+ setTimeout(() => callback(Buffer.from(malformedJson)), 10);
379
+ }
380
+ });
381
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
382
+ if (event === 'close') {
383
+ setTimeout(() => callback(0), 20);
384
+ }
385
+ });
386
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
387
+ expect(result.success).toBe(true);
388
+ expect(result.output).toEqual({
389
+ decision: 'allow',
390
+ systemMessage: malformedJson,
391
+ });
392
+ });
393
+ it('should handle invalid JSON with exit code 1 (non-blocking error)', async () => {
394
+ const invalidJson = '{ broken json';
395
+ mockSpawn.mockStderrOn.mockImplementation((event, callback) => {
396
+ if (event === 'data') {
397
+ setTimeout(() => callback(Buffer.from(invalidJson)), 10);
398
+ }
399
+ });
400
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
401
+ if (event === 'close') {
402
+ setTimeout(() => callback(1), 20);
403
+ }
404
+ });
405
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
406
+ expect(result.success).toBe(false);
407
+ expect(result.exitCode).toBe(1);
408
+ expect(result.output).toEqual({
409
+ decision: 'allow',
410
+ systemMessage: `Warning: ${invalidJson}`,
411
+ });
412
+ });
413
+ it('should handle invalid JSON with exit code 2 (blocking error)', async () => {
414
+ const invalidJson = '{ "error": incomplete';
415
+ mockSpawn.mockStderrOn.mockImplementation((event, callback) => {
416
+ if (event === 'data') {
417
+ setTimeout(() => callback(Buffer.from(invalidJson)), 10);
418
+ }
419
+ });
420
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
421
+ if (event === 'close') {
422
+ setTimeout(() => callback(2), 20);
423
+ }
424
+ });
425
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
426
+ expect(result.success).toBe(false);
427
+ expect(result.exitCode).toBe(2);
428
+ expect(result.output).toEqual({
429
+ decision: 'deny',
430
+ reason: invalidJson,
431
+ });
432
+ });
433
+ it('should handle empty JSON output', async () => {
434
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
435
+ if (event === 'data') {
436
+ setTimeout(() => callback(Buffer.from('')), 10);
437
+ }
438
+ });
439
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
440
+ if (event === 'close') {
441
+ setTimeout(() => callback(0), 20);
442
+ }
443
+ });
444
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
445
+ expect(result.success).toBe(true);
446
+ expect(result.exitCode).toBe(0);
447
+ expect(result.output).toBeUndefined();
448
+ });
449
+ it('should handle double-encoded JSON string', async () => {
450
+ const mockOutput = { decision: 'allow', reason: 'All good' };
451
+ const doubleEncodedJson = JSON.stringify(JSON.stringify(mockOutput));
452
+ mockSpawn.mockStdoutOn.mockImplementation((event, callback) => {
453
+ if (event === 'data') {
454
+ setTimeout(() => callback(Buffer.from(doubleEncodedJson)), 10);
455
+ }
456
+ });
457
+ mockSpawn.mockProcessOn.mockImplementation((event, callback) => {
458
+ if (event === 'close') {
459
+ setTimeout(() => callback(0), 20);
460
+ }
461
+ });
462
+ const result = await hookRunner.executeHook(commandConfig, HookEventName.BeforeTool, mockInput);
463
+ expect(result.success).toBe(true);
464
+ expect(result.output).toEqual(mockOutput);
465
+ });
466
+ });
467
+ });
468
+ //# sourceMappingURL=hookRunner.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hookRunner.test.js","sourceRoot":"","sources":["../../../src/hooks/hookRunner.test.ts"],"names":[],"mappings":"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"}
@@ -424,7 +424,7 @@ export class IdeClient {
424
424
  if (!this.ideProcessInfo) {
425
425
  return undefined;
426
426
  }
427
- // For backwards compatability
427
+ // For backwards compatibility
428
428
  try {
429
429
  const portFile = path.join(os.tmpdir(), `gemini-ide-server-${this.ideProcessInfo.pid}.json`);
430
430
  const portFileContents = await fs.promises.readFile(portFile, 'utf8');
@@ -495,7 +495,7 @@ export class IdeClient {
495
495
  return validWorkspaces[0];
496
496
  }
497
497
  createProxyAwareFetch() {
498
- // ignore proxy for '127.0.0.1' by deafult to allow connecting to the ide mcp server
498
+ // ignore proxy for '127.0.0.1' by default to allow connecting to the ide mcp server
499
499
  const existingNoProxy = process.env['NO_PROXY'] || '';
500
500
  const agent = new EnvHttpProxyAgent({
501
501
  noProxy: [existingNoProxy, '127.0.0.1'].filter(Boolean).join(','),
@@ -558,7 +558,7 @@ export class IdeClient {
558
558
  logger.debug(`No resolver found for ${filePath}`);
559
559
  }
560
560
  });
561
- // For backwards compatability. Newer extension versions will only send
561
+ // For backwards compatibility. Newer extension versions will only send
562
562
  // IdeDiffRejectedNotificationSchema.
563
563
  this.client.setNotificationHandler(IdeDiffClosedNotificationSchema, (notification) => {
564
564
  const { filePath } = notification.params;
@@ -413,7 +413,7 @@ export declare const IdeDiffRejectedNotificationSchema: z.ZodObject<{
413
413
  method: "ide/diffRejected";
414
414
  }>;
415
415
  /**
416
- * This is defineded for backwards compatability only. Newer extension versions
416
+ * This is defined for backwards compatibility only. Newer extension versions
417
417
  * will only send IdeDiffRejectedNotificationSchema.
418
418
  *
419
419
  * A notification that a diff has been closed in the IDE.
@@ -96,7 +96,7 @@ export const IdeDiffRejectedNotificationSchema = z.object({
96
96
  }),
97
97
  });
98
98
  /**
99
- * This is defineded for backwards compatability only. Newer extension versions
99
+ * This is defined for backwards compatibility only. Newer extension versions
100
100
  * will only send IdeDiffRejectedNotificationSchema.
101
101
  *
102
102
  * A notification that a diff has been closed in the IDE.
@@ -299,6 +299,19 @@ priority = 1.5
299
299
  toolName = "test"
300
300
  decision = "allow"
301
301
  priority = -1
302
+ `);
303
+ expect(result.errors).toHaveLength(1);
304
+ const error = result.errors[0];
305
+ expect(error.errorType).toBe('schema_validation');
306
+ expect(error.details).toContain('priority');
307
+ expect(error.details).toContain('>= 0');
308
+ });
309
+ it('should return a schema_validation error if priority is much lower than 0', async () => {
310
+ const result = await runLoadPoliciesFromToml(`
311
+ [[rule]]
312
+ toolName = "test"
313
+ decision = "allow"
314
+ priority = -9999
302
315
  `);
303
316
  expect(result.errors).toHaveLength(1);
304
317
  const error = result.errors[0];
@@ -312,6 +325,19 @@ priority = -1
312
325
  toolName = "test"
313
326
  decision = "allow"
314
327
  priority = 1000
328
+ `);
329
+ expect(result.errors).toHaveLength(1);
330
+ const error = result.errors[0];
331
+ expect(error.errorType).toBe('schema_validation');
332
+ expect(error.details).toContain('priority');
333
+ expect(error.details).toContain('<= 999');
334
+ });
335
+ it('should return a schema_validation error if priority is much higher than 1000', async () => {
336
+ const result = await runLoadPoliciesFromToml(`
337
+ [[rule]]
338
+ toolName = "test"
339
+ decision = "allow"
340
+ priority = 9999
315
341
  `);
316
342
  expect(result.errors).toHaveLength(1);
317
343
  const error = result.errors[0];