@google/gemini-cli-core 0.7.0-nightly.20250912.68035591 → 0.7.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.
- package/dist/index.d.ts +5 -4
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/src/code_assist/converter.d.ts +1 -0
- package/dist/src/code_assist/converter.js +1 -0
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +10 -0
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.d.ts +5 -7
- package/dist/src/code_assist/oauth-credential-storage.js +5 -8
- package/dist/src/code_assist/oauth-credential-storage.js.map +1 -1
- package/dist/src/code_assist/oauth-credential-storage.test.js +35 -33
- package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -1
- package/dist/src/code_assist/oauth2.js +28 -2
- package/dist/src/code_assist/oauth2.js.map +1 -1
- package/dist/src/code_assist/oauth2.test.js +674 -536
- package/dist/src/code_assist/oauth2.test.js.map +1 -1
- package/dist/src/config/config.d.ts +19 -0
- package/dist/src/config/config.js +48 -6
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +93 -1
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -0
- package/dist/src/config/models.js +1 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/core/baseLlmClient.d.ts +1 -0
- package/dist/src/core/baseLlmClient.js +24 -0
- package/dist/src/core/baseLlmClient.js.map +1 -1
- package/dist/src/core/baseLlmClient.test.js +63 -0
- package/dist/src/core/baseLlmClient.test.js.map +1 -1
- package/dist/src/core/client.d.ts +3 -4
- package/dist/src/core/client.js +62 -145
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +119 -202
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +9 -0
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +16 -11
- package/dist/src/core/geminiChat.js +124 -150
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +342 -204
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/loggingContentGenerator.js +5 -5
- package/dist/src/core/loggingContentGenerator.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.test.js +1 -0
- package/dist/src/core/nonInteractiveToolExecutor.test.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/ide/constants.d.ts +1 -0
- package/dist/src/ide/constants.js +1 -0
- package/dist/src/ide/constants.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +44 -14
- package/dist/src/ide/detect-ide.js +29 -69
- package/dist/src/ide/detect-ide.js.map +1 -1
- package/dist/src/ide/detect-ide.test.js +29 -46
- package/dist/src/ide/detect-ide.test.js.map +1 -1
- package/dist/src/ide/ide-client.d.ts +28 -17
- package/dist/src/ide/ide-client.js +125 -57
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-client.test.js +44 -10
- package/dist/src/ide/ide-client.test.js.map +1 -1
- package/dist/src/ide/ide-installer.d.ts +2 -2
- package/dist/src/ide/ide-installer.js +15 -11
- package/dist/src/ide/ide-installer.js.map +1 -1
- package/dist/src/ide/ide-installer.test.js +30 -12
- package/dist/src/ide/ide-installer.test.js.map +1 -1
- package/dist/src/ide/ideContext.d.ts +0 -93
- package/dist/src/ide/ideContext.js +0 -45
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/types.d.ts +141 -0
- package/dist/src/ide/types.js +73 -0
- package/dist/src/ide/types.js.map +1 -1
- package/dist/src/index.d.ts +4 -2
- package/dist/src/index.js +4 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +4 -1
- package/dist/src/mcp/oauth-provider.js +32 -26
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.d.ts +2 -0
- package/dist/src/mcp/oauth-token-storage.js +25 -0
- package/dist/src/mcp/oauth-token-storage.js.map +1 -1
- package/dist/src/mcp/oauth-token-storage.test.js +251 -160
- package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
- package/dist/src/mcp/token-storage/index.d.ts +11 -0
- package/dist/src/mcp/token-storage/index.js +12 -0
- package/dist/src/mcp/token-storage/index.js.map +1 -0
- package/dist/src/policy/policy-engine.js +11 -2
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +45 -0
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/routing/modelRouterService.js +37 -3
- package/dist/src/routing/modelRouterService.js.map +1 -1
- package/dist/src/routing/modelRouterService.test.js +37 -11
- package/dist/src/routing/modelRouterService.test.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.d.ts +12 -0
- package/dist/src/routing/strategies/classifierStrategy.js +173 -0
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -0
- package/dist/src/routing/strategies/classifierStrategy.test.d.ts +6 -0
- package/dist/src/routing/strategies/classifierStrategy.test.js +192 -0
- package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -0
- package/dist/src/routing/strategies/compositeStrategy.js +4 -3
- package/dist/src/routing/strategies/compositeStrategy.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +13 -12
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.test.js +3 -2
- package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -1
- package/dist/src/services/chatRecordingService.d.ts +2 -1
- package/dist/src/services/chatRecordingService.js +3 -3
- package/dist/src/services/chatRecordingService.js.map +1 -1
- package/dist/src/services/chatRecordingService.test.js +8 -3
- package/dist/src/services/chatRecordingService.test.js.map +1 -1
- package/dist/src/services/gitService.js +9 -12
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +10 -20
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.js +23 -18
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +27 -13
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +30 -15
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +43 -11
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/activity-detector.d.ts +41 -0
- package/dist/src/telemetry/activity-detector.js +61 -0
- package/dist/src/telemetry/activity-detector.js.map +1 -0
- package/dist/src/telemetry/activity-detector.test.d.ts +6 -0
- package/dist/src/telemetry/activity-detector.test.js +136 -0
- package/dist/src/telemetry/activity-detector.test.js.map +1 -0
- package/dist/src/telemetry/activity-types.d.ts +19 -0
- package/dist/src/telemetry/activity-types.js +21 -0
- package/dist/src/telemetry/activity-types.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +14 -2
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +109 -3
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +63 -5
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +12 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +27 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/config.d.ts +31 -0
- package/dist/src/telemetry/config.js +76 -0
- package/dist/src/telemetry/config.js.map +1 -0
- package/dist/src/telemetry/config.test.d.ts +6 -0
- package/dist/src/telemetry/config.test.js +124 -0
- package/dist/src/telemetry/config.test.js.map +1 -0
- package/dist/src/telemetry/constants.d.ts +9 -0
- package/dist/src/telemetry/constants.js +9 -0
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/gcp-exporters.d.ts +34 -0
- package/dist/src/telemetry/gcp-exporters.js +117 -0
- package/dist/src/telemetry/gcp-exporters.js.map +1 -0
- package/dist/src/telemetry/gcp-exporters.test.d.ts +6 -0
- package/dist/src/telemetry/gcp-exporters.test.js +318 -0
- package/dist/src/telemetry/gcp-exporters.test.js.map +1 -0
- package/dist/src/telemetry/index.d.ts +5 -1
- package/dist/src/telemetry/index.js +5 -1
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +8 -1
- package/dist/src/telemetry/loggers.js +111 -2
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +207 -4
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/metrics.d.ts +3 -0
- package/dist/src/telemetry/metrics.js +43 -1
- package/dist/src/telemetry/metrics.js.map +1 -1
- package/dist/src/telemetry/metrics.test.js +42 -0
- package/dist/src/telemetry/metrics.test.js.map +1 -1
- package/dist/src/telemetry/sdk.js +20 -2
- package/dist/src/telemetry/sdk.js.map +1 -1
- package/dist/src/telemetry/sdk.test.js +108 -0
- package/dist/src/telemetry/sdk.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +50 -3
- package/dist/src/telemetry/types.js +91 -6
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.d.ts +1 -1
- package/dist/src/telemetry/uiTelemetry.js +2 -3
- package/dist/src/telemetry/uiTelemetry.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +11 -11
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/tools/edit.js +4 -2
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +77 -1
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/message-bus-integration.test.d.ts +6 -0
- package/dist/src/tools/message-bus-integration.test.js +183 -0
- package/dist/src/tools/message-bus-integration.test.js.map +1 -0
- package/dist/src/tools/shell.js +8 -11
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +33 -37
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/smart-edit.d.ts +0 -1
- package/dist/src/tools/smart-edit.js +3 -15
- package/dist/src/tools/smart-edit.js.map +1 -1
- package/dist/src/tools/smart-edit.test.js +16 -1
- package/dist/src/tools/smart-edit.test.js.map +1 -1
- package/dist/src/tools/tool-registry.js +1 -0
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tools.d.ts +13 -4
- package/dist/src/tools/tools.js +101 -3
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/write-file.js +2 -2
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +16 -10
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/tools/write-todos.d.ts +25 -0
- package/dist/src/tools/write-todos.js +150 -0
- package/dist/src/tools/write-todos.js.map +1 -0
- package/dist/src/tools/write-todos.test.d.ts +6 -0
- package/dist/src/tools/write-todos.test.js +89 -0
- package/dist/src/tools/write-todos.test.js.map +1 -0
- package/dist/src/utils/editCorrector.d.ts +7 -6
- package/dist/src/utils/editCorrector.js +61 -18
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editCorrector.test.js +30 -79
- package/dist/src/utils/editCorrector.test.js.map +1 -1
- package/dist/src/utils/editor.js +31 -44
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +61 -75
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/errorParsing.js +2 -2
- package/dist/src/utils/errorParsing.js.map +1 -1
- package/dist/src/utils/errorParsing.test.js +7 -7
- package/dist/src/utils/errorParsing.test.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +17 -8
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +12 -6
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.d.ts +2 -2
- package/dist/src/utils/nextSpeakerChecker.js +8 -2
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +40 -33
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/shell-utils.d.ts +5 -0
- package/dist/src/utils/shell-utils.js +23 -0
- package/dist/src/utils/shell-utils.js.map +1 -1
- package/dist/src/utils/textUtils.d.ts +5 -0
- package/dist/src/utils/textUtils.js +14 -0
- package/dist/src/utils/textUtils.js.map +1 -1
- package/dist/src/utils/textUtils.test.d.ts +6 -0
- package/dist/src/utils/textUtils.test.js +59 -0
- package/dist/src/utils/textUtils.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -1
- package/dist/google-gemini-cli-core-0.6.0-nightly.tgz +0 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect, vi, afterEach } from 'vitest';
|
|
7
|
-
import { detectIde,
|
|
7
|
+
import { detectIde, IDE_DEFINITIONS } from './detect-ide.js';
|
|
8
8
|
describe('detectIde', () => {
|
|
9
9
|
const ideProcessInfo = { pid: 123, command: 'some/path/to/code' };
|
|
10
10
|
const ideProcessInfoNoCode = { pid: 123, command: 'some/path/to/fork' };
|
|
@@ -18,92 +18,75 @@ describe('detectIde', () => {
|
|
|
18
18
|
it('should detect Devin', () => {
|
|
19
19
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
20
20
|
vi.stubEnv('__COG_BASHRC_SOURCED', '1');
|
|
21
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
21
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.devin);
|
|
22
22
|
});
|
|
23
23
|
it('should detect Replit', () => {
|
|
24
24
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
25
25
|
vi.stubEnv('REPLIT_USER', 'testuser');
|
|
26
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
26
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.replit);
|
|
27
27
|
});
|
|
28
28
|
it('should detect Cursor', () => {
|
|
29
29
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
30
30
|
vi.stubEnv('CURSOR_TRACE_ID', 'some-id');
|
|
31
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
31
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.cursor);
|
|
32
32
|
});
|
|
33
33
|
it('should detect Codespaces', () => {
|
|
34
34
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
35
35
|
vi.stubEnv('CODESPACES', 'true');
|
|
36
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
36
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.codespaces);
|
|
37
37
|
});
|
|
38
38
|
it('should detect Cloud Shell via EDITOR_IN_CLOUD_SHELL', () => {
|
|
39
39
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
40
40
|
vi.stubEnv('EDITOR_IN_CLOUD_SHELL', 'true');
|
|
41
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
41
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.cloudshell);
|
|
42
42
|
});
|
|
43
43
|
it('should detect Cloud Shell via CLOUD_SHELL', () => {
|
|
44
44
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
45
45
|
vi.stubEnv('CLOUD_SHELL', 'true');
|
|
46
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
46
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.cloudshell);
|
|
47
47
|
});
|
|
48
48
|
it('should detect Trae', () => {
|
|
49
49
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
50
50
|
vi.stubEnv('TERM_PRODUCT', 'Trae');
|
|
51
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
51
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.trae);
|
|
52
52
|
});
|
|
53
53
|
it('should detect Firebase Studio via MONOSPACE_ENV', () => {
|
|
54
54
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
55
55
|
vi.stubEnv('MONOSPACE_ENV', 'true');
|
|
56
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
56
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.firebasestudio);
|
|
57
57
|
});
|
|
58
58
|
it('should detect VSCode when no other IDE is detected and command includes "code"', () => {
|
|
59
59
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
60
60
|
vi.stubEnv('MONOSPACE_ENV', '');
|
|
61
|
-
expect(detectIde(ideProcessInfo)).toBe(
|
|
61
|
+
expect(detectIde(ideProcessInfo)).toBe(IDE_DEFINITIONS.vscode);
|
|
62
62
|
});
|
|
63
63
|
it('should detect VSCodeFork when no other IDE is detected and command does not include "code"', () => {
|
|
64
64
|
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
65
65
|
vi.stubEnv('MONOSPACE_ENV', '');
|
|
66
|
-
expect(detectIde(ideProcessInfoNoCode)).toBe(
|
|
67
|
-
});
|
|
68
|
-
it('should prioritize other IDEs over VSCode detection', () => {
|
|
69
|
-
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
70
|
-
vi.stubEnv('REPLIT_USER', 'testuser');
|
|
71
|
-
expect(detectIde(ideProcessInfo)).toBe(DetectedIde.Replit);
|
|
66
|
+
expect(detectIde(ideProcessInfoNoCode)).toBe(IDE_DEFINITIONS.vscodefork);
|
|
72
67
|
});
|
|
73
68
|
});
|
|
74
|
-
describe('
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
it('should return correct info for Replit', () => {
|
|
79
|
-
expect(getIdeInfo(DetectedIde.Replit)).toEqual({ displayName: 'Replit' });
|
|
80
|
-
});
|
|
81
|
-
it('should return correct info for Cursor', () => {
|
|
82
|
-
expect(getIdeInfo(DetectedIde.Cursor)).toEqual({ displayName: 'Cursor' });
|
|
83
|
-
});
|
|
84
|
-
it('should return correct info for CloudShell', () => {
|
|
85
|
-
expect(getIdeInfo(DetectedIde.CloudShell)).toEqual({
|
|
86
|
-
displayName: 'Cloud Shell',
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
it('should return correct info for Codespaces', () => {
|
|
90
|
-
expect(getIdeInfo(DetectedIde.Codespaces)).toEqual({
|
|
91
|
-
displayName: 'GitHub Codespaces',
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
it('should return correct info for FirebaseStudio', () => {
|
|
95
|
-
expect(getIdeInfo(DetectedIde.FirebaseStudio)).toEqual({
|
|
96
|
-
displayName: 'Firebase Studio',
|
|
97
|
-
});
|
|
69
|
+
describe('detectIde with ideInfoFromFile', () => {
|
|
70
|
+
const ideProcessInfo = { pid: 123, command: 'some/path/to/code' };
|
|
71
|
+
afterEach(() => {
|
|
72
|
+
vi.unstubAllEnvs();
|
|
98
73
|
});
|
|
99
|
-
it('should
|
|
100
|
-
|
|
74
|
+
it('should use the name and displayName from the file', () => {
|
|
75
|
+
const ideInfoFromFile = {
|
|
76
|
+
name: 'custom-ide',
|
|
77
|
+
displayName: 'Custom IDE',
|
|
78
|
+
};
|
|
79
|
+
expect(detectIde(ideProcessInfo, ideInfoFromFile)).toEqual(ideInfoFromFile);
|
|
101
80
|
});
|
|
102
|
-
it('should
|
|
103
|
-
|
|
81
|
+
it('should fall back to env detection if name is missing', () => {
|
|
82
|
+
const ideInfoFromFile = { displayName: 'Custom IDE' };
|
|
83
|
+
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
84
|
+
expect(detectIde(ideProcessInfo, ideInfoFromFile)).toBe(IDE_DEFINITIONS.vscode);
|
|
104
85
|
});
|
|
105
|
-
it('should
|
|
106
|
-
|
|
86
|
+
it('should fall back to env detection if displayName is missing', () => {
|
|
87
|
+
const ideInfoFromFile = { name: 'custom-ide' };
|
|
88
|
+
vi.stubEnv('TERM_PROGRAM', 'vscode');
|
|
89
|
+
expect(detectIde(ideProcessInfo, ideInfoFromFile)).toBe(IDE_DEFINITIONS.vscode);
|
|
107
90
|
});
|
|
108
91
|
});
|
|
109
92
|
//# sourceMappingURL=detect-ide.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-ide.test.js","sourceRoot":"","sources":["../../../src/ide/detect-ide.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"detect-ide.test.js","sourceRoot":"","sources":["../../../src/ide/detect-ide.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,14 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { type
|
|
7
|
-
|
|
6
|
+
import { type IdeInfo } from '../ide/detect-ide.js';
|
|
7
|
+
export type DiffUpdateResult = {
|
|
8
|
+
status: 'accepted';
|
|
9
|
+
content?: string;
|
|
10
|
+
} | {
|
|
11
|
+
status: 'rejected';
|
|
12
|
+
content: undefined;
|
|
13
|
+
};
|
|
8
14
|
export type IDEConnectionState = {
|
|
9
15
|
status: IDEConnectionStatus;
|
|
10
16
|
details?: string;
|
|
@@ -22,8 +28,9 @@ export declare class IdeClient {
|
|
|
22
28
|
private client;
|
|
23
29
|
private state;
|
|
24
30
|
private currentIde;
|
|
25
|
-
private currentIdeDisplayName;
|
|
26
31
|
private ideProcessInfo;
|
|
32
|
+
private connectionConfig;
|
|
33
|
+
private authToken;
|
|
27
34
|
private diffResponses;
|
|
28
35
|
private statusListeners;
|
|
29
36
|
private trustChangeListeners;
|
|
@@ -42,20 +49,24 @@ export declare class IdeClient {
|
|
|
42
49
|
removeTrustChangeListener(listener: (isTrusted: boolean) => void): void;
|
|
43
50
|
connect(): Promise<void>;
|
|
44
51
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
52
|
+
* Opens a diff view in the IDE, allowing the user to review and accept or
|
|
53
|
+
* reject changes.
|
|
54
|
+
*
|
|
55
|
+
* This method sends a request to the IDE to display a diff between the
|
|
56
|
+
* current content of a file and the new content provided. It then waits for
|
|
57
|
+
* a notification from the IDE indicating that the user has either accepted
|
|
58
|
+
* (potentially with manual edits) or rejected the diff.
|
|
59
|
+
*
|
|
60
|
+
* A mutex ensures that only one diff view can be open at a time to prevent
|
|
61
|
+
* race conditions.
|
|
51
62
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
63
|
+
* @param filePath The absolute path to the file to be diffed.
|
|
64
|
+
* @param newContent The proposed new content for the file.
|
|
65
|
+
* @returns A promise that resolves with a `DiffUpdateResult`, indicating
|
|
66
|
+
* whether the diff was 'accepted' or 'rejected' and including the final
|
|
67
|
+
* content if accepted.
|
|
57
68
|
*/
|
|
58
|
-
openDiff(filePath: string, newContent
|
|
69
|
+
openDiff(filePath: string, newContent: string): Promise<DiffUpdateResult>;
|
|
59
70
|
/**
|
|
60
71
|
* Acquires a lock to ensure sequential execution of critical sections.
|
|
61
72
|
*
|
|
@@ -79,13 +90,13 @@ export declare class IdeClient {
|
|
|
79
90
|
}): Promise<string | undefined>;
|
|
80
91
|
resolveDiffFromCli(filePath: string, outcome: 'accepted' | 'rejected'): Promise<void>;
|
|
81
92
|
disconnect(): Promise<void>;
|
|
82
|
-
getCurrentIde():
|
|
93
|
+
getCurrentIde(): IdeInfo | undefined;
|
|
83
94
|
getConnectionStatus(): IDEConnectionState;
|
|
84
95
|
getDetectedIdeDisplayName(): string | undefined;
|
|
85
96
|
isDiffingEnabled(): boolean;
|
|
86
97
|
private discoverTools;
|
|
87
98
|
private setState;
|
|
88
|
-
static validateWorkspacePath(ideWorkspacePath: string | undefined,
|
|
99
|
+
static validateWorkspacePath(ideWorkspacePath: string | undefined, cwd: string): {
|
|
89
100
|
isValid: boolean;
|
|
90
101
|
error?: string;
|
|
91
102
|
};
|
|
@@ -5,17 +5,19 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import * as fs from 'node:fs';
|
|
7
7
|
import { isSubpath } from '../utils/paths.js';
|
|
8
|
-
import { detectIde
|
|
9
|
-
import { ideContextStore
|
|
10
|
-
import { IdeContextNotificationSchema } from './types.js';
|
|
8
|
+
import { detectIde } from '../ide/detect-ide.js';
|
|
9
|
+
import { ideContextStore } from './ideContext.js';
|
|
10
|
+
import { IdeContextNotificationSchema, IdeDiffAcceptedNotificationSchema, IdeDiffClosedNotificationSchema, IdeDiffRejectedNotificationSchema, } from './types.js';
|
|
11
11
|
import { getIdeProcessInfo } from './process-utils.js';
|
|
12
12
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
13
13
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
14
14
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
15
|
+
import { CallToolResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
15
16
|
import * as os from 'node:os';
|
|
16
17
|
import * as path from 'node:path';
|
|
17
18
|
import { EnvHttpProxyAgent } from 'undici';
|
|
18
19
|
import { ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
20
|
+
import { IDE_REQUEST_TIMEOUT_MS } from './constants.js';
|
|
19
21
|
const logger = {
|
|
20
22
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
23
|
debug: (...args) => console.debug('[DEBUG] [IDEClient]', ...args),
|
|
@@ -49,8 +51,9 @@ export class IdeClient {
|
|
|
49
51
|
details: 'IDE integration is currently disabled. To enable it, run /ide enable.',
|
|
50
52
|
};
|
|
51
53
|
currentIde;
|
|
52
|
-
currentIdeDisplayName;
|
|
53
54
|
ideProcessInfo;
|
|
55
|
+
connectionConfig;
|
|
56
|
+
authToken;
|
|
54
57
|
diffResponses = new Map();
|
|
55
58
|
statusListeners = new Set();
|
|
56
59
|
trustChangeListeners = new Set();
|
|
@@ -67,10 +70,8 @@ export class IdeClient {
|
|
|
67
70
|
IdeClient.instancePromise = (async () => {
|
|
68
71
|
const client = new IdeClient();
|
|
69
72
|
client.ideProcessInfo = await getIdeProcessInfo();
|
|
70
|
-
client.
|
|
71
|
-
|
|
72
|
-
client.currentIdeDisplayName = getIdeInfo(client.currentIde).displayName;
|
|
73
|
-
}
|
|
73
|
+
client.connectionConfig = await client.getConnectionConfigFromFile();
|
|
74
|
+
client.currentIde = detectIde(client.ideProcessInfo, client.connectionConfig?.ideInfo);
|
|
74
75
|
return client;
|
|
75
76
|
})();
|
|
76
77
|
}
|
|
@@ -89,28 +90,31 @@ export class IdeClient {
|
|
|
89
90
|
this.trustChangeListeners.delete(listener);
|
|
90
91
|
}
|
|
91
92
|
async connect() {
|
|
92
|
-
if (!this.currentIde
|
|
93
|
+
if (!this.currentIde) {
|
|
93
94
|
this.setState(IDEConnectionStatus.Disconnected, `IDE integration is not supported in your current environment. To use this feature, run Gemini CLI in one of these supported IDEs: VS Code or VS Code forks`, false);
|
|
94
95
|
return;
|
|
95
96
|
}
|
|
96
97
|
this.setState(IDEConnectionStatus.Connecting);
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
this.connectionConfig = await this.getConnectionConfigFromFile();
|
|
99
|
+
if (this.connectionConfig?.authToken) {
|
|
100
|
+
this.authToken = this.connectionConfig.authToken;
|
|
101
|
+
}
|
|
102
|
+
const workspacePath = this.connectionConfig?.workspacePath ??
|
|
99
103
|
process.env['GEMINI_CLI_IDE_WORKSPACE_PATH'];
|
|
100
|
-
const { isValid, error } = IdeClient.validateWorkspacePath(workspacePath,
|
|
104
|
+
const { isValid, error } = IdeClient.validateWorkspacePath(workspacePath, process.cwd());
|
|
101
105
|
if (!isValid) {
|
|
102
106
|
this.setState(IDEConnectionStatus.Disconnected, error, true);
|
|
103
107
|
return;
|
|
104
108
|
}
|
|
105
|
-
if (
|
|
106
|
-
if (
|
|
107
|
-
const connected = await this.establishHttpConnection(
|
|
109
|
+
if (this.connectionConfig) {
|
|
110
|
+
if (this.connectionConfig.port) {
|
|
111
|
+
const connected = await this.establishHttpConnection(this.connectionConfig.port);
|
|
108
112
|
if (connected) {
|
|
109
113
|
return;
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
|
-
if (
|
|
113
|
-
const connected = await this.establishStdioConnection(
|
|
116
|
+
if (this.connectionConfig.stdio) {
|
|
117
|
+
const connected = await this.establishStdioConnection(this.connectionConfig.stdio);
|
|
114
118
|
if (connected) {
|
|
115
119
|
return;
|
|
116
120
|
}
|
|
@@ -130,21 +134,25 @@ export class IdeClient {
|
|
|
130
134
|
return;
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
|
-
this.setState(IDEConnectionStatus.Disconnected, `Failed to connect to IDE companion extension in ${this.
|
|
137
|
+
this.setState(IDEConnectionStatus.Disconnected, `Failed to connect to IDE companion extension in ${this.currentIde.displayName}. Please ensure the extension is running. To install the extension, run /ide install.`, true);
|
|
134
138
|
}
|
|
135
139
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
140
|
+
* Opens a diff view in the IDE, allowing the user to review and accept or
|
|
141
|
+
* reject changes.
|
|
142
|
+
*
|
|
143
|
+
* This method sends a request to the IDE to display a diff between the
|
|
144
|
+
* current content of a file and the new content provided. It then waits for
|
|
145
|
+
* a notification from the IDE indicating that the user has either accepted
|
|
146
|
+
* (potentially with manual edits) or rejected the diff.
|
|
147
|
+
*
|
|
148
|
+
* A mutex ensures that only one diff view can be open at a time to prevent
|
|
149
|
+
* race conditions.
|
|
142
150
|
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
151
|
+
* @param filePath The absolute path to the file to be diffed.
|
|
152
|
+
* @param newContent The proposed new content for the file.
|
|
153
|
+
* @returns A promise that resolves with a `DiffUpdateResult`, indicating
|
|
154
|
+
* whether the diff was 'accepted' or 'rejected' and including the final
|
|
155
|
+
* content if accepted.
|
|
148
156
|
*/
|
|
149
157
|
async openDiff(filePath, newContent) {
|
|
150
158
|
const release = await this.acquireMutex();
|
|
@@ -155,15 +163,27 @@ export class IdeClient {
|
|
|
155
163
|
}
|
|
156
164
|
this.diffResponses.set(filePath, resolve);
|
|
157
165
|
this.client
|
|
158
|
-
.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
.request({
|
|
167
|
+
method: 'tools/call',
|
|
168
|
+
params: {
|
|
169
|
+
name: `openDiff`,
|
|
170
|
+
arguments: {
|
|
171
|
+
filePath,
|
|
172
|
+
newContent,
|
|
173
|
+
},
|
|
163
174
|
},
|
|
175
|
+
}, CallToolResultSchema, { timeout: IDE_REQUEST_TIMEOUT_MS })
|
|
176
|
+
.then((parsedResultData) => {
|
|
177
|
+
if (parsedResultData.isError) {
|
|
178
|
+
const textPart = parsedResultData.content.find((part) => part.type === 'text');
|
|
179
|
+
const errorMessage = textPart?.text ?? `Tool 'openDiff' reported an error.`;
|
|
180
|
+
logger.debug(`Request for openDiff ${filePath} failed with isError:`, errorMessage);
|
|
181
|
+
this.diffResponses.delete(filePath);
|
|
182
|
+
reject(new Error(errorMessage));
|
|
183
|
+
}
|
|
164
184
|
})
|
|
165
185
|
.catch((err) => {
|
|
166
|
-
logger.debug(`
|
|
186
|
+
logger.debug(`Request for openDiff ${filePath} failed:`, err);
|
|
167
187
|
this.diffResponses.delete(filePath);
|
|
168
188
|
reject(err);
|
|
169
189
|
});
|
|
@@ -200,22 +220,48 @@ export class IdeClient {
|
|
|
200
220
|
}
|
|
201
221
|
async closeDiff(filePath, options) {
|
|
202
222
|
try {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
223
|
+
if (!this.client) {
|
|
224
|
+
return undefined;
|
|
225
|
+
}
|
|
226
|
+
const resultData = await this.client.request({
|
|
227
|
+
method: 'tools/call',
|
|
228
|
+
params: {
|
|
229
|
+
name: `closeDiff`,
|
|
230
|
+
arguments: {
|
|
231
|
+
filePath,
|
|
232
|
+
suppressNotification: options?.suppressNotification,
|
|
233
|
+
},
|
|
208
234
|
},
|
|
209
|
-
});
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
|
|
235
|
+
}, CallToolResultSchema, { timeout: IDE_REQUEST_TIMEOUT_MS });
|
|
236
|
+
if (!resultData) {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
if (resultData.isError) {
|
|
240
|
+
const textPart = resultData.content.find((part) => part.type === 'text');
|
|
241
|
+
const errorMessage = textPart?.text ?? `Tool 'closeDiff' reported an error.`;
|
|
242
|
+
logger.debug(`Request for closeDiff ${filePath} failed with isError:`, errorMessage);
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
const textPart = resultData.content.find((part) => part.type === 'text');
|
|
246
|
+
if (textPart?.text) {
|
|
247
|
+
try {
|
|
248
|
+
const parsedJson = JSON.parse(textPart.text);
|
|
249
|
+
if (parsedJson && typeof parsedJson.content === 'string') {
|
|
250
|
+
return parsedJson.content;
|
|
251
|
+
}
|
|
252
|
+
if (parsedJson && parsedJson.content === null) {
|
|
253
|
+
return undefined;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
catch (_e) {
|
|
257
|
+
logger.debug(`Invalid JSON in closeDiff response for ${filePath}:`, textPart.text);
|
|
258
|
+
}
|
|
213
259
|
}
|
|
214
260
|
}
|
|
215
261
|
catch (err) {
|
|
216
|
-
logger.debug(`
|
|
262
|
+
logger.debug(`Request for closeDiff ${filePath} failed:`, err);
|
|
217
263
|
}
|
|
218
|
-
return;
|
|
264
|
+
return undefined;
|
|
219
265
|
}
|
|
220
266
|
// Closes the diff. Instead of waiting for a notification,
|
|
221
267
|
// manually resolves the diff resolver as the desired outcome.
|
|
@@ -254,7 +300,7 @@ export class IdeClient {
|
|
|
254
300
|
return this.state;
|
|
255
301
|
}
|
|
256
302
|
getDetectedIdeDisplayName() {
|
|
257
|
-
return this.
|
|
303
|
+
return this.currentIde?.displayName;
|
|
258
304
|
}
|
|
259
305
|
isDiffingEnabled() {
|
|
260
306
|
return (!!this.client &&
|
|
@@ -316,17 +362,17 @@ export class IdeClient {
|
|
|
316
362
|
ideContextStore.clear();
|
|
317
363
|
}
|
|
318
364
|
}
|
|
319
|
-
static validateWorkspacePath(ideWorkspacePath,
|
|
365
|
+
static validateWorkspacePath(ideWorkspacePath, cwd) {
|
|
320
366
|
if (ideWorkspacePath === undefined) {
|
|
321
367
|
return {
|
|
322
368
|
isValid: false,
|
|
323
|
-
error: `Failed to connect to IDE companion extension
|
|
369
|
+
error: `Failed to connect to IDE companion extension. Please ensure the extension is running. To install the extension, run /ide install.`,
|
|
324
370
|
};
|
|
325
371
|
}
|
|
326
372
|
if (ideWorkspacePath === '') {
|
|
327
373
|
return {
|
|
328
374
|
isValid: false,
|
|
329
|
-
error: `To use this feature, please open a workspace folder in
|
|
375
|
+
error: `To use this feature, please open a workspace folder in your IDE and try again.`,
|
|
330
376
|
};
|
|
331
377
|
}
|
|
332
378
|
const ideWorkspacePaths = ideWorkspacePath.split(path.delimiter);
|
|
@@ -338,7 +384,7 @@ export class IdeClient {
|
|
|
338
384
|
if (!isWithinWorkspace) {
|
|
339
385
|
return {
|
|
340
386
|
isValid: false,
|
|
341
|
-
error: `Directory mismatch. Gemini CLI is running in a different location than the open workspace in
|
|
387
|
+
error: `Directory mismatch. Gemini CLI is running in a different location than the open workspace in the IDE. Please run the CLI from one of the following directories: ${ideWorkspacePaths.join(', ')}`,
|
|
342
388
|
};
|
|
343
389
|
}
|
|
344
390
|
return { isValid: true };
|
|
@@ -389,7 +435,7 @@ export class IdeClient {
|
|
|
389
435
|
// windows are open, multiple files matching the pattern are expected to
|
|
390
436
|
// exist.
|
|
391
437
|
}
|
|
392
|
-
const portFileDir = path.join(os.tmpdir(), '
|
|
438
|
+
const portFileDir = path.join(os.tmpdir(), 'gemini', 'ide');
|
|
393
439
|
let portFiles;
|
|
394
440
|
try {
|
|
395
441
|
portFiles = await fs.promises.readdir(portFileDir);
|
|
@@ -398,6 +444,9 @@ export class IdeClient {
|
|
|
398
444
|
logger.debug('Failed to read IDE connection directory:', e);
|
|
399
445
|
return undefined;
|
|
400
446
|
}
|
|
447
|
+
if (!portFiles) {
|
|
448
|
+
return undefined;
|
|
449
|
+
}
|
|
401
450
|
const fileRegex = new RegExp(`^gemini-ide-server-${this.ideProcessInfo.pid}-\\d+\\.json$`);
|
|
402
451
|
const matchingFiles = portFiles
|
|
403
452
|
.filter((file) => fileRegex.test(file))
|
|
@@ -426,7 +475,7 @@ export class IdeClient {
|
|
|
426
475
|
if (!content) {
|
|
427
476
|
return false;
|
|
428
477
|
}
|
|
429
|
-
const { isValid } = IdeClient.validateWorkspacePath(content.workspacePath,
|
|
478
|
+
const { isValid } = IdeClient.validateWorkspacePath(content.workspacePath, process.cwd());
|
|
430
479
|
return isValid;
|
|
431
480
|
});
|
|
432
481
|
if (validWorkspaces.length === 0) {
|
|
@@ -437,7 +486,7 @@ export class IdeClient {
|
|
|
437
486
|
}
|
|
438
487
|
const portFromEnv = this.getPortFromEnv();
|
|
439
488
|
if (portFromEnv) {
|
|
440
|
-
const matchingPort = validWorkspaces.find((content) => content.port === portFromEnv);
|
|
489
|
+
const matchingPort = validWorkspaces.find((content) => String(content.port) === portFromEnv);
|
|
441
490
|
if (matchingPort) {
|
|
442
491
|
return matchingPort;
|
|
443
492
|
}
|
|
@@ -462,7 +511,7 @@ export class IdeClient {
|
|
|
462
511
|
return new Response(response.body, {
|
|
463
512
|
status: response.status,
|
|
464
513
|
statusText: response.statusText,
|
|
465
|
-
headers: response.headers,
|
|
514
|
+
headers: [...response.headers.entries()],
|
|
466
515
|
});
|
|
467
516
|
};
|
|
468
517
|
}
|
|
@@ -480,10 +529,11 @@ export class IdeClient {
|
|
|
480
529
|
}
|
|
481
530
|
});
|
|
482
531
|
this.client.onerror = (_error) => {
|
|
483
|
-
|
|
532
|
+
const errorMessage = _error instanceof Error ? _error.message : `_error`;
|
|
533
|
+
this.setState(IDEConnectionStatus.Disconnected, `IDE connection error. The connection was lost unexpectedly. Please try reconnecting by running /ide enable\n${errorMessage}`, true);
|
|
484
534
|
};
|
|
485
535
|
this.client.onclose = () => {
|
|
486
|
-
this.setState(IDEConnectionStatus.Disconnected, `IDE connection
|
|
536
|
+
this.setState(IDEConnectionStatus.Disconnected, `IDE connection closed. To reconnect, run /ide enable.`, true);
|
|
487
537
|
};
|
|
488
538
|
this.client.setNotificationHandler(IdeDiffAcceptedNotificationSchema, (notification) => {
|
|
489
539
|
const { filePath, content } = notification.params;
|
|
@@ -496,6 +546,19 @@ export class IdeClient {
|
|
|
496
546
|
logger.debug(`No resolver found for ${filePath}`);
|
|
497
547
|
}
|
|
498
548
|
});
|
|
549
|
+
this.client.setNotificationHandler(IdeDiffRejectedNotificationSchema, (notification) => {
|
|
550
|
+
const { filePath } = notification.params;
|
|
551
|
+
const resolver = this.diffResponses.get(filePath);
|
|
552
|
+
if (resolver) {
|
|
553
|
+
resolver({ status: 'rejected', content: undefined });
|
|
554
|
+
this.diffResponses.delete(filePath);
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
logger.debug(`No resolver found for ${filePath}`);
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
// For backwards compatability. Newer extension versions will only send
|
|
561
|
+
// IdeDiffRejectedNotificationSchema.
|
|
499
562
|
this.client.setNotificationHandler(IdeDiffClosedNotificationSchema, (notification) => {
|
|
500
563
|
const { filePath } = notification.params;
|
|
501
564
|
const resolver = this.diffResponses.get(filePath);
|
|
@@ -519,6 +582,11 @@ export class IdeClient {
|
|
|
519
582
|
});
|
|
520
583
|
transport = new StreamableHTTPClientTransport(new URL(`http://${getIdeServerHost()}:${port}/mcp`), {
|
|
521
584
|
fetch: this.createProxyAwareFetch(),
|
|
585
|
+
requestInit: {
|
|
586
|
+
headers: this.authToken
|
|
587
|
+
? { Authorization: `Bearer ${this.authToken}` }
|
|
588
|
+
: {},
|
|
589
|
+
},
|
|
522
590
|
});
|
|
523
591
|
await this.client.connect(transport);
|
|
524
592
|
this.registerClientHandlers();
|