@google/gemini-cli 0.17.0-nightly.20251114.0fcbff506 → 0.17.0-nightly.20251117.cf8de02c6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/google-gemini-cli-0.17.0-nightly.20251116.e650a4ee5.tgz +0 -0
  2. package/dist/package.json +2 -2
  3. package/dist/src/commands/extensions/disable.test.d.ts +6 -0
  4. package/dist/src/commands/extensions/disable.test.js +160 -0
  5. package/dist/src/commands/extensions/disable.test.js.map +1 -0
  6. package/dist/src/commands/extensions/enable.test.d.ts +6 -0
  7. package/dist/src/commands/extensions/enable.test.js +140 -0
  8. package/dist/src/commands/extensions/enable.test.js.map +1 -0
  9. package/dist/src/commands/extensions/examples/mcp-server/example.test.d.ts +6 -0
  10. package/dist/src/commands/extensions/examples/mcp-server/example.test.js +111 -0
  11. package/dist/src/commands/extensions/examples/mcp-server/example.test.js.map +1 -0
  12. package/dist/src/commands/extensions/examples/mcp-server/example.test.ts +143 -0
  13. package/dist/src/commands/extensions/link.test.d.ts +6 -0
  14. package/dist/src/commands/extensions/link.test.js +121 -0
  15. package/dist/src/commands/extensions/link.test.js.map +1 -0
  16. package/dist/src/commands/extensions/list.test.d.ts +6 -0
  17. package/dist/src/commands/extensions/list.test.js +102 -0
  18. package/dist/src/commands/extensions/list.test.js.map +1 -0
  19. package/dist/src/commands/extensions/uninstall.test.js +107 -9
  20. package/dist/src/commands/extensions/uninstall.test.js.map +1 -1
  21. package/dist/src/commands/extensions/update.test.d.ts +6 -0
  22. package/dist/src/commands/extensions/update.test.js +160 -0
  23. package/dist/src/commands/extensions/update.test.js.map +1 -0
  24. package/dist/src/config/auth.js +1 -1
  25. package/dist/src/config/auth.test.js +2 -2
  26. package/dist/src/config/config.js +1 -3
  27. package/dist/src/config/config.js.map +1 -1
  28. package/dist/src/config/config.test.js +5 -2
  29. package/dist/src/config/config.test.js.map +1 -1
  30. package/dist/src/config/settingsSchema.d.ts +9 -0
  31. package/dist/src/config/settingsSchema.js +10 -1
  32. package/dist/src/config/settingsSchema.js.map +1 -1
  33. package/dist/src/config/trustedFolders.d.ts +1 -1
  34. package/dist/src/config/trustedFolders.js +24 -17
  35. package/dist/src/config/trustedFolders.js.map +1 -1
  36. package/dist/src/gemini.js +6 -4
  37. package/dist/src/gemini.js.map +1 -1
  38. package/dist/src/gemini.test.js.map +1 -1
  39. package/dist/src/generated/git-commit.d.ts +2 -2
  40. package/dist/src/generated/git-commit.js +2 -2
  41. package/dist/src/ui/AppContainer.js +55 -7
  42. package/dist/src/ui/AppContainer.js.map +1 -1
  43. package/dist/src/ui/auth/AuthDialog.js +11 -3
  44. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  45. package/dist/src/ui/auth/AuthDialog.test.js +32 -2
  46. package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
  47. package/dist/src/ui/commands/directoryCommand.d.ts +0 -1
  48. package/dist/src/ui/commands/directoryCommand.js +104 -43
  49. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  50. package/dist/src/ui/commands/directoryCommand.test.js +91 -2
  51. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -1
  52. package/dist/src/ui/commands/permissionsCommand.js +62 -5
  53. package/dist/src/ui/commands/permissionsCommand.js.map +1 -1
  54. package/dist/src/ui/commands/permissionsCommand.test.js +60 -4
  55. package/dist/src/ui/commands/permissionsCommand.test.js.map +1 -1
  56. package/dist/src/ui/commands/types.d.ts +7 -1
  57. package/dist/src/ui/commands/types.js.map +1 -1
  58. package/dist/src/ui/components/Composer.js +1 -1
  59. package/dist/src/ui/components/Composer.js.map +1 -1
  60. package/dist/src/ui/components/DialogManager.js +1 -1
  61. package/dist/src/ui/components/DialogManager.js.map +1 -1
  62. package/dist/src/ui/components/Help.js +1 -1
  63. package/dist/src/ui/components/Help.js.map +1 -1
  64. package/dist/src/ui/components/Help.test.js +9 -0
  65. package/dist/src/ui/components/Help.test.js.map +1 -1
  66. package/dist/src/ui/components/HistoryItemDisplay.js +2 -1
  67. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  68. package/dist/src/ui/components/InputPrompt.js +2 -0
  69. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  70. package/dist/src/ui/components/MultiFolderTrustDialog.d.ts +23 -0
  71. package/dist/src/ui/components/MultiFolderTrustDialog.js +90 -0
  72. package/dist/src/ui/components/MultiFolderTrustDialog.js.map +1 -0
  73. package/dist/src/ui/components/MultiFolderTrustDialog.test.d.ts +6 -0
  74. package/dist/src/ui/components/MultiFolderTrustDialog.test.js +161 -0
  75. package/dist/src/ui/components/MultiFolderTrustDialog.test.js.map +1 -0
  76. package/dist/src/ui/components/PermissionsModifyTrustDialog.d.ts +5 -2
  77. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +12 -7
  78. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
  79. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
  80. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  81. package/dist/src/ui/components/messages/ModelMessage.d.ts +11 -0
  82. package/dist/src/ui/components/messages/ModelMessage.js +5 -0
  83. package/dist/src/ui/components/messages/ModelMessage.js.map +1 -0
  84. package/dist/src/ui/contexts/KeypressContext.d.ts +1 -1
  85. package/dist/src/ui/contexts/KeypressContext.js +7 -2
  86. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  87. package/dist/src/ui/contexts/MouseContext.js +16 -1
  88. package/dist/src/ui/contexts/MouseContext.js.map +1 -1
  89. package/dist/src/ui/contexts/MouseContext.test.js +34 -0
  90. package/dist/src/ui/contexts/MouseContext.test.js.map +1 -1
  91. package/dist/src/ui/contexts/ScrollProvider.drag.test.js +12 -0
  92. package/dist/src/ui/contexts/ScrollProvider.drag.test.js.map +1 -1
  93. package/dist/src/ui/contexts/ScrollProvider.js +23 -12
  94. package/dist/src/ui/contexts/ScrollProvider.js.map +1 -1
  95. package/dist/src/ui/contexts/ScrollProvider.test.js +66 -0
  96. package/dist/src/ui/contexts/ScrollProvider.test.js.map +1 -1
  97. package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
  98. package/dist/src/ui/contexts/UIActionsContext.js +1 -0
  99. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  100. package/dist/src/ui/contexts/UIStateContext.d.ts +5 -0
  101. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  102. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +4 -2
  103. package/dist/src/ui/hooks/slashCommandProcessor.js +15 -3
  104. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  105. package/dist/src/ui/hooks/slashCommandProcessor.test.js +84 -38
  106. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  107. package/dist/src/ui/hooks/useFolderTrust.js +11 -1
  108. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
  109. package/dist/src/ui/hooks/useFolderTrust.test.js +22 -0
  110. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  111. package/dist/src/ui/hooks/useGeminiStream.js +17 -0
  112. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  113. package/dist/src/ui/hooks/useIncludeDirsTrust.d.ts +8 -0
  114. package/dist/src/ui/hooks/useIncludeDirsTrust.js +120 -0
  115. package/dist/src/ui/hooks/useIncludeDirsTrust.js.map +1 -0
  116. package/dist/src/ui/hooks/useIncludeDirsTrust.test.d.ts +6 -0
  117. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js +151 -0
  118. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js.map +1 -0
  119. package/dist/src/ui/hooks/usePermissionsModifyTrust.d.ts +2 -2
  120. package/dist/src/ui/hooks/usePermissionsModifyTrust.js +44 -7
  121. package/dist/src/ui/hooks/usePermissionsModifyTrust.js.map +1 -1
  122. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +191 -89
  123. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  124. package/dist/src/ui/layouts/DefaultAppLayout.js +1 -1
  125. package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
  126. package/dist/src/ui/noninteractive/nonInteractiveUi.js +1 -0
  127. package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
  128. package/dist/src/ui/types.d.ts +5 -1
  129. package/dist/src/ui/types.js.map +1 -1
  130. package/dist/src/ui/utils/directoryUtils.d.ts +6 -0
  131. package/dist/src/ui/utils/directoryUtils.js +21 -0
  132. package/dist/src/ui/utils/directoryUtils.js.map +1 -0
  133. package/dist/src/ui/utils/directoryUtils.test.d.ts +6 -0
  134. package/dist/src/ui/utils/directoryUtils.test.js +52 -0
  135. package/dist/src/ui/utils/directoryUtils.test.js.map +1 -0
  136. package/dist/src/ui/utils/mouse.d.ts +2 -1
  137. package/dist/src/ui/utils/mouse.js +27 -1
  138. package/dist/src/ui/utils/mouse.js.map +1 -1
  139. package/dist/src/ui/utils/mouse.test.js +5 -0
  140. package/dist/src/ui/utils/mouse.test.js.map +1 -1
  141. package/dist/src/utils/events.d.ts +5 -1
  142. package/dist/src/utils/events.js +2 -0
  143. package/dist/src/utils/events.js.map +1 -1
  144. package/dist/src/zed-integration/acp.d.ts +2 -24
  145. package/dist/src/zed-integration/acp.js +2 -156
  146. package/dist/src/zed-integration/acp.js.map +1 -1
  147. package/dist/src/zed-integration/acp.test.d.ts +6 -0
  148. package/dist/src/zed-integration/acp.test.js +227 -0
  149. package/dist/src/zed-integration/acp.test.js.map +1 -0
  150. package/dist/src/zed-integration/connection.d.ts +28 -0
  151. package/dist/src/zed-integration/connection.js +163 -0
  152. package/dist/src/zed-integration/connection.js.map +1 -0
  153. package/dist/src/zed-integration/schema.d.ts +69 -13
  154. package/dist/src/zed-integration/schema.js +6 -5
  155. package/dist/src/zed-integration/schema.js.map +1 -1
  156. package/dist/tsconfig.tsbuildinfo +1 -1
  157. package/package.json +3 -3
  158. package/dist/google-gemini-cli-0.17.0-nightly.20251113.48e3932f6.tgz +0 -0
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@google/gemini-cli",
3
- "version": "0.17.0-nightly.20251114.0fcbff506",
3
+ "version": "0.17.0-nightly.20251117.cf8de02c6",
4
4
  "description": "Gemini CLI",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,7 +25,7 @@
