@google/gemini-cli 0.12.0-nightly.20251023.c4c0c0d1 → 0.12.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 (248) hide show
  1. package/README.md +7 -5
  2. package/dist/package.json +3 -3
  3. package/dist/src/commands/extensions/disable.d.ts +1 -1
  4. package/dist/src/commands/extensions/disable.js +5 -4
  5. package/dist/src/commands/extensions/disable.js.map +1 -1
  6. package/dist/src/commands/extensions/enable.d.ts +1 -1
  7. package/dist/src/commands/extensions/enable.js +3 -2
  8. package/dist/src/commands/extensions/enable.js.map +1 -1
  9. package/dist/src/commands/extensions/install.js +2 -1
  10. package/dist/src/commands/extensions/install.js.map +1 -1
  11. package/dist/src/commands/extensions/install.test.js +1 -0
  12. package/dist/src/commands/extensions/install.test.js.map +1 -1
  13. package/dist/src/commands/extensions/link.js +2 -1
  14. package/dist/src/commands/extensions/link.js.map +1 -1
  15. package/dist/src/commands/extensions/list.js +2 -2
  16. package/dist/src/commands/extensions/list.js.map +1 -1
  17. package/dist/src/commands/extensions/uninstall.js +2 -1
  18. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  19. package/dist/src/commands/extensions/update.js +2 -2
  20. package/dist/src/commands/extensions/update.js.map +1 -1
  21. package/dist/src/commands/mcp/list.js +2 -2
  22. package/dist/src/commands/mcp/list.js.map +1 -1
  23. package/dist/src/config/config.d.ts +6 -3
  24. package/dist/src/config/config.js +56 -11
  25. package/dist/src/config/config.js.map +1 -1
  26. package/dist/src/config/config.test.js +208 -175
  27. package/dist/src/config/config.test.js.map +1 -1
  28. package/dist/src/config/extension-manager.d.ts +23 -10
  29. package/dist/src/config/extension-manager.js +90 -64
  30. package/dist/src/config/extension-manager.js.map +1 -1
  31. package/dist/src/config/extension.test.js +183 -76
  32. package/dist/src/config/extension.test.js.map +1 -1
  33. package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
  34. package/dist/src/config/extensions/extensionEnablement.js +3 -2
  35. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  36. package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
  37. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  38. package/dist/src/config/extensions/extensionSettings.d.ts +3 -3
  39. package/dist/src/config/extensions/extensionSettings.js +74 -24
  40. package/dist/src/config/extensions/extensionSettings.js.map +1 -1
  41. package/dist/src/config/extensions/extensionSettings.test.js +145 -24
  42. package/dist/src/config/extensions/extensionSettings.test.js.map +1 -1
  43. package/dist/src/config/extensions/github.js +3 -3
  44. package/dist/src/config/extensions/github.js.map +1 -1
  45. package/dist/src/config/extensions/github.test.js +1 -1
  46. package/dist/src/config/extensions/github.test.js.map +1 -1
  47. package/dist/src/config/extensions/github_fetch.d.ts +1 -1
  48. package/dist/src/config/extensions/github_fetch.js +13 -1
  49. package/dist/src/config/extensions/github_fetch.js.map +1 -1
  50. package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
  51. package/dist/src/config/extensions/github_fetch.test.js +169 -0
  52. package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
  53. package/dist/src/config/extensions/update.js +7 -6
  54. package/dist/src/config/extensions/update.js.map +1 -1
  55. package/dist/src/config/extensions/update.test.js +54 -30
  56. package/dist/src/config/extensions/update.test.js.map +1 -1
  57. package/dist/src/config/keyBindings.js +1 -1
  58. package/dist/src/config/keyBindings.js.map +1 -1
  59. package/dist/src/config/policies/read-only.toml +56 -0
  60. package/dist/src/config/policies/write.toml +63 -0
  61. package/dist/src/config/policies/yolo.toml +31 -0
  62. package/dist/src/config/policy-engine.integration.test.js +41 -38
  63. package/dist/src/config/policy-engine.integration.test.js.map +1 -1
  64. package/dist/src/config/policy-toml-loader.d.ts +46 -0
  65. package/dist/src/config/policy-toml-loader.js +314 -0
  66. package/dist/src/config/policy-toml-loader.js.map +1 -0
  67. package/dist/src/config/policy-toml-loader.test.d.ts +6 -0
  68. package/dist/src/config/policy-toml-loader.test.js +626 -0
  69. package/dist/src/config/policy-toml-loader.test.js.map +1 -0
  70. package/dist/src/config/policy.d.ts +9 -2
  71. package/dist/src/config/policy.js +139 -110
  72. package/dist/src/config/policy.js.map +1 -1
  73. package/dist/src/config/policy.test.js +780 -82
  74. package/dist/src/config/policy.test.js.map +1 -1
  75. package/dist/src/config/settings.test.js +6 -6
  76. package/dist/src/config/settings.test.js.map +1 -1
  77. package/dist/src/core/initializer.js +2 -1
  78. package/dist/src/core/initializer.js.map +1 -1
  79. package/dist/src/gemini.js +6 -17
  80. package/dist/src/gemini.js.map +1 -1
  81. package/dist/src/gemini.test.js +27 -2
  82. package/dist/src/gemini.test.js.map +1 -1
  83. package/dist/src/generated/git-commit.d.ts +2 -2
  84. package/dist/src/generated/git-commit.js +2 -2
  85. package/dist/src/generated/git-commit.js.map +1 -1
  86. package/dist/src/nonInteractiveCli.js +16 -4
  87. package/dist/src/nonInteractiveCli.js.map +1 -1
  88. package/dist/src/nonInteractiveCli.test.js +67 -12
  89. package/dist/src/nonInteractiveCli.test.js.map +1 -1
  90. package/dist/src/test-utils/render.d.ts +12 -0
  91. package/dist/src/test-utils/render.js +28 -1
  92. package/dist/src/test-utils/render.js.map +1 -1
  93. package/dist/src/test-utils/render.test.d.ts +6 -0
  94. package/dist/src/test-utils/render.test.js +54 -0
  95. package/dist/src/test-utils/render.test.js.map +1 -0
  96. package/dist/src/ui/AppContainer.js +29 -23
  97. package/dist/src/ui/AppContainer.js.map +1 -1
  98. package/dist/src/ui/AppContainer.test.js +8 -0
  99. package/dist/src/ui/AppContainer.test.js.map +1 -1
  100. package/dist/src/ui/commands/directoryCommand.js +1 -1
  101. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  102. package/dist/src/ui/commands/extensionsCommand.js +45 -1
  103. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  104. package/dist/src/ui/commands/extensionsCommand.test.js +64 -1
  105. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
  106. package/dist/src/ui/commands/memoryCommand.js +1 -1
  107. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  108. package/dist/src/ui/commands/memoryCommand.test.js +3 -1
  109. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
  110. package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
  111. package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
  112. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  113. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  114. package/dist/src/ui/components/FolderTrustDialog.test.js +4 -4
  115. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  116. package/dist/src/ui/components/Footer.js +1 -1
  117. package/dist/src/ui/components/Footer.js.map +1 -1
  118. package/dist/src/ui/components/Footer.test.js +24 -0
  119. package/dist/src/ui/components/Footer.test.js.map +1 -1
  120. package/dist/src/ui/components/Help.test.js +0 -1
  121. package/dist/src/ui/components/Help.test.js.map +1 -1
  122. package/dist/src/ui/components/InputPrompt.test.js +442 -342
  123. package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
  124. package/dist/src/ui/components/ModelDialog.test.js +5 -5
  125. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  126. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +11 -12
  127. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  128. package/dist/src/ui/components/SettingsDialog.test.js +13 -14
  129. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  130. package/dist/src/ui/components/ThemeDialog.test.js +1 -2
  131. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  132. package/dist/src/ui/components/shared/BaseSelectionList.test.js +11 -12
  133. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  134. package/dist/src/ui/components/shared/text-buffer.test.js +2 -1
  135. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
  136. package/dist/src/ui/components/views/ExtensionsList.d.ts +1 -1
  137. package/dist/src/ui/components/views/ExtensionsList.js +4 -1
  138. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  139. package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
  140. package/dist/src/ui/contexts/KeypressContext.js +114 -64
  141. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  142. package/dist/src/ui/contexts/KeypressContext.test.js +166 -482
  143. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  144. package/dist/src/ui/contexts/SessionContext.test.js +27 -13
  145. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
  146. package/dist/src/ui/hooks/atCommandProcessor.js +2 -2
  147. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  148. package/dist/src/ui/hooks/shellCommandProcessor.test.js +18 -2
  149. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  150. package/dist/src/ui/hooks/slashCommandProcessor.test.js +74 -80
  151. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  152. package/dist/src/ui/hooks/useAtCompletion.test.js +32 -23
  153. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
  154. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +2 -1
  155. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  156. package/dist/src/ui/hooks/useCommandCompletion.test.js +79 -78
  157. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
  158. package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
  159. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
  160. package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
  161. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
  162. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +1 -2
  163. package/dist/src/ui/hooks/useExtensionUpdates.js +4 -2
  164. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  165. package/dist/src/ui/hooks/useExtensionUpdates.test.js +37 -26
  166. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  167. package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
  168. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
  169. package/dist/src/ui/hooks/useFocus.test.js +25 -9
  170. package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
  171. package/dist/src/ui/hooks/useFolderTrust.test.js +45 -22
  172. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  173. package/dist/src/ui/hooks/useGeminiStream.js +56 -19
  174. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  175. package/dist/src/ui/hooks/useGeminiStream.test.js +155 -74
  176. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  177. package/dist/src/ui/hooks/useGitBranchName.test.js +29 -16
  178. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  179. package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
  180. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
  181. package/dist/src/ui/hooks/useIdeTrustListener.test.js +24 -7
  182. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
  183. package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
  184. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
  185. package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
  186. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
  187. package/dist/src/ui/hooks/useKeypress.test.js +94 -113
  188. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
  189. package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
  190. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  191. package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
  192. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
  193. package/dist/src/ui/hooks/useMessageQueue.test.js +61 -45
  194. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  195. package/dist/src/ui/hooks/useModelCommand.test.js +18 -11
  196. package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
  197. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
  198. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  199. package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
  200. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  201. package/dist/src/ui/hooks/usePhraseCycler.test.js +83 -110
  202. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
  203. package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -10
  204. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
  205. package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
  206. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  207. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +33 -40
  208. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
  209. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
  210. package/dist/src/ui/hooks/useReactToolScheduler.js +37 -26
  211. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  212. package/dist/src/ui/hooks/useReactToolScheduler.test.js +1 -1
  213. package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -1
  214. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
  215. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
  216. package/dist/src/ui/hooks/useSelectionList.test.js +193 -132
  217. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  218. package/dist/src/ui/hooks/useShellHistory.test.js +40 -16
  219. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  220. package/dist/src/ui/hooks/useSlashCompletion.test.js +54 -49
  221. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  222. package/dist/src/ui/hooks/useTimer.test.js +43 -14
  223. package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
  224. package/dist/src/ui/hooks/useToolScheduler.test.js +163 -74
  225. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  226. package/dist/src/ui/hooks/vim.test.js +251 -356
  227. package/dist/src/ui/hooks/vim.test.js.map +1 -1
  228. package/dist/src/ui/keyMatchers.test.js +3 -3
  229. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  230. package/dist/src/ui/utils/textOutput.d.ts +25 -0
  231. package/dist/src/ui/utils/textOutput.js +49 -0
  232. package/dist/src/ui/utils/textOutput.js.map +1 -0
  233. package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
  234. package/dist/src/ui/utils/textOutput.test.js +79 -0
  235. package/dist/src/ui/utils/textOutput.test.js.map +1 -0
  236. package/dist/src/ui/utils/updateCheck.d.ts +7 -1
  237. package/dist/src/ui/utils/updateCheck.js +27 -26
  238. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  239. package/dist/src/ui/utils/updateCheck.test.js +19 -49
  240. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  241. package/dist/src/utils/handleAutoUpdate.js +9 -3
  242. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  243. package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
  244. package/dist/src/zed-integration/zedIntegration.js +9 -16
  245. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  246. package/dist/tsconfig.tsbuildinfo +1 -1
  247. package/package.json +4 -4
  248. package/dist/google-gemini-cli-0.12.0-nightly.20251022.0542de95.tgz +0 -0
