@google/gemini-cli-core 0.1.12 → 0.1.14
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/README.md +30 -3
- package/dist/google-gemini-cli-core-0.1.13.tgz +0 -0
- package/dist/src/code_assist/codeAssist.js +2 -2
- package/dist/src/code_assist/codeAssist.js.map +1 -1
- package/dist/src/code_assist/oauth2.js +46 -5
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +100 -3
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +4 -6
- package/dist/src/code_assist/server.js +4 -69
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +10 -2
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.d.ts +6 -1
- package/dist/src/code_assist/setup.js +4 -1
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js +4 -1
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +2 -2
- package/dist/src/config/config.d.ts +52 -11
- package/dist/src/config/config.js +79 -33
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +29 -26
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/flashFallback.test.js +1 -1
- package/dist/src/config/flashFallback.test.js.map +1 -1
- package/dist/src/core/client.d.ts +8 -3
- package/dist/src/core/client.js +62 -3
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +145 -37
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +3 -2
- package/dist/src/core/contentGenerator.js +5 -4
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +12 -5
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.js +14 -1
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +84 -2
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +4 -3
- package/dist/src/core/geminiChat.js +8 -11
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiRequest.js +2 -37
- package/dist/src/core/geminiRequest.js.map +1 -1
- package/dist/src/core/logger.js +6 -0
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +1 -1
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/modelCheck.d.ts +1 -1
- package/dist/src/core/modelCheck.js +10 -3
- package/dist/src/core/modelCheck.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +8 -5
- package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
- package/dist/src/core/prompts.js +42 -18
- package/dist/src/core/prompts.js.map +1 -1
- package/dist/src/core/prompts.test.js +121 -4
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/core/turn.d.ts +12 -3
- package/dist/src/core/turn.js +10 -0
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/core/turn.test.js +129 -0
- package/dist/src/core/turn.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +28 -0
- package/dist/src/ide/ide-client.js +79 -0
- package/dist/src/ide/ide-client.js.map +1 -0
- package/dist/src/ide/ideContext.d.ts +174 -0
- package/dist/src/ide/ideContext.js +101 -0
- package/dist/src/ide/ideContext.js.map +1 -0
- package/dist/src/ide/ideContext.test.js +111 -0
- package/dist/src/ide/ideContext.test.js.map +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/google-auth-provider.d.ts +23 -0
- package/dist/src/mcp/google-auth-provider.js +63 -0
- package/dist/src/mcp/google-auth-provider.js.map +1 -0
- package/dist/src/mcp/google-auth-provider.test.d.ts +6 -0
- package/dist/src/mcp/google-auth-provider.test.js +54 -0
- package/dist/src/mcp/google-auth-provider.test.js.map +1 -0
- package/dist/src/mcp/oauth-provider.d.ts +142 -0
- package/dist/src/mcp/oauth-provider.js +446 -0
- package/dist/src/mcp/oauth-provider.js.map +1 -0
- package/dist/src/mcp/oauth-provider.test.d.ts +6 -0
- package/dist/src/mcp/oauth-provider.test.js +520 -0
- package/dist/src/mcp/oauth-provider.test.js.map +1 -0
- package/dist/src/mcp/oauth-token-storage.d.ts +81 -0
- package/dist/src/mcp/oauth-token-storage.js +149 -0
- package/dist/src/mcp/oauth-token-storage.js.map +1 -0
- package/dist/src/mcp/oauth-token-storage.test.d.ts +6 -0
- package/dist/src/mcp/oauth-token-storage.test.js +205 -0
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -0
- package/dist/src/mcp/oauth-utils.d.ts +109 -0
- package/dist/src/mcp/oauth-utils.js +183 -0
- package/dist/src/mcp/oauth-utils.js.map +1 -0
- package/dist/src/mcp/oauth-utils.test.d.ts +6 -0
- package/dist/src/mcp/oauth-utils.test.js +144 -0
- package/dist/src/mcp/oauth-utils.test.js.map +1 -0
- package/dist/src/services/gitService.js +1 -5
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +1 -6
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +94 -0
- package/dist/src/services/loopDetectionService.js +318 -0
- package/dist/src/services/loopDetectionService.js.map +1 -0
- package/dist/src/services/loopDetectionService.test.d.ts +6 -0
- package/dist/src/services/loopDetectionService.test.js +266 -0
- package/dist/src/services/loopDetectionService.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +5 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +69 -4
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +4 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +9 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +1 -0
- package/dist/src/telemetry/constants.js +1 -0
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/file-exporters.d.ts +28 -0
- package/dist/src/telemetry/file-exporters.js +62 -0
- package/dist/src/telemetry/file-exporters.js.map +1 -0
- package/dist/src/telemetry/integration.test.circular.d.ts +6 -0
- package/dist/src/telemetry/integration.test.circular.js +53 -0
- package/dist/src/telemetry/integration.test.circular.js.map +1 -0
- package/dist/src/telemetry/loggers.d.ts +3 -1
- package/dist/src/telemetry/loggers.js +34 -2
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.d.ts +6 -0
- package/dist/src/telemetry/loggers.test.circular.js +100 -0
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -0
- package/dist/src/telemetry/sdk.js +17 -6
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +19 -1
- package/dist/src/telemetry/types.js +28 -0
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
- package/dist/src/telemetry/uiTelemetry.js +7 -0
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +92 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/tools/edit.d.ts +7 -12
- package/dist/src/tools/edit.js +34 -32
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +12 -0
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.d.ts +1 -14
- package/dist/src/tools/glob.js +13 -36
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +4 -3
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +3 -6
- package/dist/src/tools/grep.js +12 -18
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +5 -2
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.d.ts +6 -14
- package/dist/src/tools/ls.js +47 -40
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +59 -1
- package/dist/src/tools/mcp-client.js +557 -146
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +166 -623
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/mcp-tool.d.ts +11 -5
- package/dist/src/tools/mcp-tool.js +34 -10
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +74 -24
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/memoryTool.js +2 -2
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/read-file.d.ts +3 -3
- package/dist/src/tools/read-file.js +10 -10
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +100 -70
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.d.ts +6 -10
- package/dist/src/tools/read-many-files.js +74 -43
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +7 -3
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/shell.d.ts +2 -23
- package/dist/src/tools/shell.js +58 -138
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +85 -311
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +13 -2
- package/dist/src/tools/tool-registry.js +57 -10
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +112 -41
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +37 -2
- package/dist/src/tools/tools.js +25 -2
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/web-fetch.js +7 -2
- package/dist/src/tools/web-fetch.js.map +1 -1
- package/dist/src/tools/web-fetch.test.js +1 -0
- package/dist/src/tools/web-fetch.test.js.map +1 -1
- package/dist/src/tools/web-search.js +2 -2
- package/dist/src/tools/web-search.js.map +1 -1
- package/dist/src/tools/write-file.d.ts +0 -8
- package/dist/src/tools/write-file.js +14 -23
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.d.ts +2 -0
- package/dist/src/utils/bfsFileSearch.js +4 -1
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +108 -105
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/browser.d.ts +13 -0
- package/dist/src/utils/browser.js +49 -0
- package/dist/src/utils/browser.js.map +1 -0
- package/dist/src/utils/editCorrector.js +4 -4
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +1 -1
- package/dist/src/utils/editor.js +16 -10
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +128 -28
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/errorReporting.d.ts +1 -1
- package/dist/src/utils/errorReporting.js +2 -2
- package/dist/src/utils/errorReporting.js.map +1 -1
- package/dist/src/utils/errorReporting.test.js +44 -38
- package/dist/src/utils/errorReporting.test.js.map +1 -1
- package/dist/src/utils/errors.js +4 -4
- package/dist/src/utils/errors.js.map +1 -1
- package/dist/src/utils/fileUtils.d.ts +4 -4
- package/dist/src/utils/fileUtils.js +33 -17
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +37 -37
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/getFolderStructure.d.ts +3 -2
- package/dist/src/utils/getFolderStructure.js +27 -28
- package/dist/src/utils/getFolderStructure.js.map +1 -1
- package/dist/src/utils/getFolderStructure.test.js +169 -187
- package/dist/src/utils/getFolderStructure.test.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.js +4 -7
- package/dist/src/utils/gitIgnoreParser.js.map +1 -1
- package/dist/src/utils/gitIgnoreParser.test.js +70 -61
- package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +2 -1
- package/dist/src/utils/memoryDiscovery.js +11 -5
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +160 -371
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/partUtils.d.ts +14 -0
- package/dist/src/utils/partUtils.js +65 -0
- package/dist/src/utils/partUtils.js.map +1 -0
- package/dist/src/utils/partUtils.test.d.ts +6 -0
- package/dist/src/utils/partUtils.test.js +130 -0
- package/dist/src/utils/partUtils.test.js.map +1 -0
- package/dist/src/utils/paths.d.ts +11 -0
- package/dist/src/utils/paths.js +17 -1
- package/dist/src/utils/paths.js.map +1 -1
- package/dist/src/utils/quotaErrorDetection.js +2 -11
- package/dist/src/utils/quotaErrorDetection.js.map +1 -1
- package/dist/src/utils/retry.d.ts +6 -0
- package/dist/src/utils/retry.js +2 -2
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/safeJsonStringify.d.ts +13 -0
- package/dist/src/utils/safeJsonStringify.js +25 -0
- package/dist/src/utils/safeJsonStringify.js.map +1 -0
- package/dist/src/utils/safeJsonStringify.test.d.ts +6 -0
- package/dist/src/utils/safeJsonStringify.test.js +61 -0
- package/dist/src/utils/safeJsonStringify.test.js.map +1 -0
- package/dist/src/utils/schemaValidator.d.ts +1 -1
- package/dist/src/utils/schemaValidator.js +6 -3
- package/dist/src/utils/schemaValidator.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +44 -0
- package/dist/src/utils/shell-utils.js +243 -0
- package/dist/src/utils/shell-utils.js.map +1 -0
- package/dist/src/utils/shell-utils.test.d.ts +6 -0
- package/dist/src/utils/shell-utils.test.js +450 -0
- package/dist/src/utils/shell-utils.test.js.map +1 -0
- package/dist/src/utils/summarizer.d.ts +1 -1
- package/dist/src/utils/summarizer.js +11 -39
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/summarizer.test.js +1 -1
- package/dist/src/utils/systemEncoding.d.ts +40 -0
- package/dist/src/utils/systemEncoding.js +149 -0
- package/dist/src/utils/systemEncoding.js.map +1 -0
- package/dist/src/utils/systemEncoding.test.d.ts +6 -0
- package/dist/src/utils/systemEncoding.test.js +368 -0
- package/dist/src/utils/systemEncoding.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/dist/google-gemini-cli-core-0.1.11.tgz +0 -0
- package/dist/src/core/geminiRequest.test.js +0 -72
- package/dist/src/core/geminiRequest.test.js.map +0 -1
- /package/dist/src/{core/geminiRequest.test.d.ts → ide/ideContext.test.d.ts} +0 -0
|
@@ -6,341 +6,115 @@
|
|
|
6
6
|
import { expect, describe, it, vi, beforeEach } from 'vitest';
|
|
7
7
|
import { ShellTool } from './shell.js';
|
|
8
8
|
import * as summarizer from '../utils/summarizer.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import os from 'os';
|
|
10
|
+
describe('ShellTool Bug Reproduction', () => {
|
|
11
|
+
let shellTool;
|
|
12
|
+
let config;
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
config = {
|
|
12
15
|
getCoreTools: () => undefined,
|
|
13
16
|
getExcludeTools: () => undefined,
|
|
17
|
+
getDebugMode: () => false,
|
|
18
|
+
getGeminiClient: () => ({}),
|
|
19
|
+
getTargetDir: () => '.',
|
|
20
|
+
getSummarizeToolOutputConfig: () => ({
|
|
21
|
+
[shellTool.name]: {},
|
|
22
|
+
}),
|
|
14
23
|
};
|
|
15
|
-
|
|
16
|
-
const result = shellTool.isCommandAllowed('ls -l');
|
|
17
|
-
expect(result.allowed).toBe(true);
|
|
18
|
-
});
|
|
19
|
-
it('should allow a command if it is in the allowed list', async () => {
|
|
20
|
-
const config = {
|
|
21
|
-
getCoreTools: () => ['ShellTool(ls -l)'],
|
|
22
|
-
getExcludeTools: () => undefined,
|
|
23
|
-
};
|
|
24
|
-
const shellTool = new ShellTool(config);
|
|
25
|
-
const result = shellTool.isCommandAllowed('ls -l');
|
|
26
|
-
expect(result.allowed).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
it('should block a command if it is not in the allowed list', async () => {
|
|
29
|
-
const config = {
|
|
30
|
-
getCoreTools: () => ['ShellTool(ls -l)'],
|
|
31
|
-
getExcludeTools: () => undefined,
|
|
32
|
-
};
|
|
33
|
-
const shellTool = new ShellTool(config);
|
|
34
|
-
const result = shellTool.isCommandAllowed('rm -rf /');
|
|
35
|
-
expect(result.allowed).toBe(false);
|
|
36
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
24
|
+
shellTool = new ShellTool(config);
|
|
37
25
|
});
|
|
38
|
-
it('should
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
expect(result.
|
|
46
|
-
expect(
|
|
26
|
+
it('should not let the summarizer override the return display', async () => {
|
|
27
|
+
const summarizeSpy = vi
|
|
28
|
+
.spyOn(summarizer, 'summarizeToolOutput')
|
|
29
|
+
.mockResolvedValue('summarized output');
|
|
30
|
+
const abortSignal = new AbortController().signal;
|
|
31
|
+
const result = await shellTool.execute({ command: 'echo hello' }, abortSignal, () => { });
|
|
32
|
+
expect(result.returnDisplay).toBe('hello' + os.EOL);
|
|
33
|
+
expect(result.llmContent).toBe('summarized output');
|
|
34
|
+
expect(summarizeSpy).toHaveBeenCalled();
|
|
47
35
|
});
|
|
48
|
-
it('should
|
|
49
|
-
|
|
36
|
+
it('should not call summarizer if disabled in config', async () => {
|
|
37
|
+
config = {
|
|
50
38
|
getCoreTools: () => undefined,
|
|
51
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
52
|
-
};
|
|
53
|
-
const shellTool = new ShellTool(config);
|
|
54
|
-
const result = shellTool.isCommandAllowed('ls -l');
|
|
55
|
-
expect(result.allowed).toBe(true);
|
|
56
|
-
});
|
|
57
|
-
it('should block a command if it is in both the allowed and blocked lists', async () => {
|
|
58
|
-
const config = {
|
|
59
|
-
getCoreTools: () => ['ShellTool(rm -rf /)'],
|
|
60
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
61
|
-
};
|
|
62
|
-
const shellTool = new ShellTool(config);
|
|
63
|
-
const result = shellTool.isCommandAllowed('rm -rf /');
|
|
64
|
-
expect(result.allowed).toBe(false);
|
|
65
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
66
|
-
});
|
|
67
|
-
it('should allow any command when ShellTool is in coreTools without specific commands', async () => {
|
|
68
|
-
const config = {
|
|
69
|
-
getCoreTools: () => ['ShellTool'],
|
|
70
|
-
getExcludeTools: () => [],
|
|
71
|
-
};
|
|
72
|
-
const shellTool = new ShellTool(config);
|
|
73
|
-
const result = shellTool.isCommandAllowed('any command');
|
|
74
|
-
expect(result.allowed).toBe(true);
|
|
75
|
-
});
|
|
76
|
-
it('should block any command when ShellTool is in excludeTools without specific commands', async () => {
|
|
77
|
-
const config = {
|
|
78
|
-
getCoreTools: () => [],
|
|
79
|
-
getExcludeTools: () => ['ShellTool'],
|
|
80
|
-
};
|
|
81
|
-
const shellTool = new ShellTool(config);
|
|
82
|
-
const result = shellTool.isCommandAllowed('any command');
|
|
83
|
-
expect(result.allowed).toBe(false);
|
|
84
|
-
expect(result.reason).toBe('Shell tool is globally disabled in configuration');
|
|
85
|
-
});
|
|
86
|
-
it('should allow a command if it is in the allowed list using the public-facing name', async () => {
|
|
87
|
-
const config = {
|
|
88
|
-
getCoreTools: () => ['run_shell_command(ls -l)'],
|
|
89
39
|
getExcludeTools: () => undefined,
|
|
40
|
+
getDebugMode: () => false,
|
|
41
|
+
getGeminiClient: () => ({}),
|
|
42
|
+
getTargetDir: () => '.',
|
|
43
|
+
getSummarizeToolOutputConfig: () => ({}),
|
|
90
44
|
};
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const shellTool = new ShellTool(config);
|
|
101
|
-
const result = shellTool.isCommandAllowed('rm -rf /');
|
|
102
|
-
expect(result.allowed).toBe(false);
|
|
103
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
104
|
-
});
|
|
105
|
-
it('should block any command when ShellTool is in excludeTools using the public-facing name', async () => {
|
|
106
|
-
const config = {
|
|
107
|
-
getCoreTools: () => [],
|
|
108
|
-
getExcludeTools: () => ['run_shell_command'],
|
|
109
|
-
};
|
|
110
|
-
const shellTool = new ShellTool(config);
|
|
111
|
-
const result = shellTool.isCommandAllowed('any command');
|
|
112
|
-
expect(result.allowed).toBe(false);
|
|
113
|
-
expect(result.reason).toBe('Shell tool is globally disabled in configuration');
|
|
114
|
-
});
|
|
115
|
-
it('should block any command if coreTools contains an empty ShellTool command list using the public-facing name', async () => {
|
|
116
|
-
const config = {
|
|
117
|
-
getCoreTools: () => ['run_shell_command()'],
|
|
118
|
-
getExcludeTools: () => [],
|
|
119
|
-
};
|
|
120
|
-
const shellTool = new ShellTool(config);
|
|
121
|
-
const result = shellTool.isCommandAllowed('any command');
|
|
122
|
-
expect(result.allowed).toBe(false);
|
|
123
|
-
expect(result.reason).toBe("Command 'any command' is not in the allowed commands list");
|
|
124
|
-
});
|
|
125
|
-
it('should block any command if coreTools contains an empty ShellTool command list', async () => {
|
|
126
|
-
const config = {
|
|
127
|
-
getCoreTools: () => ['ShellTool()'],
|
|
128
|
-
getExcludeTools: () => [],
|
|
129
|
-
};
|
|
130
|
-
const shellTool = new ShellTool(config);
|
|
131
|
-
const result = shellTool.isCommandAllowed('any command');
|
|
132
|
-
expect(result.allowed).toBe(false);
|
|
133
|
-
expect(result.reason).toBe("Command 'any command' is not in the allowed commands list");
|
|
45
|
+
shellTool = new ShellTool(config);
|
|
46
|
+
const summarizeSpy = vi
|
|
47
|
+
.spyOn(summarizer, 'summarizeToolOutput')
|
|
48
|
+
.mockResolvedValue('summarized output');
|
|
49
|
+
const abortSignal = new AbortController().signal;
|
|
50
|
+
const result = await shellTool.execute({ command: 'echo hello' }, abortSignal, () => { });
|
|
51
|
+
expect(result.returnDisplay).toBe('hello' + os.EOL);
|
|
52
|
+
expect(result.llmContent).not.toBe('summarized output');
|
|
53
|
+
expect(summarizeSpy).not.toHaveBeenCalled();
|
|
134
54
|
});
|
|
135
|
-
it('should
|
|
136
|
-
|
|
55
|
+
it('should pass token budget to summarizer', async () => {
|
|
56
|
+
config = {
|
|
137
57
|
getCoreTools: () => undefined,
|
|
138
|
-
getExcludeTools: () =>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
it('should allow any command when ShellTool is present with specific commands', async () => {
|
|
146
|
-
const config = {
|
|
147
|
-
getCoreTools: () => ['ShellTool', 'ShellTool(ls)'],
|
|
148
|
-
getExcludeTools: () => [],
|
|
149
|
-
};
|
|
150
|
-
const shellTool = new ShellTool(config);
|
|
151
|
-
const result = shellTool.isCommandAllowed('any command');
|
|
152
|
-
expect(result.allowed).toBe(true);
|
|
153
|
-
});
|
|
154
|
-
it('should block a command on the blocklist even with a wildcard allow', async () => {
|
|
155
|
-
const config = {
|
|
156
|
-
getCoreTools: () => ['ShellTool'],
|
|
157
|
-
getExcludeTools: () => ['ShellTool(rm -rf /)'],
|
|
158
|
-
};
|
|
159
|
-
const shellTool = new ShellTool(config);
|
|
160
|
-
const result = shellTool.isCommandAllowed('rm -rf /');
|
|
161
|
-
expect(result.allowed).toBe(false);
|
|
162
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
163
|
-
});
|
|
164
|
-
it('should allow a command that starts with an allowed command prefix', async () => {
|
|
165
|
-
const config = {
|
|
166
|
-
getCoreTools: () => ['ShellTool(gh issue edit)'],
|
|
167
|
-
getExcludeTools: () => [],
|
|
168
|
-
};
|
|
169
|
-
const shellTool = new ShellTool(config);
|
|
170
|
-
const result = shellTool.isCommandAllowed('gh issue edit 1 --add-label "kind/feature"');
|
|
171
|
-
expect(result.allowed).toBe(true);
|
|
172
|
-
});
|
|
173
|
-
it('should allow a command that starts with an allowed command prefix using the public-facing name', async () => {
|
|
174
|
-
const config = {
|
|
175
|
-
getCoreTools: () => ['run_shell_command(gh issue edit)'],
|
|
176
|
-
getExcludeTools: () => [],
|
|
177
|
-
};
|
|
178
|
-
const shellTool = new ShellTool(config);
|
|
179
|
-
const result = shellTool.isCommandAllowed('gh issue edit 1 --add-label "kind/feature"');
|
|
180
|
-
expect(result.allowed).toBe(true);
|
|
181
|
-
});
|
|
182
|
-
it('should not allow a command that starts with an allowed command prefix but is chained with another command', async () => {
|
|
183
|
-
const config = {
|
|
184
|
-
getCoreTools: () => ['run_shell_command(gh issue edit)'],
|
|
185
|
-
getExcludeTools: () => [],
|
|
186
|
-
};
|
|
187
|
-
const shellTool = new ShellTool(config);
|
|
188
|
-
const result = shellTool.isCommandAllowed('gh issue edit&&rm -rf /');
|
|
189
|
-
expect(result.allowed).toBe(false);
|
|
190
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
191
|
-
});
|
|
192
|
-
it('should not allow a command that is a prefix of an allowed command', async () => {
|
|
193
|
-
const config = {
|
|
194
|
-
getCoreTools: () => ['run_shell_command(gh issue edit)'],
|
|
195
|
-
getExcludeTools: () => [],
|
|
196
|
-
};
|
|
197
|
-
const shellTool = new ShellTool(config);
|
|
198
|
-
const result = shellTool.isCommandAllowed('gh issue');
|
|
199
|
-
expect(result.allowed).toBe(false);
|
|
200
|
-
expect(result.reason).toBe("Command 'gh issue' is not in the allowed commands list");
|
|
201
|
-
});
|
|
202
|
-
it('should not allow a command that is a prefix of a blocked command', async () => {
|
|
203
|
-
const config = {
|
|
204
|
-
getCoreTools: () => [],
|
|
205
|
-
getExcludeTools: () => ['run_shell_command(gh issue edit)'],
|
|
206
|
-
};
|
|
207
|
-
const shellTool = new ShellTool(config);
|
|
208
|
-
const result = shellTool.isCommandAllowed('gh issue');
|
|
209
|
-
expect(result.allowed).toBe(true);
|
|
210
|
-
});
|
|
211
|
-
it('should not allow a command that is chained with a pipe', async () => {
|
|
212
|
-
const config = {
|
|
213
|
-
getCoreTools: () => ['run_shell_command(gh issue list)'],
|
|
214
|
-
getExcludeTools: () => [],
|
|
215
|
-
};
|
|
216
|
-
const shellTool = new ShellTool(config);
|
|
217
|
-
const result = shellTool.isCommandAllowed('gh issue list | rm -rf /');
|
|
218
|
-
expect(result.allowed).toBe(false);
|
|
219
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
220
|
-
});
|
|
221
|
-
it('should not allow a command that is chained with a semicolon', async () => {
|
|
222
|
-
const config = {
|
|
223
|
-
getCoreTools: () => ['run_shell_command(gh issue list)'],
|
|
224
|
-
getExcludeTools: () => [],
|
|
225
|
-
};
|
|
226
|
-
const shellTool = new ShellTool(config);
|
|
227
|
-
const result = shellTool.isCommandAllowed('gh issue list; rm -rf /');
|
|
228
|
-
expect(result.allowed).toBe(false);
|
|
229
|
-
expect(result.reason).toBe("Command 'rm -rf /' is not in the allowed commands list");
|
|
230
|
-
});
|
|
231
|
-
it('should block a chained command if any part is blocked', async () => {
|
|
232
|
-
const config = {
|
|
233
|
-
getCoreTools: () => ['run_shell_command(echo "hello")'],
|
|
234
|
-
getExcludeTools: () => ['run_shell_command(rm)'],
|
|
235
|
-
};
|
|
236
|
-
const shellTool = new ShellTool(config);
|
|
237
|
-
const result = shellTool.isCommandAllowed('echo "hello" && rm -rf /');
|
|
238
|
-
expect(result.allowed).toBe(false);
|
|
239
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
240
|
-
});
|
|
241
|
-
it('should block a command if its prefix is on the blocklist, even if the command itself is on the allowlist', async () => {
|
|
242
|
-
const config = {
|
|
243
|
-
getCoreTools: () => ['run_shell_command(git push)'],
|
|
244
|
-
getExcludeTools: () => ['run_shell_command(git)'],
|
|
245
|
-
};
|
|
246
|
-
const shellTool = new ShellTool(config);
|
|
247
|
-
const result = shellTool.isCommandAllowed('git push');
|
|
248
|
-
expect(result.allowed).toBe(false);
|
|
249
|
-
expect(result.reason).toBe("Command 'git push' is blocked by configuration");
|
|
250
|
-
});
|
|
251
|
-
it('should be case-sensitive in its matching', async () => {
|
|
252
|
-
const config = {
|
|
253
|
-
getCoreTools: () => ['run_shell_command(echo)'],
|
|
254
|
-
getExcludeTools: () => [],
|
|
255
|
-
};
|
|
256
|
-
const shellTool = new ShellTool(config);
|
|
257
|
-
const result = shellTool.isCommandAllowed('ECHO "hello"');
|
|
258
|
-
expect(result.allowed).toBe(false);
|
|
259
|
-
expect(result.reason).toBe('Command \'ECHO "hello"\' is not in the allowed commands list');
|
|
260
|
-
});
|
|
261
|
-
it('should correctly handle commands with extra whitespace around chaining operators', async () => {
|
|
262
|
-
const config = {
|
|
263
|
-
getCoreTools: () => ['run_shell_command(ls -l)'],
|
|
264
|
-
getExcludeTools: () => ['run_shell_command(rm)'],
|
|
265
|
-
};
|
|
266
|
-
const shellTool = new ShellTool(config);
|
|
267
|
-
const result = shellTool.isCommandAllowed('ls -l ; rm -rf /');
|
|
268
|
-
expect(result.allowed).toBe(false);
|
|
269
|
-
expect(result.reason).toBe("Command 'rm -rf /' is blocked by configuration");
|
|
270
|
-
});
|
|
271
|
-
it('should allow a chained command if all parts are allowed', async () => {
|
|
272
|
-
const config = {
|
|
273
|
-
getCoreTools: () => [
|
|
274
|
-
'run_shell_command(echo)',
|
|
275
|
-
'run_shell_command(ls -l)',
|
|
276
|
-
],
|
|
277
|
-
getExcludeTools: () => [],
|
|
278
|
-
};
|
|
279
|
-
const shellTool = new ShellTool(config);
|
|
280
|
-
const result = shellTool.isCommandAllowed('echo "hello" && ls -l');
|
|
281
|
-
expect(result.allowed).toBe(true);
|
|
282
|
-
});
|
|
283
|
-
it('should allow a command with command substitution using backticks', async () => {
|
|
284
|
-
const config = {
|
|
285
|
-
getCoreTools: () => ['run_shell_command(echo)'],
|
|
286
|
-
getExcludeTools: () => [],
|
|
287
|
-
};
|
|
288
|
-
const shellTool = new ShellTool(config);
|
|
289
|
-
const result = shellTool.isCommandAllowed('echo `rm -rf /`');
|
|
290
|
-
expect(result.allowed).toBe(true);
|
|
291
|
-
});
|
|
292
|
-
it('should block a command with command substitution using $()', async () => {
|
|
293
|
-
const config = {
|
|
294
|
-
getCoreTools: () => ['run_shell_command(echo)'],
|
|
295
|
-
getExcludeTools: () => [],
|
|
296
|
-
};
|
|
297
|
-
const shellTool = new ShellTool(config);
|
|
298
|
-
const result = shellTool.isCommandAllowed('echo $(rm -rf /)');
|
|
299
|
-
expect(result.allowed).toBe(false);
|
|
300
|
-
expect(result.reason).toBe('Command substitution using $() is not allowed for security reasons');
|
|
301
|
-
});
|
|
302
|
-
it('should allow a command with I/O redirection', async () => {
|
|
303
|
-
const config = {
|
|
304
|
-
getCoreTools: () => ['run_shell_command(echo)'],
|
|
305
|
-
getExcludeTools: () => [],
|
|
306
|
-
};
|
|
307
|
-
const shellTool = new ShellTool(config);
|
|
308
|
-
const result = shellTool.isCommandAllowed('echo "hello" > file.txt');
|
|
309
|
-
expect(result.allowed).toBe(true);
|
|
310
|
-
});
|
|
311
|
-
it('should not allow a command that is chained with a double pipe', async () => {
|
|
312
|
-
const config = {
|
|
313
|
-
getCoreTools: () => ['run_shell_command(gh issue list)'],
|
|
314
|
-
getExcludeTools: () => [],
|
|
58
|
+
getExcludeTools: () => undefined,
|
|
59
|
+
getDebugMode: () => false,
|
|
60
|
+
getGeminiClient: () => ({}),
|
|
61
|
+
getTargetDir: () => '.',
|
|
62
|
+
getSummarizeToolOutputConfig: () => ({
|
|
63
|
+
[shellTool.name]: { tokenBudget: 1000 },
|
|
64
|
+
}),
|
|
315
65
|
};
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
66
|
+
shellTool = new ShellTool(config);
|
|
67
|
+
const summarizeSpy = vi
|
|
68
|
+
.spyOn(summarizer, 'summarizeToolOutput')
|
|
69
|
+
.mockResolvedValue('summarized output');
|
|
70
|
+
const abortSignal = new AbortController().signal;
|
|
71
|
+
await shellTool.execute({ command: 'echo "hello"' }, abortSignal, () => { });
|
|
72
|
+
expect(summarizeSpy).toHaveBeenCalledWith(expect.any(String), expect.any(Object), expect.any(Object), 1000);
|
|
320
73
|
});
|
|
321
|
-
|
|
322
|
-
describe('ShellTool Bug Reproduction', () => {
|
|
323
|
-
let shellTool;
|
|
324
|
-
let config;
|
|
325
|
-
beforeEach(() => {
|
|
74
|
+
it('should use default token budget if not specified', async () => {
|
|
326
75
|
config = {
|
|
327
76
|
getCoreTools: () => undefined,
|
|
328
77
|
getExcludeTools: () => undefined,
|
|
329
78
|
getDebugMode: () => false,
|
|
330
79
|
getGeminiClient: () => ({}),
|
|
331
80
|
getTargetDir: () => '.',
|
|
81
|
+
getSummarizeToolOutputConfig: () => ({
|
|
82
|
+
[shellTool.name]: {},
|
|
83
|
+
}),
|
|
332
84
|
};
|
|
333
85
|
shellTool = new ShellTool(config);
|
|
334
|
-
});
|
|
335
|
-
it('should not let the summarizer override the return display', async () => {
|
|
336
86
|
const summarizeSpy = vi
|
|
337
87
|
.spyOn(summarizer, 'summarizeToolOutput')
|
|
338
88
|
.mockResolvedValue('summarized output');
|
|
339
89
|
const abortSignal = new AbortController().signal;
|
|
340
|
-
|
|
341
|
-
expect(
|
|
342
|
-
|
|
343
|
-
|
|
90
|
+
await shellTool.execute({ command: 'echo "hello"' }, abortSignal, () => { });
|
|
91
|
+
expect(summarizeSpy).toHaveBeenCalledWith(expect.any(String), expect.any(Object), expect.any(Object), undefined);
|
|
92
|
+
});
|
|
93
|
+
it('should pass GEMINI_CLI environment variable to executed commands', async () => {
|
|
94
|
+
config = {
|
|
95
|
+
getCoreTools: () => undefined,
|
|
96
|
+
getExcludeTools: () => undefined,
|
|
97
|
+
getDebugMode: () => false,
|
|
98
|
+
getGeminiClient: () => ({}),
|
|
99
|
+
getTargetDir: () => '.',
|
|
100
|
+
getSummarizeToolOutputConfig: () => ({}),
|
|
101
|
+
};
|
|
102
|
+
shellTool = new ShellTool(config);
|
|
103
|
+
const abortSignal = new AbortController().signal;
|
|
104
|
+
const result = await shellTool.execute({ command: 'echo "$GEMINI_CLI"' }, abortSignal, () => { });
|
|
105
|
+
expect(result.returnDisplay).toBe('1' + os.EOL);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
describe('shouldConfirmExecute', () => {
|
|
109
|
+
it('should de-duplicate command roots before asking for confirmation', async () => {
|
|
110
|
+
const shellTool = new ShellTool({
|
|
111
|
+
getCoreTools: () => ['run_shell_command'],
|
|
112
|
+
getExcludeTools: () => [],
|
|
113
|
+
});
|
|
114
|
+
const result = (await shellTool.shouldConfirmExecute({
|
|
115
|
+
command: 'git status && git log',
|
|
116
|
+
}, new AbortController().signal));
|
|
117
|
+
expect(result.rootCommand).toEqual('git');
|
|
344
118
|
});
|
|
345
119
|
});
|
|
346
120
|
//# sourceMappingURL=shell.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.test.js","sourceRoot":"","sources":["../../../src/tools/shell.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shell.test.js","sourceRoot":"","sources":["../../../src/tools/shell.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,6 @@ import { Config } from '../config/config.js';
|
|
|
9
9
|
type ToolParams = Record<string, unknown>;
|
|
10
10
|
export declare class DiscoveredTool extends BaseTool<ToolParams, ToolResult> {
|
|
11
11
|
private readonly config;
|
|
12
|
-
readonly name: string;
|
|
13
12
|
readonly description: string;
|
|
14
13
|
readonly parameterSchema: Record<string, unknown>;
|
|
15
14
|
constructor(config: Config, name: string, description: string, parameterSchema: Record<string, unknown>);
|
|
@@ -27,8 +26,20 @@ export declare class ToolRegistry {
|
|
|
27
26
|
/**
|
|
28
27
|
* Discovers tools from project (if available and configured).
|
|
29
28
|
* Can be called multiple times to update discovered tools.
|
|
29
|
+
* This will discover tools from the command line and from MCP servers.
|
|
30
30
|
*/
|
|
31
|
-
|
|
31
|
+
discoverAllTools(): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Discovers tools from project (if available and configured).
|
|
34
|
+
* Can be called multiple times to update discovered tools.
|
|
35
|
+
* This will NOT discover tools from the command line, only from MCP servers.
|
|
36
|
+
*/
|
|
37
|
+
discoverMcpTools(): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* Discover or re-discover tools for a single MCP server.
|
|
40
|
+
* @param serverName - The name of the server to discover tools from.
|
|
41
|
+
*/
|
|
42
|
+
discoverToolsForServer(serverName: string): Promise<void>;
|
|
32
43
|
private discoverAndRegisterToolsFromCommand;
|
|
33
44
|
/**
|
|
34
45
|
* Retrieves the list of tool schemas (FunctionDeclaration array).
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { Type } from '@google/genai';
|
|
7
|
-
import { BaseTool } from './tools.js';
|
|
7
|
+
import { BaseTool, Icon } from './tools.js';
|
|
8
8
|
import { spawn } from 'node:child_process';
|
|
9
9
|
import { StringDecoder } from 'node:string_decoder';
|
|
10
10
|
import { discoverMcpTools } from './mcp-client.js';
|
|
@@ -12,7 +12,6 @@ import { DiscoveredMCPTool } from './mcp-tool.js';
|
|
|
12
12
|
import { parse } from 'shell-quote';
|
|
13
13
|
export class DiscoveredTool extends BaseTool {
|
|
14
14
|
config;
|
|
15
|
-
name;
|
|
16
15
|
description;
|
|
17
16
|
parameterSchema;
|
|
18
17
|
constructor(config, name, description, parameterSchema) {
|
|
@@ -34,10 +33,9 @@ Error: Error or \`(none)\` if no error was reported for the subprocess.
|
|
|
34
33
|
Exit Code: Exit code or \`(none)\` if terminated by signal.
|
|
35
34
|
Signal: Signal number or \`(none)\` if no signal was received.
|
|
36
35
|
`;
|
|
37
|
-
super(name, name, description, parameterSchema, false, // isOutputMarkdown
|
|
36
|
+
super(name, name, description, Icon.Hammer, parameterSchema, false, // isOutputMarkdown
|
|
38
37
|
false);
|
|
39
38
|
this.config = config;
|
|
40
|
-
this.name = name;
|
|
41
39
|
this.description = description;
|
|
42
40
|
this.parameterSchema = parameterSchema;
|
|
43
41
|
}
|
|
@@ -113,16 +111,22 @@ export class ToolRegistry {
|
|
|
113
111
|
*/
|
|
114
112
|
registerTool(tool) {
|
|
115
113
|
if (this.tools.has(tool.name)) {
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
if (tool instanceof DiscoveredMCPTool) {
|
|
115
|
+
tool = tool.asFullyQualifiedTool();
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// Decide on behavior: throw error, log warning, or allow overwrite
|
|
119
|
+
console.warn(`Tool with name "${tool.name}" is already registered. Overwriting.`);
|
|
120
|
+
}
|
|
118
121
|
}
|
|
119
122
|
this.tools.set(tool.name, tool);
|
|
120
123
|
}
|
|
121
124
|
/**
|
|
122
125
|
* Discovers tools from project (if available and configured).
|
|
123
126
|
* Can be called multiple times to update discovered tools.
|
|
127
|
+
* This will discover tools from the command line and from MCP servers.
|
|
124
128
|
*/
|
|
125
|
-
async
|
|
129
|
+
async discoverAllTools() {
|
|
126
130
|
// remove any previously discovered tools
|
|
127
131
|
for (const tool of this.tools.values()) {
|
|
128
132
|
if (tool instanceof DiscoveredTool || tool instanceof DiscoveredMCPTool) {
|
|
@@ -131,7 +135,39 @@ export class ToolRegistry {
|
|
|
131
135
|
}
|
|
132
136
|
await this.discoverAndRegisterToolsFromCommand();
|
|
133
137
|
// discover tools using MCP servers, if configured
|
|
134
|
-
await discoverMcpTools(this.config.getMcpServers() ?? {}, this.config.getMcpServerCommand(), this);
|
|
138
|
+
await discoverMcpTools(this.config.getMcpServers() ?? {}, this.config.getMcpServerCommand(), this, this.config.getDebugMode());
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Discovers tools from project (if available and configured).
|
|
142
|
+
* Can be called multiple times to update discovered tools.
|
|
143
|
+
* This will NOT discover tools from the command line, only from MCP servers.
|
|
144
|
+
*/
|
|
145
|
+
async discoverMcpTools() {
|
|
146
|
+
// remove any previously discovered tools
|
|
147
|
+
for (const tool of this.tools.values()) {
|
|
148
|
+
if (tool instanceof DiscoveredMCPTool) {
|
|
149
|
+
this.tools.delete(tool.name);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// discover tools using MCP servers, if configured
|
|
153
|
+
await discoverMcpTools(this.config.getMcpServers() ?? {}, this.config.getMcpServerCommand(), this, this.config.getDebugMode());
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Discover or re-discover tools for a single MCP server.
|
|
157
|
+
* @param serverName - The name of the server to discover tools from.
|
|
158
|
+
*/
|
|
159
|
+
async discoverToolsForServer(serverName) {
|
|
160
|
+
// Remove any previously discovered tools from this server
|
|
161
|
+
for (const [name, tool] of this.tools.entries()) {
|
|
162
|
+
if (tool instanceof DiscoveredMCPTool && tool.serverName === serverName) {
|
|
163
|
+
this.tools.delete(name);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const mcpServers = this.config.getMcpServers() ?? {};
|
|
167
|
+
const serverConfig = mcpServers[serverName];
|
|
168
|
+
if (serverConfig) {
|
|
169
|
+
await discoverMcpTools({ [serverName]: serverConfig }, undefined, this, this.config.getDebugMode());
|
|
170
|
+
}
|
|
135
171
|
}
|
|
136
172
|
async discoverAndRegisterToolsFromCommand() {
|
|
137
173
|
const discoveryCmd = this.config.getToolDiscoveryCommand();
|
|
@@ -248,7 +284,7 @@ export class ToolRegistry {
|
|
|
248
284
|
* Returns an array of all registered and discovered tool instances.
|
|
249
285
|
*/
|
|
250
286
|
getAllTools() {
|
|
251
|
-
return Array.from(this.tools.values());
|
|
287
|
+
return Array.from(this.tools.values()).sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
252
288
|
}
|
|
253
289
|
/**
|
|
254
290
|
* Returns an array of tools registered from a specific MCP server.
|
|
@@ -260,7 +296,7 @@ export class ToolRegistry {
|
|
|
260
296
|
serverTools.push(tool);
|
|
261
297
|
}
|
|
262
298
|
}
|
|
263
|
-
return serverTools;
|
|
299
|
+
return serverTools.sort((a, b) => a.name.localeCompare(b.name));
|
|
264
300
|
}
|
|
265
301
|
/**
|
|
266
302
|
* Get the definition of a specific tool.
|
|
@@ -314,6 +350,17 @@ function _sanitizeParameters(schema, visited) {
|
|
|
314
350
|
}
|
|
315
351
|
}
|
|
316
352
|
}
|
|
353
|
+
// Handle enum values - Gemini API only allows enum for STRING type
|
|
354
|
+
if (schema.enum && Array.isArray(schema.enum)) {
|
|
355
|
+
if (schema.type !== Type.STRING) {
|
|
356
|
+
// If enum is present but type is not STRING, convert type to STRING
|
|
357
|
+
schema.type = Type.STRING;
|
|
358
|
+
}
|
|
359
|
+
// Filter out null and undefined values, then convert remaining values to strings for Gemini API compatibility
|
|
360
|
+
schema.enum = schema.enum
|
|
361
|
+
.filter((value) => value !== null && value !== undefined)
|
|
362
|
+
.map((value) => String(value));
|
|
363
|
+
}
|
|
317
364
|
// Vertex AI only supports 'enum' and 'date-time' for STRING format.
|
|
318
365
|
if (schema.type === Type.STRING) {
|
|
319
366
|
if (schema.format &&
|