25
25
  "dist"
26
26
  ],
27
27
  "config": {
28
- "sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.17.0-nightly.20251114.0fcbff506"
28
+ "sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.17.0-nightly.20251117.cf8de02c6"
29
29
  },
30
30
  "dependencies": {
31
31
  "@google/gemini-cli-core": "file:../core",
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,160 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { vi, describe, it, expect, beforeEach, afterEach, } from 'vitest';
7
+ import {} from 'yargs';
8
+ import { handleDisable, disableCommand } from './disable.js';
9
+ import { ExtensionManager } from '../../config/extension-manager.js';
10
+ import { loadSettings, SettingScope, } from '../../config/settings.js';
11
+ import { getErrorMessage } from '../../utils/errors.js';
12
+ // Mock dependencies
13
+ vi.mock('../../config/extension-manager.js');
14
+ vi.mock('../../config/settings.js');
15
+ vi.mock('../../utils/errors.js');
16
+ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
17
+ const actual = await importOriginal();
18
+ return {
19
+ ...actual,
20
+ debugLogger: {
21
+ log: vi.fn(),
22
+ error: vi.fn(),
23
+ },
24
+ };
25
+ });
26
+ vi.mock('../../config/extensions/consent.js', () => ({
27
+ requestConsentNonInteractive: vi.fn(),
28
+ }));
29
+ vi.mock('../../config/extensions/extensionSettings.js', () => ({
30
+ promptForSetting: vi.fn(),
31
+ }));
32
+ describe('extensions disable command', () => {
33
+ const mockLoadSettings = vi.mocked(loadSettings);
34
+ const mockGetErrorMessage = vi.mocked(getErrorMessage);
35
+ const mockExtensionManager = vi.mocked(ExtensionManager);
36
+ let mockDebugLogger;
37
+ beforeEach(async () => {
38
+ vi.clearAllMocks();
39
+ // We need to re-import the mocked module to get the fresh mock
40
+ mockDebugLogger = (await import('@google/gemini-cli-core'))
41
+ .debugLogger;
42
+ mockLoadSettings.mockReturnValue({
43
+ merged: {},
44
+ });
45
+ mockExtensionManager.prototype.loadExtensions = vi
46
+ .fn()
47
+ .mockResolvedValue(undefined);
48
+ mockExtensionManager.prototype.disableExtension = vi
49
+ .fn()
50
+ .mockResolvedValue(undefined);
51
+ });
52
+ afterEach(() => {
53
+ vi.restoreAllMocks();
54
+ });
55
+ describe('handleDisable', () => {
56
+ it.each([
57
+ {
58
+ name: 'my-extension',
59
+ scope: undefined,
60
+ expectedScope: SettingScope.User,
61
+ expectedLog: 'Extension "my-extension" successfully disabled for scope "undefined".',
62
+ },
63
+ {
64
+ name: 'my-extension',
65
+ scope: 'user',
66
+ expectedScope: SettingScope.User,
67
+ expectedLog: 'Extension "my-extension" successfully disabled for scope "user".',
68
+ },
69
+ {
70
+ name: 'my-extension',
71
+ scope: 'workspace',
72
+ expectedScope: SettingScope.Workspace,
73
+ expectedLog: 'Extension "my-extension" successfully disabled for scope "workspace".',
74
+ },
75
+ ])('should disable an extension in the $expectedScope scope when scope is $scope', async ({ name, scope, expectedScope, expectedLog }) => {
76
+ const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
77
+ await handleDisable({ name, scope });
78
+ expect(mockExtensionManager).toHaveBeenCalledWith(expect.objectContaining({
79
+ workspaceDir: '/test/dir',
80
+ }));
81
+ expect(mockExtensionManager.prototype.loadExtensions).toHaveBeenCalled();
82
+ expect(mockExtensionManager.prototype.disableExtension).toHaveBeenCalledWith(name, expectedScope);
83
+ expect(mockDebugLogger.log).toHaveBeenCalledWith(expectedLog);
84
+ mockCwd.mockRestore();
85
+ });
86
+ it('should log an error message and exit with code 1 when extension disabling fails', async () => {
87
+ const mockProcessExit = vi
88
+ .spyOn(process, 'exit')
89
+ .mockImplementation((() => { }));
90
+ const error = new Error('Disable failed');
91
+ mockExtensionManager.prototype.disableExtension.mockRejectedValue(error);
92
+ mockGetErrorMessage.mockReturnValue('Disable failed message');
93
+ await handleDisable({ name: 'my-extension' });
94
+ expect(mockDebugLogger.error).toHaveBeenCalledWith('Disable failed message');
95
+ expect(mockProcessExit).toHaveBeenCalledWith(1);
96
+ mockProcessExit.mockRestore();
97
+ });
98
+ });
99
+ describe('disableCommand', () => {
100
+ const command = disableCommand;
101
+ it('should have correct command and describe', () => {
102
+ expect(command.command).toBe('disable [--scope] <name>');
103
+ expect(command.describe).toBe('Disables an extension.');
104
+ });
105
+ describe('builder', () => {
106
+ let yargsMock;
107
+ beforeEach(() => {
108
+ yargsMock = {
109
+ positional: vi.fn().mockReturnThis(),
110
+ option: vi.fn().mockReturnThis(),
111
+ check: vi.fn().mockReturnThis(),
112
+ };
113
+ });
114
+ it('should configure positional and option arguments', () => {
115
+ command.builder(yargsMock);
116
+ expect(yargsMock.positional).toHaveBeenCalledWith('name', {
117
+ describe: 'The name of the extension to disable.',
118
+ type: 'string',
119
+ });
120
+ expect(yargsMock.option).toHaveBeenCalledWith('scope', {
121
+ describe: 'The scope to disable the extension in.',
122
+ type: 'string',
123
+ default: SettingScope.User,
124
+ });
125
+ expect(yargsMock.check).toHaveBeenCalled();
126
+ });
127
+ it('check function should throw for invalid scope', () => {
128
+ command.builder(yargsMock);
129
+ const checkCallback = yargsMock.check.mock.calls[0][0];
130
+ const expectedError = `Invalid scope: invalid. Please use one of ${Object.values(SettingScope)
131
+ .map((s) => s.toLowerCase())
132
+ .join(', ')}.`;
133
+ expect(() => checkCallback({ scope: 'invalid' })).toThrow(expectedError);
134
+ });
135
+ it.each(['user', 'workspace', 'USER', 'WorkSpace'])('check function should return true for valid scope "%s"', (scope) => {
136
+ command.builder(yargsMock);
137
+ const checkCallback = yargsMock.check.mock.calls[0][0];
138
+ expect(checkCallback({ scope })).toBe(true);
139
+ });
140
+ });
141
+ it('handler should trigger extension disabling', async () => {
142
+ const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
143
+ const argv = {
144
+ name: 'test-ext',
145
+ scope: 'workspace',
146
+ _: [],
147
+ $0: '',
148
+ };
149
+ await command.handler(argv);
150
+ expect(mockExtensionManager).toHaveBeenCalledWith(expect.objectContaining({
151
+ workspaceDir: '/test/dir',
152
+ }));
153
+ expect(mockExtensionManager.prototype.loadExtensions).toHaveBeenCalled();
154
+ expect(mockExtensionManager.prototype.disableExtension).toHaveBeenCalledWith('test-ext', SettingScope.Workspace);
155
+ expect(mockDebugLogger.log).toHaveBeenCalledWith('Extension "test-ext" successfully disabled for scope "workspace".');
156
+ mockCwd.mockRestore();
157
+ });
158
+ });
159
+ });
160
+ //# sourceMappingURL=disable.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disable.test.js","sourceRoot":"","sources":["../../../../src/commands/extensions/disable.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { vi, describe, it, expect, beforeEach, afterEach, } from 'vitest';
7
+ import {} from 'yargs';
8
+ import { handleEnable, enableCommand } from './enable.js';
9
+ import { ExtensionManager } from '../../config/extension-manager.js';
10
+ import { loadSettings, SettingScope, } from '../../config/settings.js';
11
+ import { FatalConfigError } from '@google/gemini-cli-core';
12
+ // Mock dependencies
13
+ vi.mock('../../config/extension-manager.js');
14
+ vi.mock('../../config/settings.js');
15
+ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
16
+ const actual = await importOriginal();
17
+ return {
18
+ ...actual,
19
+ debugLogger: {
20
+ log: vi.fn(),
21
+ error: vi.fn(),
22
+ },
23
+ getErrorMessage: vi.fn((error) => error.message),
24
+ FatalConfigError: class extends Error {
25
+ constructor(message) {
26
+ super(message);
27
+ this.name = 'FatalConfigError';
28
+ }
29
+ },
30
+ };
31
+ });
32
+ vi.mock('../../config/extensions/consent.js');
33
+ vi.mock('../../config/extensions/extensionSettings.js');
34
+ describe('extensions enable command', () => {
35
+ const mockLoadSettings = vi.mocked(loadSettings);
36
+ const mockExtensionManager = vi.mocked(ExtensionManager);
37
+ let mockDebugLogger;
38
+ beforeEach(async () => {
39
+ vi.clearAllMocks();
40
+ mockDebugLogger = (await import('@google/gemini-cli-core'))
41
+ .debugLogger;
42
+ mockLoadSettings.mockReturnValue({
43
+ merged: {},
44
+ });
45
+ mockExtensionManager.prototype.loadExtensions = vi
46
+ .fn()
47
+ .mockResolvedValue(undefined);
48
+ mockExtensionManager.prototype.enableExtension = vi.fn();
49
+ });
50
+ afterEach(() => {
51
+ vi.restoreAllMocks();
52
+ });
53
+ describe('handleEnable', () => {
54
+ it.each([
55
+ {
56
+ name: 'my-extension',
57
+ scope: undefined,
58
+ expectedScope: SettingScope.User,
59
+ expectedLog: 'Extension "my-extension" successfully enabled in all scopes.',
60
+ },
61
+ {
62
+ name: 'my-extension',
63
+ scope: 'workspace',
64
+ expectedScope: SettingScope.Workspace,
65
+ expectedLog: 'Extension "my-extension" successfully enabled for scope "workspace".',
66
+ },
67
+ ])('should enable an extension in the $expectedScope scope when scope is $scope', async ({ name, scope, expectedScope, expectedLog }) => {
68
+ const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
69
+ await handleEnable({ name, scope });
70
+ expect(mockExtensionManager).toHaveBeenCalledWith(expect.objectContaining({
71
+ workspaceDir: '/test/dir',
72
+ }));
73
+ expect(mockExtensionManager.prototype.loadExtensions).toHaveBeenCalled();
74
+ expect(mockExtensionManager.prototype.enableExtension).toHaveBeenCalledWith(name, expectedScope);
75
+ expect(mockDebugLogger.log).toHaveBeenCalledWith(expectedLog);
76
+ mockCwd.mockRestore();
77
+ });
78
+ it('should throw FatalConfigError when extension enabling fails', async () => {
79
+ const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
80
+ const error = new Error('Enable failed');
81
+ mockExtensionManager.prototype.enableExtension.mockImplementation(() => {
82
+ throw error;
83
+ });
84
+ const promise = handleEnable({ name: 'my-extension' });
85
+ await expect(promise).rejects.toThrow(FatalConfigError);
86
+ await expect(promise).rejects.toThrow('Enable failed');
87
+ mockCwd.mockRestore();
88
+ });
89
+ });
90
+ describe('enableCommand', () => {
91
+ const command = enableCommand;
92
+ it('should have correct command and describe', () => {
93
+ expect(command.command).toBe('enable [--scope] <name>');
94
+ expect(command.describe).toBe('Enables an extension.');
95
+ });
96
+ describe('builder', () => {
97
+ let yargsMock;
98
+ beforeEach(() => {
99
+ yargsMock = {
100
+ positional: vi.fn().mockReturnThis(),
101
+ option: vi.fn().mockReturnThis(),
102
+ check: vi.fn().mockReturnThis(),
103
+ };
104
+ });
105
+ it('should configure positional and option arguments', () => {
106
+ command.builder(yargsMock);
107
+ expect(yargsMock.positional).toHaveBeenCalledWith('name', {
108
+ describe: 'The name of the extension to enable.',
109
+ type: 'string',
110
+ });
111
+ expect(yargsMock.option).toHaveBeenCalledWith('scope', {
112
+ describe: 'The scope to enable the extension in. If not set, will be enabled in all scopes.',
113
+ type: 'string',
114
+ });
115
+ expect(yargsMock.check).toHaveBeenCalled();
116
+ });
117
+ it('check function should throw for invalid scope', () => {
118
+ command.builder(yargsMock);
119
+ const checkCallback = yargsMock.check.mock.calls[0][0];
120
+ const expectedError = `Invalid scope: invalid. Please use one of ${Object.values(SettingScope)
121
+ .map((s) => s.toLowerCase())
122
+ .join(', ')}.`;
123
+ expect(() => checkCallback({ scope: 'invalid' })).toThrow(expectedError);
124
+ });
125
+ });
126
+ it('handler should call handleEnable', async () => {
127
+ const mockCwd = vi.spyOn(process, 'cwd').mockReturnValue('/test/dir');
128
+ const argv = {
129
+ name: 'test-ext',
130
+ scope: 'workspace',
131
+ _: [],
132
+ $0: '',
133
+ };
134
+ await command.handler(argv);
135
+ expect(mockExtensionManager.prototype.enableExtension).toHaveBeenCalledWith('test-ext', SettingScope.Workspace);
136
+ mockCwd.mockRestore();
137
+ });
138
+ });
139
+ });
140
+ //# sourceMappingURL=enable.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enable.test.js","sourceRoot":"","sources":["../../../../src/commands/extensions/enable.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
7
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import { z } from 'zod';
10
+ // Mock the MCP server and transport
11
+ const mockRegisterTool = vi.fn();
12
+ const mockRegisterPrompt = vi.fn();
13
+ const mockConnect = vi.fn();
14
+ vi.mock('@modelcontextprotocol/sdk/server/mcp.js', () => ({
15
+ McpServer: vi.fn().mockImplementation(() => ({
16
+ registerTool: mockRegisterTool,
17
+ registerPrompt: mockRegisterPrompt,
18
+ connect: mockConnect,
19
+ })),
20
+ }));
21
+ vi.mock('@modelcontextprotocol/sdk/server/stdio.js', () => ({
22
+ StdioServerTransport: vi.fn(),
23
+ }));
24
+ describe('MCP Server Example', () => {
25
+ beforeEach(async () => {
26
+ // Dynamically import the server setup after mocks are in place
27
+ await import('./example.js');
28
+ });
29
+ afterEach(() => {
30
+ vi.clearAllMocks();
31
+ vi.resetModules();
32
+ });
33
+ it('should create an McpServer with the correct name and version', () => {
34
+ expect(McpServer).toHaveBeenCalledWith({
35
+ name: 'prompt-server',
36
+ version: '1.0.0',
37
+ });
38
+ });
39
+ it('should register the "fetch_posts" tool', () => {
40
+ expect(mockRegisterTool).toHaveBeenCalledWith('fetch_posts', {
41
+ description: 'Fetches a list of posts from a public API.',
42
+ inputSchema: z.object({}).shape,
43
+ }, expect.any(Function));
44
+ });
45
+ it('should register the "poem-writer" prompt', () => {
46
+ expect(mockRegisterPrompt).toHaveBeenCalledWith('poem-writer', {
47
+ title: 'Poem Writer',
48
+ description: 'Write a nice haiku',
49
+ argsSchema: expect.any(Object),
50
+ }, expect.any(Function));
51
+ });
52
+ it('should connect the server to an StdioServerTransport', () => {
53
+ expect(StdioServerTransport).toHaveBeenCalled();
54
+ expect(mockConnect).toHaveBeenCalledWith(expect.any(StdioServerTransport));
55
+ });
56
+ describe('fetch_posts tool implementation', () => {
57
+ it('should fetch posts and return a formatted response', async () => {
58
+ const mockPosts = [
59
+ { id: 1, title: 'Post 1' },
60
+ { id: 2, title: 'Post 2' },
61
+ ];
62
+ global.fetch = vi.fn().mockResolvedValue({
63
+ json: vi.fn().mockResolvedValue(mockPosts),
64
+ });
65
+ const toolFn = mockRegisterTool.mock.calls[0][2];
66
+ const result = await toolFn();
67
+ expect(global.fetch).toHaveBeenCalledWith('https://jsonplaceholder.typicode.com/posts');
68
+ expect(result).toEqual({
69
+ content: [
70
+ {
71
+ type: 'text',
72
+ text: JSON.stringify({ posts: mockPosts }),
73
+ },
74
+ ],
75
+ });
76
+ });
77
+ });
78
+ describe('poem-writer prompt implementation', () => {
79
+ it('should generate a prompt with a title', () => {
80
+ const promptFn = mockRegisterPrompt.mock.calls[0][2];
81
+ const result = promptFn({ title: 'My Poem' });
82
+ expect(result).toEqual({
83
+ messages: [
84
+ {
85
+ role: 'user',
86
+ content: {
87
+ type: 'text',
88
+ text: 'Write a haiku called My Poem. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables ',
89
+ },
90
+ },
91
+ ],
92
+ });
93
+ });
94
+ it('should generate a prompt with a title and mood', () => {
95
+ const promptFn = mockRegisterPrompt.mock.calls[0][2];
96
+ const result = promptFn({ title: 'My Poem', mood: 'sad' });
97
+ expect(result).toEqual({
98
+ messages: [
99
+ {
100
+ role: 'user',
101
+ content: {
102
+ type: 'text',
103
+ text: 'Write a haiku with the mood sad called My Poem. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables ',
104
+ },
105
+ },
106
+ ],
107
+ });
108
+ });
109
+ });
110
+ });
111
+ //# sourceMappingURL=example.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example.test.js","sourceRoot":"","sources":["../../../../../../src/commands/extensions/examples/mcp-server/example.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import {
8
+ describe,
9
+ it,
10
+ expect,
11
+ vi,
12
+ beforeEach,
13
+ afterEach,
14
+ type Mock,
15
+ } from 'vitest';
16
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
17
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
18
+ import { z } from 'zod';
19
+
20
+ // Mock the MCP server and transport
21
+ const mockRegisterTool = vi.fn();
22
+ const mockRegisterPrompt = vi.fn();
23
+ const mockConnect = vi.fn();
24
+
25
+ vi.mock('@modelcontextprotocol/sdk/server/mcp.js', () => ({
26
+ McpServer: vi.fn().mockImplementation(() => ({
27
+ registerTool: mockRegisterTool,
28
+ registerPrompt: mockRegisterPrompt,
29
+ connect: mockConnect,
30
+ })),
31
+ }));
32
+
33
+ vi.mock('@modelcontextprotocol/sdk/server/stdio.js', () => ({
34
+ StdioServerTransport: vi.fn(),
35
+ }));
36
+
37
+ describe('MCP Server Example', () => {
38
+ beforeEach(async () => {
39
+ // Dynamically import the server setup after mocks are in place
40
+ await import('./example.js');
41
+ });
42
+
43
+ afterEach(() => {
44
+ vi.clearAllMocks();
45
+ vi.resetModules();
46
+ });
47
+
48
+ it('should create an McpServer with the correct name and version', () => {
49
+ expect(McpServer).toHaveBeenCalledWith({
50
+ name: 'prompt-server',
51
+ version: '1.0.0',
52
+ });
53
+ });
54
+
55
+ it('should register the "fetch_posts" tool', () => {
56
+ expect(mockRegisterTool).toHaveBeenCalledWith(
57
+ 'fetch_posts',
58
+ {
59
+ description: 'Fetches a list of posts from a public API.',
60
+ inputSchema: z.object({}).shape,
61
+ },
62
+ expect.any(Function),
63
+ );
64
+ });
65
+
66
+ it('should register the "poem-writer" prompt', () => {
67
+ expect(mockRegisterPrompt).toHaveBeenCalledWith(
68
+ 'poem-writer',
69
+ {
70
+ title: 'Poem Writer',
71
+ description: 'Write a nice haiku',
72
+ argsSchema: expect.any(Object),
73
+ },
74
+ expect.any(Function),
75
+ );
76
+ });
77
+
78
+ it('should connect the server to an StdioServerTransport', () => {
79
+ expect(StdioServerTransport).toHaveBeenCalled();
80
+ expect(mockConnect).toHaveBeenCalledWith(expect.any(StdioServerTransport));
81
+ });
82
+
83
+ describe('fetch_posts tool implementation', () => {
84
+ it('should fetch posts and return a formatted response', async () => {
85
+ const mockPosts = [
86
+ { id: 1, title: 'Post 1' },
87
+ { id: 2, title: 'Post 2' },
88
+ ];
89
+ global.fetch = vi.fn().mockResolvedValue({
90
+ json: vi.fn().mockResolvedValue(mockPosts),
91
+ });
92
+
93
+ const toolFn = (mockRegisterTool as Mock).mock.calls[0][2];
94
+ const result = await toolFn();
95
+
96
+ expect(global.fetch).toHaveBeenCalledWith(
97
+ 'https://jsonplaceholder.typicode.com/posts',
98
+ );
99
+ expect(result).toEqual({
100
+ content: [
101
+ {
102
+ type: 'text',
103
+ text: JSON.stringify({ posts: mockPosts }),
104
+ },
105
+ ],
106
+ });
107
+ });
108
+ });
109
+
110
+ describe('poem-writer prompt implementation', () => {
111
+ it('should generate a prompt with a title', () => {
112
+ const promptFn = (mockRegisterPrompt as Mock).mock.calls[0][2];
113
+ const result = promptFn({ title: 'My Poem' });
114
+ expect(result).toEqual({
115
+ messages: [
116
+ {
117
+ role: 'user',
118
+ content: {
119
+ type: 'text',
120
+ text: 'Write a haiku called My Poem. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables ',
121
+ },
122
+ },
123
+ ],
124
+ });
125
+ });
126
+
127
+ it('should generate a prompt with a title and mood', () => {
128
+ const promptFn = (mockRegisterPrompt as Mock).mock.calls[0][2];
129
+ const result = promptFn({ title: 'My Poem', mood: 'sad' });
130
+ expect(result).toEqual({
131
+ messages: [
132
+ {
133
+ role: 'user',
134
+ content: {
135
+ type: 'text',
136
+ text: 'Write a haiku with the mood sad called My Poem. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables ',
137
+ },
138
+ },
139
+ ],
140
+ });
141
+ });
142
+ });
143
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};