@@ -1,10 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  /**
2
3
  * @license
3
4
  * Copyright 2025 Google LLC
4
5
  * SPDX-License-Identifier: Apache-2.0
5
6
  */
6
7
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { renderHook, act } from '@testing-library/react';
8
+ import { act } from 'react';
9
+ import { render } from 'ink-testing-library';
8
10
  import { useTimer } from './useTimer.js';
9
11
  describe('useTimer', () => {
10
12
  beforeEach(() => {
@@ -13,19 +15,36 @@ describe('useTimer', () => {
13
15
  afterEach(() => {
14
16
  vi.restoreAllMocks();
15
17
  });
18
+ const renderTimerHook = (initialIsActive, initialResetKey) => {
19
+ let hookResult;
20
+ function TestComponent({ isActive, resetKey, }) {
21
+ hookResult = useTimer(isActive, resetKey);
22
+ return null;
23
+ }
24
+ const { rerender, unmount } = render(_jsx(TestComponent, { isActive: initialIsActive, resetKey: initialResetKey }));
25
+ return {
26
+ result: {
27
+ get current() {
28
+ return hookResult;
29
+ },
30
+ },
31
+ rerender: (newProps) => rerender(_jsx(TestComponent, { ...newProps })),
32
+ unmount,
33
+ };
34
+ };
16
35
  it('should initialize with 0', () => {
17
- const { result } = renderHook(() => useTimer(false, 0));
36
+ const { result } = renderTimerHook(false, 0);
18
37
  expect(result.current).toBe(0);
19
38
  });
20
39
  it('should not increment time if isActive is false', () => {
21
- const { result } = renderHook(() => useTimer(false, 0));
40
+ const { result } = renderTimerHook(false, 0);
22
41
  act(() => {
23
42
  vi.advanceTimersByTime(5000);
24
43
  });
25
44
  expect(result.current).toBe(0);
26
45
  });
27
46
  it('should increment time every second if isActive is true', () => {
28
- const { result } = renderHook(() => useTimer(true, 0));
47
+ const { result } = renderTimerHook(true, 0);
29
48
  act(() => {
30
49
  vi.advanceTimersByTime(1000);
31
50
  });
@@ -36,9 +55,11 @@ describe('useTimer', () => {
36
55
  expect(result.current).toBe(3);
37
56
  });
38
57
  it('should reset to 0 and start incrementing when isActive becomes true from false', () => {
39
- const { result, rerender } = renderHook(({ isActive, resetKey }) => useTimer(isActive, resetKey), { initialProps: { isActive: false, resetKey: 0 } });
58
+ const { result, rerender } = renderTimerHook(false, 0);
40
59
  expect(result.current).toBe(0);
41
- rerender({ isActive: true, resetKey: 0 });
60
+ act(() => {
61
+ rerender({ isActive: true, resetKey: 0 });
62
+ });
42
63
  expect(result.current).toBe(0); // Should reset to 0 upon becoming active
43
64
  act(() => {
44
65
  vi.advanceTimersByTime(1000);
@@ -46,12 +67,14 @@ describe('useTimer', () => {
46
67
  expect(result.current).toBe(1);
47
68
  });
48
69
  it('should reset to 0 when resetKey changes while active', () => {
49
- const { result, rerender } = renderHook(({ isActive, resetKey }) => useTimer(isActive, resetKey), { initialProps: { isActive: true, resetKey: 0 } });
70
+ const { result, rerender } = renderTimerHook(true, 0);
50
71
  act(() => {
51
72
  vi.advanceTimersByTime(3000); // 3s
52
73
  });
53
74
  expect(result.current).toBe(3);
54
- rerender({ isActive: true, resetKey: 1 }); // Change resetKey
75
+ act(() => {
76
+ rerender({ isActive: true, resetKey: 1 }); // Change resetKey
77
+ });
55
78
  expect(result.current).toBe(0); // Should reset to 0
56
79
  act(() => {
57
80
  vi.advanceTimersByTime(1000);
@@ -59,27 +82,33 @@ describe('useTimer', () => {
59
82
  expect(result.current).toBe(1); // Starts incrementing from 0
60
83
  });
61
84
  it('should be 0 if isActive is false, regardless of resetKey changes', () => {
62
- const { result, rerender } = renderHook(({ isActive, resetKey }) => useTimer(isActive, resetKey), { initialProps: { isActive: false, resetKey: 0 } });
85
+ const { result, rerender } = renderTimerHook(false, 0);
63
86
  expect(result.current).toBe(0);
64
- rerender({ isActive: false, resetKey: 1 });
87
+ act(() => {
88
+ rerender({ isActive: false, resetKey: 1 });
89
+ });
65
90
  expect(result.current).toBe(0);
66
91
  });
67
92
  it('should clear timer on unmount', () => {
68
- const { unmount } = renderHook(() => useTimer(true, 0));
93
+ const { unmount } = renderTimerHook(true, 0);
69
94
  const clearIntervalSpy = vi.spyOn(global, 'clearInterval');
70
95
  unmount();
71
96
  expect(clearIntervalSpy).toHaveBeenCalledOnce();
72
97
  });
73
98
  it('should preserve elapsedTime when isActive becomes false, and reset to 0 when it becomes active again', () => {
74
- const { result, rerender } = renderHook(({ isActive, resetKey }) => useTimer(isActive, resetKey), { initialProps: { isActive: true, resetKey: 0 } });
99
+ const { result, rerender } = renderTimerHook(true, 0);
75
100
  act(() => {
76
101
  vi.advanceTimersByTime(3000); // Advance to 3 seconds
77
102
  });
78
103
  expect(result.current).toBe(3);
79
- rerender({ isActive: false, resetKey: 0 });
104
+ act(() => {
105
+ rerender({ isActive: false, resetKey: 0 });
106
+ });
80
107
  expect(result.current).toBe(3); // Time should be preserved when timer becomes inactive
81
108
  // Now make it active again, it should reset to 0
82
- rerender({ isActive: true, resetKey: 0 });
109
+ act(() => {
110
+ rerender({ isActive: true, resetKey: 0 });
111
+ });
83
112
  expect(result.current).toBe(0);
84
113
  act(() => {
85
114
  vi.advanceTimersByTime(1000);
@@ -1 +1 @@
1
- {"version":3,"file":"useTimer.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useTimer.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useTimer.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useTimer.test.tsx"],"names":[],"mappings":"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"}
@@ -4,13 +4,19 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { renderHook, act } from '@testing-library/react';
7
+ import { act } from 'react';
8
+ import { renderHook } from '../../test-utils/render.js';
8
9
  import { useReactToolScheduler, mapToDisplay, } from './useReactToolScheduler.js';
9
10
  import { DEFAULT_TRUNCATE_TOOL_OUTPUT_LINES, DEFAULT_TRUNCATE_TOOL_OUTPUT_THRESHOLD, ToolConfirmationOutcome, ApprovalMode, MockTool, } from '@google/gemini-cli-core';
10
11
  import { ToolCallStatus } from '../types.js';
11
12
  // Mocks
12
13
  vi.mock('@google/gemini-cli-core', async () => {
13
14
  const actual = await vi.importActual('@google/gemini-cli-core');
15
+ // Patch CoreToolScheduler to have cancelAll if it's missing in the test environment
16
+ if (actual.CoreToolScheduler &&
17
+ !actual.CoreToolScheduler.prototype.cancelAll) {
18
+ actual.CoreToolScheduler.prototype.cancelAll = vi.fn();
19
+ }
14
20
  return {
15
21
  ...actual,
16
22
  ToolRegistry: vi.fn(),
@@ -104,13 +110,13 @@ describe('useReactToolScheduler in YOLO Mode', () => {
104
110
  schedule(request, new AbortController().signal);
105
111
  });
106
112
  await act(async () => {
107
- await vi.runAllTimersAsync(); // Process validation
113
+ await vi.advanceTimersByTimeAsync(0); // Process validation
108
114
  });
109
115
  await act(async () => {
110
- await vi.runAllTimersAsync(); // Process scheduling
116
+ await vi.advanceTimersByTimeAsync(0); // Process scheduling
111
117
  });
112
118
  await act(async () => {
113
- await vi.runAllTimersAsync(); // Process execution
119
+ await vi.advanceTimersByTimeAsync(0); // Process execution
114
120
  });
115
121
  // Check that execute WAS called
116
122
  expect(mockToolRequiresConfirmation.execute).toHaveBeenCalledWith(request.args);
@@ -181,17 +187,21 @@ describe('useReactToolScheduler', () => {
181
187
  name: 'mockTool',
182
188
  args: { param: 'value' },
183
189
  };
190
+ let completedToolCalls = [];
191
+ onComplete.mockImplementation((calls) => {
192
+ completedToolCalls = calls;
193
+ });
184
194
  act(() => {
185
195
  schedule(request, new AbortController().signal);
186
196
  });
187
197
  await act(async () => {
188
- await vi.runAllTimersAsync();
198
+ await vi.advanceTimersByTimeAsync(0);
189
199
  });
190
200
  await act(async () => {
191
- await vi.runAllTimersAsync();
201
+ await vi.advanceTimersByTimeAsync(0);
192
202
  });
193
203
  await act(async () => {
194
- await vi.runAllTimersAsync();
204
+ await vi.advanceTimersByTimeAsync(0);
195
205
  });
196
206
  expect(mockTool.execute).toHaveBeenCalledWith(request.args);
197
207
  expect(onComplete).toHaveBeenCalledWith([
@@ -212,42 +222,123 @@ describe('useReactToolScheduler', () => {
212
222
  }),
213
223
  }),
214
224
  ]);
215
- expect(result.current[0]).toEqual([]);
225
+ expect(completedToolCalls).toHaveLength(1);
226
+ expect(completedToolCalls[0].status).toBe('success');
227
+ expect(completedToolCalls[0].request).toBe(request);
216
228
  });
217
- it('should handle tool not found', async () => {
218
- mockToolRegistry.getTool.mockReturnValue(undefined);
229
+ it('should clear previous tool calls when scheduling new ones', async () => {
230
+ mockToolRegistry.getTool.mockReturnValue(mockTool);
231
+ mockTool.execute.mockResolvedValue({
232
+ llmContent: 'Tool output',
233
+ returnDisplay: 'Formatted tool output',
234
+ });
235
+ const { result } = renderScheduler();
236
+ const schedule = result.current[1];
237
+ const setToolCallsForDisplay = result.current[3];
238
+ // Manually set a tool call in the display.
239
+ const oldToolCall = {
240
+ request: { callId: 'oldCall' },
241
+ status: 'success',
242
+ };
243
+ act(() => {
244
+ setToolCallsForDisplay([oldToolCall]);
245
+ });
246
+ expect(result.current[0]).toEqual([oldToolCall]);
247
+ const newRequest = {
248
+ callId: 'newCall',
249
+ name: 'mockTool',
250
+ args: {},
251
+ };
252
+ act(() => {
253
+ schedule(newRequest, new AbortController().signal);
254
+ });
255
+ // After scheduling, the old call should be gone,
256
+ // and the new one should be in the display in its initial state.
257
+ expect(result.current[0].length).toBe(1);
258
+ expect(result.current[0][0].request.callId).toBe('newCall');
259
+ expect(result.current[0][0].request.callId).not.toBe('oldCall');
260
+ // Let the new call finish.
261
+ await act(async () => {
262
+ await vi.advanceTimersByTimeAsync(0);
263
+ });
264
+ await act(async () => {
265
+ await vi.advanceTimersByTimeAsync(0);
266
+ });
267
+ await act(async () => {
268
+ await vi.advanceTimersByTimeAsync(0);
269
+ });
270
+ expect(onComplete).toHaveBeenCalled();
271
+ });
272
+ it('should cancel all running tool calls', async () => {
273
+ mockToolRegistry.getTool.mockReturnValue(mockTool);
274
+ let resolveExecute = () => { };
275
+ const executePromise = new Promise((resolve) => {
276
+ resolveExecute = resolve;
277
+ });
278
+ mockTool.execute.mockReturnValue(executePromise);
279
+ mockTool.shouldConfirmExecute.mockResolvedValue(null);
219
280
  const { result } = renderScheduler();
220
281
  const schedule = result.current[1];
282
+ const cancelAllToolCalls = result.current[4];
221
283
  const request = {
222
- callId: 'call1',
223
- name: 'nonexistentTool',
284
+ callId: 'cancelCall',
285
+ name: 'mockTool',
224
286
  args: {},
225
287
  };
226
288
  act(() => {
227
289
  schedule(request, new AbortController().signal);
228
290
  });
229
291
  await act(async () => {
230
- await vi.runAllTimersAsync();
292
+ await vi.advanceTimersByTimeAsync(0);
293
+ }); // validation
294
+ await act(async () => {
295
+ await vi.advanceTimersByTimeAsync(0); // Process scheduling
296
+ });
297
+ // At this point, the tool is 'executing' and waiting on the promise.
298
+ expect(result.current[0][0].status).toBe('executing');
299
+ const cancelController = new AbortController();
300
+ act(() => {
301
+ cancelAllToolCalls(cancelController.signal);
231
302
  });
232
303
  await act(async () => {
233
- await vi.runAllTimersAsync();
304
+ await vi.advanceTimersByTimeAsync(0);
234
305
  });
235
306
  expect(onComplete).toHaveBeenCalledWith([
236
307
  expect.objectContaining({
237
- status: 'error',
308
+ status: 'cancelled',
238
309
  request,
239
- response: expect.objectContaining({
240
- error: expect.objectContaining({
241
- message: expect.stringMatching(/Tool "nonexistentTool" not found in registry/),
242
- }),
243
- }),
244
310
  }),
245
311
  ]);
246
- const errorMessage = onComplete.mock.calls[0][0][0].response.error.message;
247
- expect(errorMessage).toContain('Did you mean one of:');
248
- expect(errorMessage).toContain('"mockTool"');
249
- expect(errorMessage).toContain('"anotherTool"');
250
- expect(result.current[0]).toEqual([]);
312
+ // Clean up the pending promise to avoid open handles.
313
+ resolveExecute({ llmContent: 'output', returnDisplay: 'display' });
314
+ });
315
+ it('should handle tool not found', async () => {
316
+ mockToolRegistry.getTool.mockReturnValue(undefined);
317
+ const { result } = renderScheduler();
318
+ const schedule = result.current[1];
319
+ const request = {
320
+ callId: 'call1',
321
+ name: 'nonexistentTool',
322
+ args: {},
323
+ };
324
+ let completedToolCalls = [];
325
+ onComplete.mockImplementation((calls) => {
326
+ completedToolCalls = calls;
327
+ });
328
+ act(() => {
329
+ schedule(request, new AbortController().signal);
330
+ });
331
+ await act(async () => {
332
+ await vi.advanceTimersByTimeAsync(0);
333
+ });
334
+ await act(async () => {
335
+ await vi.advanceTimersByTimeAsync(0);
336
+ });
337
+ expect(completedToolCalls).toHaveLength(1);
338
+ expect(completedToolCalls[0].status).toBe('error');
339
+ expect(completedToolCalls[0].request).toBe(request);
340
+ expect(completedToolCalls[0].response.error.message).toContain('Tool "nonexistentTool" not found in registry');
341
+ expect(completedToolCalls[0].response.error.message).toContain('Did you mean one of:');
251
342
  });
252
343
  it('should handle error during shouldConfirmExecute', async () => {
253
344
  mockToolRegistry.getTool.mockReturnValue(mockTool);
@@ -260,25 +351,23 @@ describe('useReactToolScheduler', () => {
260
351
  name: 'mockTool',
261
352
  args: {},
262
353
  };
354
+ let completedToolCalls = [];
355
+ onComplete.mockImplementation((calls) => {
356
+ completedToolCalls = calls;
357
+ });
263
358
  act(() => {
264
359
  schedule(request, new AbortController().signal);
265
360
  });
266
361
  await act(async () => {
267
- await vi.runAllTimersAsync();
362
+ await vi.advanceTimersByTimeAsync(0);
268
363
  });
269
364
  await act(async () => {
270
- await vi.runAllTimersAsync();
365
+ await vi.advanceTimersByTimeAsync(0);
271
366
  });
272
- expect(onComplete).toHaveBeenCalledWith([
273
- expect.objectContaining({
274
- status: 'error',
275
- request,
276
- response: expect.objectContaining({
277
- error: confirmError,
278
- }),
279
- }),
280
- ]);
281
- expect(result.current[0]).toEqual([]);
367
+ expect(completedToolCalls).toHaveLength(1);
368
+ expect(completedToolCalls[0].status).toBe('error');
369
+ expect(completedToolCalls[0].request).toBe(request);
370
+ expect(completedToolCalls[0].response.error).toBe(confirmError);
282
371
  });
283
372
  it('should handle error during execute', async () => {
284
373
  mockToolRegistry.getTool.mockReturnValue(mockTool);
@@ -292,28 +381,26 @@ describe('useReactToolScheduler', () => {
292
381
  name: 'mockTool',
293
382
  args: {},
294
383
  };
384
+ let completedToolCalls = [];
385
+ onComplete.mockImplementation((calls) => {
386
+ completedToolCalls = calls;
387
+ });
295
388
  act(() => {
296
389
  schedule(request, new AbortController().signal);
297
390
  });
298
391
  await act(async () => {
299
- await vi.runAllTimersAsync();
392
+ await vi.advanceTimersByTimeAsync(0);
300
393
  });
301
394
  await act(async () => {
302
- await vi.runAllTimersAsync();
395
+ await vi.advanceTimersByTimeAsync(0);
303
396
  });
304
397
  await act(async () => {
305
- await vi.runAllTimersAsync();
398
+ await vi.advanceTimersByTimeAsync(0);
306
399
  });
307
- expect(onComplete).toHaveBeenCalledWith([
308
- expect.objectContaining({
309
- status: 'error',
310
- request,
311
- response: expect.objectContaining({
312
- error: execError,
313
- }),
314
- }),
315
- ]);
316
- expect(result.current[0]).toEqual([]);
400
+ expect(completedToolCalls).toHaveLength(1);
401
+ expect(completedToolCalls[0].status).toBe('error');
402
+ expect(completedToolCalls[0].request).toBe(request);
403
+ expect(completedToolCalls[0].response.error).toBe(execError);
317
404
  });
318
405
  it('should handle tool requiring confirmation - approved', async () => {
319
406
  mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
@@ -333,7 +420,7 @@ describe('useReactToolScheduler', () => {
333
420
  schedule(request, new AbortController().signal);
334
421
  });
335
422
  await act(async () => {
336
- await vi.runAllTimersAsync();
423
+ await vi.advanceTimersByTimeAsync(0);
337
424
  });
338
425
  const waitingCall = result.current[0][0];
339
426
  expect(waitingCall.status).toBe('awaiting_approval');
@@ -343,13 +430,13 @@ describe('useReactToolScheduler', () => {
343
430
  await capturedOnConfirmForTest?.(ToolConfirmationOutcome.ProceedOnce);
344
431
  });
345
432
  await act(async () => {
346
- await vi.runAllTimersAsync();
433
+ await vi.advanceTimersByTimeAsync(0);
347
434
  });
348
435
  await act(async () => {
349
- await vi.runAllTimersAsync();
436
+ await vi.advanceTimersByTimeAsync(0);
350
437
  });
351
438
  await act(async () => {
352
- await vi.runAllTimersAsync();
439
+ await vi.advanceTimersByTimeAsync(0);
353
440
  });
354
441
  expect(mockOnUserConfirmForToolConfirmation).toHaveBeenCalledWith(ToolConfirmationOutcome.ProceedOnce);
355
442
  expect(mockToolRequiresConfirmation.execute).toHaveBeenCalled();
@@ -383,7 +470,7 @@ describe('useReactToolScheduler', () => {
383
470
  schedule(request, new AbortController().signal);
384
471
  });
385
472
  await act(async () => {
386
- await vi.runAllTimersAsync();
473
+ await vi.advanceTimersByTimeAsync(0);
387
474
  });
388
475
  const waitingCall = result.current[0][0];
389
476
  expect(waitingCall.status).toBe('awaiting_approval');
@@ -393,10 +480,10 @@ describe('useReactToolScheduler', () => {
393
480
  await capturedOnConfirmForTest?.(ToolConfirmationOutcome.Cancel);
394
481
  });
395
482
  await act(async () => {
396
- await vi.runAllTimersAsync();
483
+ await vi.advanceTimersByTimeAsync(0);
397
484
  });
398
485
  await act(async () => {
399
- await vi.runAllTimersAsync();
486
+ await vi.advanceTimersByTimeAsync(0);
400
487
  });
401
488
  expect(mockOnUserConfirmForToolConfirmation).toHaveBeenCalledWith(ToolConfirmationOutcome.Cancel);
402
489
  expect(onComplete).toHaveBeenCalledWith([
@@ -408,7 +495,7 @@ describe('useReactToolScheduler', () => {
408
495
  expect.objectContaining({
409
496
  functionResponse: expect.objectContaining({
410
497
  response: expect.objectContaining({
411
- error: '[Operation Cancelled] Reason: User did not allow tool call',
498
+ error: '[Operation Cancelled] Reason: User cancelled the operation.',
412
499
  }),
413
500
  }),
414
501
  }),
@@ -440,7 +527,7 @@ describe('useReactToolScheduler', () => {
440
527
  schedule(request, new AbortController().signal);
441
528
  });
442
529
  await act(async () => {
443
- await vi.runAllTimersAsync();
530
+ await vi.advanceTimersByTimeAsync(0);
444
531
  });
445
532
  expect(liveUpdateFn).toBeDefined();
446
533
  expect(result.current[0][0].status).toBe('executing');
@@ -448,13 +535,13 @@ describe('useReactToolScheduler', () => {
448
535
  liveUpdateFn?.('Live output 1');
449
536
  });
450
537
  await act(async () => {
451
- await vi.runAllTimersAsync();
538
+ await vi.advanceTimersByTimeAsync(0);
452
539
  });
453
540
  await act(async () => {
454
541
  liveUpdateFn?.('Live output 2');
455
542
  });
456
543
  await act(async () => {
457
- await vi.runAllTimersAsync();
544
+ await vi.advanceTimersByTimeAsync(0);
458
545
  });
459
546
  act(() => {
460
547
  resolveExecutePromise({
@@ -463,10 +550,10 @@ describe('useReactToolScheduler', () => {
463
550
  });
464
551
  });
465
552
  await act(async () => {
466
- await vi.runAllTimersAsync();
553
+ await vi.advanceTimersByTimeAsync(0);
467
554
  });
468
555
  await act(async () => {
469
- await vi.runAllTimersAsync();
556
+ await vi.advanceTimersByTimeAsync(0);
470
557
  });
471
558
  expect(onComplete).toHaveBeenCalledWith([
472
559
  expect.objectContaining({
@@ -520,16 +607,16 @@ describe('useReactToolScheduler', () => {
520
607
  schedule(requests, new AbortController().signal);
521
608
  });
522
609
  await act(async () => {
523
- await vi.runAllTimersAsync();
610
+ await vi.advanceTimersByTimeAsync(0);
524
611
  });
525
612
  await act(async () => {
526
- await vi.runAllTimersAsync();
613
+ await vi.advanceTimersByTimeAsync(0);
527
614
  });
528
615
  await act(async () => {
529
- await vi.runAllTimersAsync();
616
+ await vi.advanceTimersByTimeAsync(0);
530
617
  });
531
618
  await act(async () => {
532
- await vi.runAllTimersAsync();
619
+ await vi.advanceTimersByTimeAsync(0);
533
620
  });
534
621
  expect(onComplete).toHaveBeenCalledTimes(1);
535
622
  const completedCalls = onComplete.mock.calls[0][0];
@@ -568,7 +655,8 @@ describe('useReactToolScheduler', () => {
568
655
  ],
569
656
  }),
570
657
  });
571
- expect(result.current[0]).toEqual([]);
658
+ expect(completedCalls).toHaveLength(2);
659
+ expect(completedCalls.every((t) => t.status === 'success')).toBe(true);
572
660
  });
573
661
  it('should queue if scheduling while already running', async () => {
574
662
  mockToolRegistry.getTool.mockReturnValue(mockTool);
@@ -594,14 +682,14 @@ describe('useReactToolScheduler', () => {
594
682
  schedule(request1, new AbortController().signal);
595
683
  });
596
684
  await act(async () => {
597
- await vi.runAllTimersAsync();
685
+ await vi.advanceTimersByTimeAsync(0);
598
686
  });
599
687
  schedule(request2, new AbortController().signal);
600
688
  await act(async () => {
601
689
  await vi.advanceTimersByTimeAsync(50);
602
- await vi.runAllTimersAsync();
690
+ await vi.advanceTimersByTimeAsync(0);
603
691
  await act(async () => {
604
- await vi.runAllTimersAsync();
692
+ await vi.advanceTimersByTimeAsync(0);
605
693
  });
606
694
  });
607
695
  expect(onComplete).toHaveBeenCalledWith([
@@ -614,9 +702,9 @@ describe('useReactToolScheduler', () => {
614
702
  // Wait for request2 to complete
615
703
  await act(async () => {
616
704
  await vi.advanceTimersByTimeAsync(50);
617
- await vi.runAllTimersAsync();
705
+ await vi.advanceTimersByTimeAsync(0);
618
706
  await act(async () => {
619
- await vi.runAllTimersAsync();
707
+ await vi.advanceTimersByTimeAsync(0);
620
708
  });
621
709
  });
622
710
  expect(onComplete).toHaveBeenCalledWith([
@@ -626,7 +714,8 @@ describe('useReactToolScheduler', () => {
626
714
  response: expect.objectContaining({ resultDisplay: 'done display' }),
627
715
  }),
628
716
  ]);
629
- expect(result.current[0]).toEqual([]);
717
+ const toolCalls = result.current[0];
718
+ expect(toolCalls).toHaveLength(0);
630
719
  });
631
720
  });
632
721
  describe('mapToDisplay', () => {