@google/gemini-cli 0.16.0-preview.4 → 0.17.0-nightly.20251116.e650a4ee5

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 (130) hide show
  1. package/dist/google-gemini-cli-0.17.0-nightly.20251114.0fcbff506.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/generated/git-commit.js.map +1 -1
  42. package/dist/src/ui/AppContainer.js +22 -4
  43. package/dist/src/ui/AppContainer.js.map +1 -1
  44. package/dist/src/ui/auth/AuthDialog.js +11 -3
  45. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  46. package/dist/src/ui/auth/AuthDialog.test.js +32 -2
  47. package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
  48. package/dist/src/ui/commands/directoryCommand.d.ts +0 -1
  49. package/dist/src/ui/commands/directoryCommand.js +104 -43
  50. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  51. package/dist/src/ui/commands/directoryCommand.test.js +91 -2
  52. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -1
  53. package/dist/src/ui/commands/permissionsCommand.js +62 -5
  54. package/dist/src/ui/commands/permissionsCommand.js.map +1 -1
  55. package/dist/src/ui/commands/permissionsCommand.test.js +60 -4
  56. package/dist/src/ui/commands/permissionsCommand.test.js.map +1 -1
  57. package/dist/src/ui/commands/types.d.ts +7 -1
  58. package/dist/src/ui/commands/types.js.map +1 -1
  59. package/dist/src/ui/components/DialogManager.js +1 -1
  60. package/dist/src/ui/components/DialogManager.js.map +1 -1
  61. package/dist/src/ui/components/HistoryItemDisplay.js +2 -1
  62. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  63. package/dist/src/ui/components/MultiFolderTrustDialog.d.ts +23 -0
  64. package/dist/src/ui/components/MultiFolderTrustDialog.js +90 -0
  65. package/dist/src/ui/components/MultiFolderTrustDialog.js.map +1 -0
  66. package/dist/src/ui/components/MultiFolderTrustDialog.test.d.ts +6 -0
  67. package/dist/src/ui/components/MultiFolderTrustDialog.test.js +161 -0
  68. package/dist/src/ui/components/MultiFolderTrustDialog.test.js.map +1 -0
  69. package/dist/src/ui/components/PermissionsModifyTrustDialog.d.ts +5 -2
  70. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +12 -7
  71. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
  72. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
  73. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  74. package/dist/src/ui/components/messages/ModelMessage.d.ts +11 -0
  75. package/dist/src/ui/components/messages/ModelMessage.js +5 -0
  76. package/dist/src/ui/components/messages/ModelMessage.js.map +1 -0
  77. package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
  78. package/dist/src/ui/contexts/UIActionsContext.js +1 -0
  79. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  80. package/dist/src/ui/contexts/UIStateContext.d.ts +4 -0
  81. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  82. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +4 -2
  83. package/dist/src/ui/hooks/slashCommandProcessor.js +9 -2
  84. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  85. package/dist/src/ui/hooks/slashCommandProcessor.test.js +2 -1
  86. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  87. package/dist/src/ui/hooks/useFolderTrust.js +11 -1
  88. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
  89. package/dist/src/ui/hooks/useFolderTrust.test.js +22 -0
  90. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  91. package/dist/src/ui/hooks/useGeminiStream.js +17 -0
  92. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  93. package/dist/src/ui/hooks/useIncludeDirsTrust.d.ts +8 -0
  94. package/dist/src/ui/hooks/useIncludeDirsTrust.js +120 -0
  95. package/dist/src/ui/hooks/useIncludeDirsTrust.js.map +1 -0
  96. package/dist/src/ui/hooks/useIncludeDirsTrust.test.d.ts +6 -0
  97. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js +151 -0
  98. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js.map +1 -0
  99. package/dist/src/ui/hooks/usePermissionsModifyTrust.d.ts +2 -2
  100. package/dist/src/ui/hooks/usePermissionsModifyTrust.js +44 -7
  101. package/dist/src/ui/hooks/usePermissionsModifyTrust.js.map +1 -1
  102. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +191 -89
  103. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  104. package/dist/src/ui/layouts/DefaultAppLayout.js +1 -1
  105. package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
  106. package/dist/src/ui/noninteractive/nonInteractiveUi.js +1 -0
  107. package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
  108. package/dist/src/ui/types.d.ts +5 -1
  109. package/dist/src/ui/types.js.map +1 -1
  110. package/dist/src/ui/utils/directoryUtils.d.ts +6 -0
  111. package/dist/src/ui/utils/directoryUtils.js +21 -0
  112. package/dist/src/ui/utils/directoryUtils.js.map +1 -0
  113. package/dist/src/ui/utils/directoryUtils.test.d.ts +6 -0
  114. package/dist/src/ui/utils/directoryUtils.test.js +52 -0
  115. package/dist/src/ui/utils/directoryUtils.test.js.map +1 -0
  116. package/dist/src/zed-integration/acp.d.ts +2 -24
  117. package/dist/src/zed-integration/acp.js +2 -156
  118. package/dist/src/zed-integration/acp.js.map +1 -1
  119. package/dist/src/zed-integration/acp.test.d.ts +6 -0
  120. package/dist/src/zed-integration/acp.test.js +227 -0
  121. package/dist/src/zed-integration/acp.test.js.map +1 -0
  122. package/dist/src/zed-integration/connection.d.ts +28 -0
  123. package/dist/src/zed-integration/connection.js +163 -0
  124. package/dist/src/zed-integration/connection.js.map +1 -0
  125. package/dist/src/zed-integration/schema.d.ts +69 -13
  126. package/dist/src/zed-integration/schema.js +6 -5
  127. package/dist/src/zed-integration/schema.js.map +1 -1
  128. package/dist/tsconfig.tsbuildinfo +1 -1
  129. package/package.json +3 -3
  130. package/dist/google-gemini-cli-0.16.0-preview.3.tgz +0 -0
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@google/gemini-cli",
3
- "version": "0.16.0-preview.4",
3
+ "version": "0.17.0-nightly.20251116.e650a4ee5",
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.16.0-preview.4"
28
+ "sandboxImageUri": "us-docker.pkg.dev/gemini-code-dev/gemini-cli/sandbox:0.17.0-nightly.20251116.e650a4ee5"
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 {};