@google/gemini-cli 0.11.0-preview.0 → 0.12.0-nightly.20251023.c4c0c0d1
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.
- package/dist/google-gemini-cli-0.12.0-nightly.20251022.0542de95.tgz +0 -0
- package/dist/package.json +4 -3
- package/dist/src/commands/extensions/disable.js +13 -6
- package/dist/src/commands/extensions/disable.js.map +1 -1
- package/dist/src/commands/extensions/enable.js +13 -6
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/install.js +12 -2
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +11 -3
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.js +12 -2
- package/dist/src/commands/extensions/link.js.map +1 -1
- package/dist/src/commands/extensions/list.js +13 -4
- package/dist/src/commands/extensions/list.js.map +1 -1
- package/dist/src/commands/extensions/uninstall.js +12 -2
- package/dist/src/commands/extensions/uninstall.js.map +1 -1
- package/dist/src/commands/extensions/update.js +17 -13
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions.js +1 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/list.js +10 -3
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/list.test.js +12 -6
- package/dist/src/commands/mcp/list.test.js.map +1 -1
- package/dist/src/config/config.js +12 -0
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +11 -0
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extension-manager.d.ts +38 -0
- package/dist/src/config/extension-manager.js +412 -0
- package/dist/src/config/extension-manager.js.map +1 -0
- package/dist/src/config/extension.d.ts +4 -51
- package/dist/src/config/extension.js +1 -535
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extension.test.js +316 -159
- package/dist/src/config/extension.test.js.map +1 -1
- package/dist/src/config/extensions/consent.d.ts +38 -0
- package/dist/src/config/extensions/consent.js +123 -0
- package/dist/src/config/extensions/consent.js.map +1 -0
- package/dist/src/config/extensions/extensionEnablement.js +1 -1
- package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
- package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
- package/dist/src/config/extensions/extensionSettings.js +63 -0
- package/dist/src/config/extensions/extensionSettings.js.map +1 -0
- package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
- package/dist/src/config/extensions/extensionSettings.test.js +137 -0
- package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
- package/dist/src/config/extensions/github.d.ts +2 -2
- package/dist/src/config/extensions/github.js +3 -8
- package/dist/src/config/extensions/github.js.map +1 -1
- package/dist/src/config/extensions/github.test.js +25 -7
- package/dist/src/config/extensions/github.test.js.map +1 -1
- package/dist/src/config/extensions/storage.d.ts +14 -0
- package/dist/src/config/extensions/storage.js +32 -0
- package/dist/src/config/extensions/storage.js.map +1 -0
- package/dist/src/config/extensions/update.d.ts +4 -4
- package/dist/src/config/extensions/update.js +11 -18
- package/dist/src/config/extensions/update.js.map +1 -1
- package/dist/src/config/extensions/update.test.js +32 -58
- package/dist/src/config/extensions/update.test.js.map +1 -1
- package/dist/src/config/extensions/variableSchema.d.ts +0 -6
- package/dist/src/config/extensions/variableSchema.js.map +1 -1
- package/dist/src/config/extensions/variables.d.ts +4 -0
- package/dist/src/config/extensions/variables.js +6 -0
- package/dist/src/config/extensions/variables.js.map +1 -1
- package/dist/src/config/settings.d.ts +2 -1
- package/dist/src/config/settings.js +4 -7
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.js +113 -14
- package/dist/src/config/settings.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +9 -0
- package/dist/src/config/settingsSchema.js +9 -0
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/gemini.js +22 -5
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/nonInteractiveCli.js +14 -1
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +84 -2
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/test-utils/createExtension.d.ts +3 -1
- package/dist/src/test-utils/createExtension.js +3 -3
- package/dist/src/test-utils/createExtension.js.map +1 -1
- package/dist/src/ui/AppContainer.js +101 -47
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +138 -79
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.js +19 -10
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.test.js +8 -0
- package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +5 -6
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +249 -393
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +0 -29
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
- package/dist/src/ui/components/views/ExtensionsList.js +4 -10
- package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.test.js +34 -21
- package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.js +328 -335
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +30 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -4
- package/dist/src/ui/hooks/useExtensionUpdates.js +14 -17
- package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +23 -30
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.js +4 -0
- package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js +19 -21
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +22 -8
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
- package/dist/src/ui/hooks/useToolScheduler.test.js +30 -48
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/types.d.ts +2 -1
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.js +2 -1
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +2 -2
- package/dist/src/utils/envVarResolver.js +10 -7
- package/dist/src/utils/envVarResolver.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +4 -4
- package/dist/src/zed-integration/zedIntegration.js +3 -3
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
|
@@ -7,7 +7,9 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
7
7
|
import { act } from 'react';
|
|
8
8
|
import { renderHook, waitFor } from '@testing-library/react';
|
|
9
9
|
import { useGitBranchName } from './useGitBranchName.js';
|
|
10
|
-
import { fs, vol } from 'memfs';
|
|
10
|
+
import { fs, vol } from 'memfs';
|
|
11
|
+
import * as fsPromises from 'node:fs/promises';
|
|
12
|
+
import path from 'node:path'; // For mocking fs
|
|
11
13
|
import { spawnAsync as mockSpawnAsync } from '@google/gemini-cli-core';
|
|
12
14
|
// Mock @google/gemini-cli-core
|
|
13
15
|
vi.mock('@google/gemini-cli-core', async () => {
|
|
@@ -27,21 +29,19 @@ vi.mock('node:fs', async () => {
|
|
|
27
29
|
});
|
|
28
30
|
vi.mock('node:fs/promises', async () => {
|
|
29
31
|
const memfs = await vi.importActual('memfs');
|
|
30
|
-
return memfs.fs.promises;
|
|
32
|
+
return { ...memfs.fs.promises, default: memfs.fs.promises };
|
|
31
33
|
});
|
|
32
34
|
const CWD = '/test/project';
|
|
33
|
-
const GIT_LOGS_HEAD_PATH =
|
|
35
|
+
const GIT_LOGS_HEAD_PATH = path.join(CWD, '.git', 'logs', 'HEAD');
|
|
34
36
|
describe('useGitBranchName', () => {
|
|
35
37
|
beforeEach(() => {
|
|
36
38
|
vol.reset(); // Reset in-memory filesystem
|
|
37
39
|
vol.fromJSON({
|
|
38
40
|
[GIT_LOGS_HEAD_PATH]: 'ref: refs/heads/main',
|
|
39
41
|
});
|
|
40
|
-
vi.useFakeTimers(); // Use fake timers for async operations
|
|
41
42
|
});
|
|
42
43
|
afterEach(() => {
|
|
43
44
|
vi.restoreAllMocks();
|
|
44
|
-
vi.clearAllTimers();
|
|
45
45
|
});
|
|
46
46
|
it('should return branch name', async () => {
|
|
47
47
|
mockSpawnAsync.mockResolvedValue({
|
|
@@ -49,7 +49,6 @@ describe('useGitBranchName', () => {
|
|
|
49
49
|
});
|
|
50
50
|
const { result, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
51
51
|
await act(async () => {
|
|
52
|
-
vi.runAllTimers(); // Advance timers to trigger useEffect and exec callback
|
|
53
52
|
rerender(); // Rerender to get the updated state
|
|
54
53
|
});
|
|
55
54
|
expect(result.current).toBe('main');
|
|
@@ -59,7 +58,6 @@ describe('useGitBranchName', () => {
|
|
|
59
58
|
const { result, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
60
59
|
expect(result.current).toBeUndefined();
|
|
61
60
|
await act(async () => {
|
|
62
|
-
vi.runAllTimers();
|
|
63
61
|
rerender();
|
|
64
62
|
});
|
|
65
63
|
expect(result.current).toBeUndefined();
|
|
@@ -76,7 +74,6 @@ describe('useGitBranchName', () => {
|
|
|
76
74
|
});
|
|
77
75
|
const { result, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
78
76
|
await act(async () => {
|
|
79
|
-
vi.runAllTimers();
|
|
80
77
|
rerender();
|
|
81
78
|
});
|
|
82
79
|
expect(result.current).toBe('a1b2c3d');
|
|
@@ -93,27 +90,28 @@ describe('useGitBranchName', () => {
|
|
|
93
90
|
});
|
|
94
91
|
const { result, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
95
92
|
await act(async () => {
|
|
96
|
-
vi.runAllTimers();
|
|
97
93
|
rerender();
|
|
98
94
|
});
|
|
99
95
|
expect(result.current).toBeUndefined();
|
|
100
96
|
});
|
|
101
|
-
it('should update branch name when .git/HEAD changes', async (
|
|
102
|
-
|
|
97
|
+
it('should update branch name when .git/HEAD changes', async () => {
|
|
98
|
+
vi.spyOn(fsPromises, 'access').mockResolvedValue(undefined);
|
|
99
|
+
const watchSpy = vi.spyOn(fs, 'watch');
|
|
103
100
|
mockSpawnAsync
|
|
104
101
|
.mockResolvedValueOnce({ stdout: 'main\n' })
|
|
105
|
-
.
|
|
102
|
+
.mockResolvedValue({ stdout: 'develop\n' });
|
|
106
103
|
const { result, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
107
104
|
await act(async () => {
|
|
108
|
-
vi.runAllTimers();
|
|
109
105
|
rerender();
|
|
110
106
|
});
|
|
111
107
|
expect(result.current).toBe('main');
|
|
108
|
+
// Wait for watcher to be set up
|
|
109
|
+
await waitFor(() => {
|
|
110
|
+
expect(watchSpy).toHaveBeenCalled();
|
|
111
|
+
});
|
|
112
112
|
// Simulate file change event
|
|
113
|
-
// Ensure the watcher is set up before triggering the change
|
|
114
113
|
await act(async () => {
|
|
115
114
|
fs.writeFileSync(GIT_LOGS_HEAD_PATH, 'ref: refs/heads/develop'); // Trigger watcher
|
|
116
|
-
vi.runAllTimers(); // Process timers for watcher and exec
|
|
117
115
|
rerender();
|
|
118
116
|
});
|
|
119
117
|
await waitFor(() => {
|
|
@@ -128,7 +126,6 @@ describe('useGitBranchName', () => {
|
|
|
128
126
|
});
|
|
129
127
|
const { result, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
130
128
|
await act(async () => {
|
|
131
|
-
vi.runAllTimers();
|
|
132
129
|
rerender();
|
|
133
130
|
});
|
|
134
131
|
expect(result.current).toBe('main'); // Branch name should still be fetched initially
|
|
@@ -143,14 +140,13 @@ describe('useGitBranchName', () => {
|
|
|
143
140
|
});
|
|
144
141
|
await act(async () => {
|
|
145
142
|
fs.writeFileSync(GIT_LOGS_HEAD_PATH, 'ref: refs/heads/develop');
|
|
146
|
-
vi.runAllTimers();
|
|
147
143
|
rerender();
|
|
148
144
|
});
|
|
149
145
|
// Branch name should not change because watcher setup failed
|
|
150
146
|
expect(result.current).toBe('main');
|
|
151
147
|
});
|
|
152
|
-
it('should cleanup watcher on unmount', async (
|
|
153
|
-
|
|
148
|
+
it('should cleanup watcher on unmount', async () => {
|
|
149
|
+
vi.spyOn(fsPromises, 'access').mockResolvedValue(undefined);
|
|
154
150
|
const closeMock = vi.fn();
|
|
155
151
|
const watchMock = vi.spyOn(fs, 'watch').mockReturnValue({
|
|
156
152
|
close: closeMock,
|
|
@@ -160,11 +156,13 @@ describe('useGitBranchName', () => {
|
|
|
160
156
|
});
|
|
161
157
|
const { unmount, rerender } = renderHook(() => useGitBranchName(CWD));
|
|
162
158
|
await act(async () => {
|
|
163
|
-
vi.runAllTimers();
|
|
164
159
|
rerender();
|
|
165
160
|
});
|
|
161
|
+
// Wait for watcher to be set up BEFORE unmounting
|
|
162
|
+
await waitFor(() => {
|
|
163
|
+
expect(watchMock).toHaveBeenCalledWith(GIT_LOGS_HEAD_PATH, expect.any(Function));
|
|
164
|
+
});
|
|
166
165
|
unmount();
|
|
167
|
-
expect(watchMock).toHaveBeenCalledWith(GIT_LOGS_HEAD_PATH, expect.any(Function));
|
|
168
166
|
expect(closeMock).toHaveBeenCalled();
|
|
169
167
|
});
|
|
170
168
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useGitBranchName.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useGitBranchName.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,iBAAiB;
|
|
1
|
+
{"version":3,"file":"useGitBranchName.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useGitBranchName.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,10 +4,23 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { CoreToolScheduler, debugLogger } from '@google/gemini-cli-core';
|
|
7
|
-
import { useCallback, useState, useMemo } from 'react';
|
|
7
|
+
import { useCallback, useState, useMemo, useEffect, useRef } from 'react';
|
|
8
8
|
import { ToolCallStatus } from '../types.js';
|
|
9
9
|
export function useReactToolScheduler(onComplete, config, getPreferredEditor, onEditorClose) {
|
|
10
10
|
const [toolCallsForDisplay, setToolCallsForDisplay] = useState([]);
|
|
11
|
+
// Store callbacks in refs to keep them up-to-date without causing re-renders.
|
|
12
|
+
const onCompleteRef = useRef(onComplete);
|
|
13
|
+
const getPreferredEditorRef = useRef(getPreferredEditor);
|
|
14
|
+
const onEditorCloseRef = useRef(onEditorClose);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
onCompleteRef.current = onComplete;
|
|
17
|
+
}, [onComplete]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
getPreferredEditorRef.current = getPreferredEditor;
|
|
20
|
+
}, [getPreferredEditor]);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
onEditorCloseRef.current = onEditorClose;
|
|
23
|
+
}, [onEditorClose]);
|
|
11
24
|
const outputUpdateHandler = useCallback((toolCallId, outputChunk) => {
|
|
12
25
|
setToolCallsForDisplay((prevCalls) => prevCalls.map((tc) => {
|
|
13
26
|
if (tc.request.callId === toolCallId && tc.status === 'executing') {
|
|
@@ -18,8 +31,8 @@ export function useReactToolScheduler(onComplete, config, getPreferredEditor, on
|
|
|
18
31
|
}));
|
|
19
32
|
}, []);
|
|
20
33
|
const allToolCallsCompleteHandler = useCallback(async (completedToolCalls) => {
|
|
21
|
-
await
|
|
22
|
-
}, [
|
|
34
|
+
await onCompleteRef.current(completedToolCalls);
|
|
35
|
+
}, []);
|
|
23
36
|
const toolCallsUpdateHandler = useCallback((updatedCoreToolCalls) => {
|
|
24
37
|
setToolCallsForDisplay((prevTrackedCalls) => updatedCoreToolCalls.map((coreTc) => {
|
|
25
38
|
const existingTrackedCall = prevTrackedCalls.find((ptc) => ptc.request.callId === coreTc.request.callId);
|
|
@@ -45,21 +58,22 @@ export function useReactToolScheduler(onComplete, config, getPreferredEditor, on
|
|
|
45
58
|
};
|
|
46
59
|
}));
|
|
47
60
|
}, [setToolCallsForDisplay]);
|
|
61
|
+
const stableGetPreferredEditor = useCallback(() => getPreferredEditorRef.current(), []);
|
|
62
|
+
const stableOnEditorClose = useCallback(() => onEditorCloseRef.current(), []);
|
|
48
63
|
const scheduler = useMemo(() => new CoreToolScheduler({
|
|
49
64
|
outputUpdateHandler,
|
|
50
65
|
onAllToolCallsComplete: allToolCallsCompleteHandler,
|
|
51
66
|
onToolCallsUpdate: toolCallsUpdateHandler,
|
|
52
|
-
getPreferredEditor,
|
|
67
|
+
getPreferredEditor: stableGetPreferredEditor,
|
|
53
68
|
config,
|
|
54
|
-
onEditorClose,
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
69
|
+
onEditorClose: stableOnEditorClose,
|
|
56
70
|
}), [
|
|
57
71
|
config,
|
|
58
72
|
outputUpdateHandler,
|
|
59
73
|
allToolCallsCompleteHandler,
|
|
60
74
|
toolCallsUpdateHandler,
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
stableGetPreferredEditor,
|
|
76
|
+
stableOnEditorClose,
|
|
63
77
|
]);
|
|
64
78
|
const schedule = useCallback((request, signal) => {
|
|
65
79
|
void scheduler.schedule(request, signal);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useReactToolScheduler.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useReactToolScheduler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkBH,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useReactToolScheduler.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useReactToolScheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { CoreToolScheduler } from '@google/gemini-cli-core';
|
|
7
|
+
import { renderHook } from '@testing-library/react';
|
|
8
|
+
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
9
|
+
import { useReactToolScheduler } from './useReactToolScheduler.js';
|
|
10
|
+
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
|
|
11
|
+
const actual = await importOriginal();
|
|
12
|
+
return {
|
|
13
|
+
...actual,
|
|
14
|
+
CoreToolScheduler: vi.fn(),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
const mockCoreToolScheduler = vi.mocked(CoreToolScheduler);
|
|
18
|
+
describe('useReactToolScheduler', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
vi.clearAllMocks();
|
|
21
|
+
});
|
|
22
|
+
it('only creates one instance of CoreToolScheduler even if props change', () => {
|
|
23
|
+
const onComplete = vi.fn();
|
|
24
|
+
const getPreferredEditor = vi.fn();
|
|
25
|
+
const onEditorClose = vi.fn();
|
|
26
|
+
const config = {};
|
|
27
|
+
const { rerender } = renderHook((props) => useReactToolScheduler(props.onComplete, props.config, props.getPreferredEditor, props.onEditorClose), {
|
|
28
|
+
initialProps: {
|
|
29
|
+
onComplete,
|
|
30
|
+
config,
|
|
31
|
+
getPreferredEditor,
|
|
32
|
+
onEditorClose,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
expect(mockCoreToolScheduler).toHaveBeenCalledTimes(1);
|
|
36
|
+
// Rerender with a new onComplete function
|
|
37
|
+
const newOnComplete = vi.fn();
|
|
38
|
+
rerender({
|
|
39
|
+
onComplete: newOnComplete,
|
|
40
|
+
config,
|
|
41
|
+
getPreferredEditor,
|
|
42
|
+
onEditorClose,
|
|
43
|
+
});
|
|
44
|
+
expect(mockCoreToolScheduler).toHaveBeenCalledTimes(1);
|
|
45
|
+
// Rerender with a new getPreferredEditor function
|
|
46
|
+
const newGetPreferredEditor = vi.fn();
|
|
47
|
+
rerender({
|
|
48
|
+
onComplete: newOnComplete,
|
|
49
|
+
config,
|
|
50
|
+
getPreferredEditor: newGetPreferredEditor,
|
|
51
|
+
onEditorClose,
|
|
52
|
+
});
|
|
53
|
+
expect(mockCoreToolScheduler).toHaveBeenCalledTimes(1);
|
|
54
|
+
// Rerender with a new onEditorClose function
|
|
55
|
+
const newOnEditorClose = vi.fn();
|
|
56
|
+
rerender({
|
|
57
|
+
onComplete: newOnComplete,
|
|
58
|
+
config,
|
|
59
|
+
getPreferredEditor: newGetPreferredEditor,
|
|
60
|
+
onEditorClose: newOnEditorClose,
|
|
61
|
+
});
|
|
62
|
+
expect(mockCoreToolScheduler).toHaveBeenCalledTimes(1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=useReactToolScheduler.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useReactToolScheduler.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useReactToolScheduler.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,EAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC1D,MAAM,MAAM,GACV,MAAM,cAAc,EAA4C,CAAC;IACnE,OAAO;QACL,GAAG,MAAM;QACT,iBAAiB,EAAE,EAAE,CAAC,EAAE,EAAE;KAC3B,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAE3D,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,GAAG,EAAE;QAC7E,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,kBAAkB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,EAAY,CAAC;QAE5B,MAAM,EAAE,QAAQ,EAAE,GAAG,UAAU,CAC7B,CAAC,KAAK,EAAE,EAAE,CACR,qBAAqB,CACnB,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,kBAAkB,EACxB,KAAK,CAAC,aAAa,CACpB,EACH;YACE,YAAY,EAAE;gBACZ,UAAU;gBACV,MAAM;gBACN,kBAAkB;gBAClB,aAAa;aACd;SACF,CACF,CAAC;QAEF,MAAM,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAEvD,0CAA0C;QAC1C,MAAM,aAAa,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,QAAQ,CAAC;YACP,UAAU,EAAE,aAAa;YACzB,MAAM;YACN,kBAAkB;YAClB,aAAa;SACd,CAAC,CAAC;QACH,MAAM,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAEvD,kDAAkD;QAClD,MAAM,qBAAqB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,QAAQ,CAAC;YACP,UAAU,EAAE,aAAa;YACzB,MAAM;YACN,kBAAkB,EAAE,qBAAqB;YACzC,aAAa;SACd,CAAC,CAAC;QACH,MAAM,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAEvD,6CAA6C;QAC7C,MAAM,gBAAgB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACjC,QAAQ,CAAC;YACP,UAAU,EAAE,aAAa;YACzB,MAAM;YACN,kBAAkB,EAAE,qBAAqB;YACzC,aAAa,EAAE,gBAAgB;SAChC,CAAC,CAAC;QACH,MAAM,CAAC,qBAAqB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -70,10 +70,8 @@ const mockToolRequiresConfirmation = new MockTool({
|
|
|
70
70
|
});
|
|
71
71
|
describe('useReactToolScheduler in YOLO Mode', () => {
|
|
72
72
|
let onComplete;
|
|
73
|
-
let setPendingHistoryItem;
|
|
74
73
|
beforeEach(() => {
|
|
75
74
|
onComplete = vi.fn();
|
|
76
|
-
setPendingHistoryItem = vi.fn();
|
|
77
75
|
mockToolRegistry.getTool.mockClear();
|
|
78
76
|
mockToolRequiresConfirmation.execute.mockClear();
|
|
79
77
|
mockToolRequiresConfirmation.shouldConfirmExecute.mockClear();
|
|
@@ -87,7 +85,7 @@ describe('useReactToolScheduler in YOLO Mode', () => {
|
|
|
87
85
|
// IMPORTANT: Disable YOLO mode after this test suite
|
|
88
86
|
mockConfig.getApprovalMode.mockReturnValue(ApprovalMode.DEFAULT);
|
|
89
87
|
});
|
|
90
|
-
const renderSchedulerInYoloMode = () => renderHook(() => useReactToolScheduler(onComplete, mockConfig,
|
|
88
|
+
const renderSchedulerInYoloMode = () => renderHook(() => useReactToolScheduler(onComplete, mockConfig, () => undefined, () => { }));
|
|
91
89
|
it('should skip confirmation and execute tool directly when yoloMode is true', async () => {
|
|
92
90
|
mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
|
|
93
91
|
const expectedOutput = 'YOLO Confirmed output';
|
|
@@ -135,49 +133,14 @@ describe('useReactToolScheduler in YOLO Mode', () => {
|
|
|
135
133
|
}),
|
|
136
134
|
}),
|
|
137
135
|
]);
|
|
138
|
-
// Ensure no confirmation UI was triggered (setPendingHistoryItem should not have been called with confirmation details)
|
|
139
|
-
const setPendingHistoryItemCalls = setPendingHistoryItem.mock.calls;
|
|
140
|
-
const confirmationCall = setPendingHistoryItemCalls.find((call) => {
|
|
141
|
-
const item = typeof call[0] === 'function' ? call[0]({}) : call[0];
|
|
142
|
-
return item?.tools?.[0]?.confirmationDetails;
|
|
143
|
-
});
|
|
144
|
-
expect(confirmationCall).toBeUndefined();
|
|
145
136
|
});
|
|
146
137
|
});
|
|
147
138
|
describe('useReactToolScheduler', () => {
|
|
148
|
-
// TODO(ntaylormullen): The following tests are skipped due to difficulties in
|
|
149
|
-
// reliably testing the asynchronous state updates and interactions with timers.
|
|
150
|
-
// These tests involve complex sequences of events, including confirmations,
|
|
151
|
-
// live output updates, and cancellations, which are challenging to assert
|
|
152
|
-
// correctly with the current testing setup. Further investigation is needed
|
|
153
|
-
// to find a robust way to test these scenarios.
|
|
154
139
|
let onComplete;
|
|
155
|
-
let setPendingHistoryItem;
|
|
156
140
|
let capturedOnConfirmForTest;
|
|
157
141
|
beforeEach(() => {
|
|
158
142
|
onComplete = vi.fn();
|
|
159
143
|
capturedOnConfirmForTest = undefined;
|
|
160
|
-
setPendingHistoryItem = vi.fn((updaterOrValue) => {
|
|
161
|
-
let pendingItem = null;
|
|
162
|
-
if (typeof updaterOrValue === 'function') {
|
|
163
|
-
// Loosen the type for prevState to allow for more flexible updates in tests
|
|
164
|
-
const prevState = {
|
|
165
|
-
type: 'tool_group', // Still default to tool_group for most cases
|
|
166
|
-
tools: [],
|
|
167
|
-
};
|
|
168
|
-
pendingItem = updaterOrValue(prevState); // Allow any for more flexibility
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
pendingItem = updaterOrValue;
|
|
172
|
-
}
|
|
173
|
-
// Capture onConfirm if it exists, regardless of the exact type of pendingItem
|
|
174
|
-
// This is a common pattern in these tests.
|
|
175
|
-
if (pendingItem?.tools?.[0]?.confirmationDetails
|
|
176
|
-
?.onConfirm) {
|
|
177
|
-
capturedOnConfirmForTest = pendingItem
|
|
178
|
-
.tools[0].confirmationDetails?.onConfirm;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
144
|
mockToolRegistry.getTool.mockClear();
|
|
182
145
|
mockTool.execute.mockClear();
|
|
183
146
|
mockTool.shouldConfirmExecute.mockClear();
|
|
@@ -199,7 +162,7 @@ describe('useReactToolScheduler', () => {
|
|
|
199
162
|
vi.clearAllTimers();
|
|
200
163
|
vi.useRealTimers();
|
|
201
164
|
});
|
|
202
|
-
const renderScheduler = () => renderHook(() => useReactToolScheduler(onComplete, mockConfig,
|
|
165
|
+
const renderScheduler = () => renderHook(() => useReactToolScheduler(onComplete, mockConfig, () => undefined, () => { }));
|
|
203
166
|
it('initial state should be empty', () => {
|
|
204
167
|
const { result } = renderScheduler();
|
|
205
168
|
expect(result.current[0]).toEqual([]);
|
|
@@ -352,7 +315,7 @@ describe('useReactToolScheduler', () => {
|
|
|
352
315
|
]);
|
|
353
316
|
expect(result.current[0]).toEqual([]);
|
|
354
317
|
});
|
|
355
|
-
it
|
|
318
|
+
it('should handle tool requiring confirmation - approved', async () => {
|
|
356
319
|
mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
|
|
357
320
|
const expectedOutput = 'Confirmed output';
|
|
358
321
|
mockToolRequiresConfirmation.execute.mockResolvedValue({
|
|
@@ -372,7 +335,9 @@ describe('useReactToolScheduler', () => {
|
|
|
372
335
|
await act(async () => {
|
|
373
336
|
await vi.runAllTimersAsync();
|
|
374
337
|
});
|
|
375
|
-
|
|
338
|
+
const waitingCall = result.current[0][0];
|
|
339
|
+
expect(waitingCall.status).toBe('awaiting_approval');
|
|
340
|
+
capturedOnConfirmForTest = waitingCall.confirmationDetails?.onConfirm;
|
|
376
341
|
expect(capturedOnConfirmForTest).toBeDefined();
|
|
377
342
|
await act(async () => {
|
|
378
343
|
await capturedOnConfirmForTest?.(ToolConfirmationOutcome.ProceedOnce);
|
|
@@ -405,7 +370,7 @@ describe('useReactToolScheduler', () => {
|
|
|
405
370
|
}),
|
|
406
371
|
]);
|
|
407
372
|
});
|
|
408
|
-
it
|
|
373
|
+
it('should handle tool requiring confirmation - cancelled by user', async () => {
|
|
409
374
|
mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
|
|
410
375
|
const { result } = renderScheduler();
|
|
411
376
|
const schedule = result.current[1];
|
|
@@ -420,7 +385,9 @@ describe('useReactToolScheduler', () => {
|
|
|
420
385
|
await act(async () => {
|
|
421
386
|
await vi.runAllTimersAsync();
|
|
422
387
|
});
|
|
423
|
-
|
|
388
|
+
const waitingCall = result.current[0][0];
|
|
389
|
+
expect(waitingCall.status).toBe('awaiting_approval');
|
|
390
|
+
capturedOnConfirmForTest = waitingCall.confirmationDetails?.onConfirm;
|
|
424
391
|
expect(capturedOnConfirmForTest).toBeDefined();
|
|
425
392
|
await act(async () => {
|
|
426
393
|
await capturedOnConfirmForTest?.(ToolConfirmationOutcome.Cancel);
|
|
@@ -441,7 +408,7 @@ describe('useReactToolScheduler', () => {
|
|
|
441
408
|
expect.objectContaining({
|
|
442
409
|
functionResponse: expect.objectContaining({
|
|
443
410
|
response: expect.objectContaining({
|
|
444
|
-
error:
|
|
411
|
+
error: '[Operation Cancelled] Reason: User did not allow tool call',
|
|
445
412
|
}),
|
|
446
413
|
}),
|
|
447
414
|
}),
|
|
@@ -450,7 +417,7 @@ describe('useReactToolScheduler', () => {
|
|
|
450
417
|
}),
|
|
451
418
|
]);
|
|
452
419
|
});
|
|
453
|
-
it
|
|
420
|
+
it('should handle live output updates', async () => {
|
|
454
421
|
mockToolRegistry.getTool.mockReturnValue(mockToolWithLiveOutput);
|
|
455
422
|
let liveUpdateFn;
|
|
456
423
|
let resolveExecutePromise;
|
|
@@ -476,7 +443,7 @@ describe('useReactToolScheduler', () => {
|
|
|
476
443
|
await vi.runAllTimersAsync();
|
|
477
444
|
});
|
|
478
445
|
expect(liveUpdateFn).toBeDefined();
|
|
479
|
-
expect(
|
|
446
|
+
expect(result.current[0][0].status).toBe('executing');
|
|
480
447
|
await act(async () => {
|
|
481
448
|
liveUpdateFn?.('Live output 1');
|
|
482
449
|
});
|
|
@@ -603,7 +570,7 @@ describe('useReactToolScheduler', () => {
|
|
|
603
570
|
});
|
|
604
571
|
expect(result.current[0]).toEqual([]);
|
|
605
572
|
});
|
|
606
|
-
it
|
|
573
|
+
it('should queue if scheduling while already running', async () => {
|
|
607
574
|
mockToolRegistry.getTool.mockReturnValue(mockTool);
|
|
608
575
|
const longExecutePromise = new Promise((resolve) => setTimeout(() => resolve({
|
|
609
576
|
llmContent: 'done',
|
|
@@ -629,7 +596,7 @@ describe('useReactToolScheduler', () => {
|
|
|
629
596
|
await act(async () => {
|
|
630
597
|
await vi.runAllTimersAsync();
|
|
631
598
|
});
|
|
632
|
-
|
|
599
|
+
schedule(request2, new AbortController().signal);
|
|
633
600
|
await act(async () => {
|
|
634
601
|
await vi.advanceTimersByTimeAsync(50);
|
|
635
602
|
await vi.runAllTimersAsync();
|
|
@@ -644,6 +611,21 @@ describe('useReactToolScheduler', () => {
|
|
|
644
611
|
response: expect.objectContaining({ resultDisplay: 'done display' }),
|
|
645
612
|
}),
|
|
646
613
|
]);
|
|
614
|
+
// Wait for request2 to complete
|
|
615
|
+
await act(async () => {
|
|
616
|
+
await vi.advanceTimersByTimeAsync(50);
|
|
617
|
+
await vi.runAllTimersAsync();
|
|
618
|
+
await act(async () => {
|
|
619
|
+
await vi.runAllTimersAsync();
|
|
620
|
+
});
|
|
621
|
+
});
|
|
622
|
+
expect(onComplete).toHaveBeenCalledWith([
|
|
623
|
+
expect.objectContaining({
|
|
624
|
+
status: 'success',
|
|
625
|
+
request: request2,
|
|
626
|
+
response: expect.objectContaining({ resultDisplay: 'done display' }),
|
|
627
|
+
}),
|
|
628
|
+
]);
|
|
647
629
|
expect(result.current[0]).toEqual([]);
|
|
648
630
|
});
|
|
649
631
|
});
|