@google/gemini-cli-core 0.1.15 → 0.1.16

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 (222) hide show
  1. package/README.md +32 -0
  2. package/dist/google-gemini-cli-core-0.1.15.tgz +0 -0
  3. package/dist/src/code_assist/converter.d.ts +2 -1
  4. package/dist/src/code_assist/converter.js +2 -1
  5. package/dist/src/code_assist/converter.js.map +1 -1
  6. package/dist/src/code_assist/converter.test.js +13 -10
  7. package/dist/src/code_assist/converter.test.js.map +1 -1
  8. package/dist/src/code_assist/server.d.ts +2 -2
  9. package/dist/src/code_assist/server.js +4 -4
  10. package/dist/src/code_assist/server.js.map +1 -1
  11. package/dist/src/code_assist/server.test.js +9 -9
  12. package/dist/src/code_assist/server.test.js.map +1 -1
  13. package/dist/src/code_assist/setup.js +1 -1
  14. package/dist/src/code_assist/setup.js.map +1 -1
  15. package/dist/src/code_assist/setup.test.js +2 -2
  16. package/dist/src/code_assist/setup.test.js.map +1 -1
  17. package/dist/src/config/config.d.ts +19 -7
  18. package/dist/src/config/config.js +37 -13
  19. package/dist/src/config/config.js.map +1 -1
  20. package/dist/src/config/config.test.js +33 -0
  21. package/dist/src/config/config.test.js.map +1 -1
  22. package/dist/src/config/flashFallback.test.js +23 -47
  23. package/dist/src/config/flashFallback.test.js.map +1 -1
  24. package/dist/src/config/models.d.ts +1 -0
  25. package/dist/src/config/models.js +1 -0
  26. package/dist/src/config/models.js.map +1 -1
  27. package/dist/src/core/client.d.ts +3 -1
  28. package/dist/src/core/client.js +74 -23
  29. package/dist/src/core/client.js.map +1 -1
  30. package/dist/src/core/client.test.js +167 -21
  31. package/dist/src/core/client.test.js.map +1 -1
  32. package/dist/src/core/contentGenerator.d.ts +2 -2
  33. package/dist/src/core/contentGenerator.js.map +1 -1
  34. package/dist/src/core/coreToolScheduler.d.ts +1 -3
  35. package/dist/src/core/coreToolScheduler.js +25 -16
  36. package/dist/src/core/coreToolScheduler.js.map +1 -1
  37. package/dist/src/core/coreToolScheduler.test.js +76 -1
  38. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  39. package/dist/src/core/geminiChat.js +3 -2
  40. package/dist/src/core/geminiChat.js.map +1 -1
  41. package/dist/src/core/geminiChat.test.js +2 -2
  42. package/dist/src/core/geminiChat.test.js.map +1 -1
  43. package/dist/src/core/logger.d.ts +1 -0
  44. package/dist/src/core/logger.js +22 -8
  45. package/dist/src/core/logger.js.map +1 -1
  46. package/dist/src/core/logger.test.js +60 -9
  47. package/dist/src/core/logger.test.js.map +1 -1
  48. package/dist/src/core/nonInteractiveToolExecutor.js +11 -3
  49. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  50. package/dist/src/core/prompts.js +1 -1
  51. package/dist/src/core/tokenLimits.js +1 -0
  52. package/dist/src/core/tokenLimits.js.map +1 -1
  53. package/dist/src/core/turn.d.ts +3 -0
  54. package/dist/src/core/turn.js +3 -0
  55. package/dist/src/core/turn.js.map +1 -1
  56. package/dist/src/ide/detect-ide.d.ts +10 -0
  57. package/dist/src/ide/detect-ide.js +24 -0
  58. package/dist/src/ide/detect-ide.js.map +1 -0
  59. package/dist/src/ide/ide-client.d.ts +19 -7
  60. package/dist/src/ide/ide-client.js +100 -36
  61. package/dist/src/ide/ide-client.js.map +1 -1
  62. package/dist/src/ide/ide-installer.d.ts +15 -0
  63. package/dist/src/ide/ide-installer.js +111 -0
  64. package/dist/src/ide/ide-installer.js.map +1 -0
  65. package/dist/src/ide/ide-installer.test.d.ts +6 -0
  66. package/dist/src/ide/ide-installer.test.js +78 -0
  67. package/dist/src/ide/ide-installer.test.js.map +1 -0
  68. package/dist/src/ide/ideContext.d.ts +212 -107
  69. package/dist/src/ide/ideContext.js +45 -44
  70. package/dist/src/ide/ideContext.js.map +1 -1
  71. package/dist/src/ide/ideContext.test.js +254 -100
  72. package/dist/src/ide/ideContext.test.js.map +1 -1
  73. package/dist/src/index.d.ts +4 -0
  74. package/dist/src/index.js +4 -0
  75. package/dist/src/index.js.map +1 -1
  76. package/dist/src/mcp/oauth-provider.js +3 -3
  77. package/dist/src/mcp/oauth-provider.js.map +1 -1
  78. package/dist/src/mcp/oauth-provider.test.js +9 -8
  79. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  80. package/dist/src/mcp/oauth-utils.js +2 -2
  81. package/dist/src/mcp/oauth-utils.js.map +1 -1
  82. package/dist/src/mcp/oauth-utils.test.js +1 -1
  83. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  84. package/dist/src/services/loopDetectionService.d.ts +3 -0
  85. package/dist/src/services/loopDetectionService.js +18 -0
  86. package/dist/src/services/loopDetectionService.js.map +1 -1
  87. package/dist/src/services/loopDetectionService.test.js +90 -11
  88. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  89. package/dist/src/services/shellExecutionService.js +7 -4
  90. package/dist/src/services/shellExecutionService.js.map +1 -1
  91. package/dist/src/services/shellExecutionService.test.js +11 -5
  92. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  93. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +4 -2
  94. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +80 -34
  95. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  96. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +6 -1
  97. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +19 -0
  98. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  99. package/dist/src/telemetry/constants.d.ts +2 -1
  100. package/dist/src/telemetry/constants.js +2 -1
  101. package/dist/src/telemetry/constants.js.map +1 -1
  102. package/dist/src/telemetry/index.d.ts +2 -2
  103. package/dist/src/telemetry/index.js +2 -2
  104. package/dist/src/telemetry/index.js.map +1 -1
  105. package/dist/src/telemetry/loggers.d.ts +3 -2
  106. package/dist/src/telemetry/loggers.js +21 -5
  107. package/dist/src/telemetry/loggers.js.map +1 -1
  108. package/dist/src/telemetry/loggers.test.circular.js +2 -0
  109. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  110. package/dist/src/telemetry/loggers.test.js +8 -3
  111. package/dist/src/telemetry/loggers.test.js.map +1 -1
  112. package/dist/src/telemetry/telemetry.test.js +2 -0
  113. package/dist/src/telemetry/telemetry.test.js.map +1 -1
  114. package/dist/src/telemetry/types.d.ts +19 -4
  115. package/dist/src/telemetry/types.js +30 -4
  116. package/dist/src/telemetry/types.js.map +1 -1
  117. package/dist/src/telemetry/uiTelemetry.test.js +3 -0
  118. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  119. package/dist/src/test-utils/mockWorkspaceContext.d.ts +13 -0
  120. package/dist/src/test-utils/mockWorkspaceContext.js +24 -0
  121. package/dist/src/test-utils/mockWorkspaceContext.js.map +1 -0
  122. package/dist/src/tools/edit.js +27 -3
  123. package/dist/src/tools/edit.js.map +1 -1
  124. package/dist/src/tools/edit.test.js +104 -1
  125. package/dist/src/tools/edit.test.js.map +1 -1
  126. package/dist/src/tools/glob.js +53 -17
  127. package/dist/src/tools/glob.js.map +1 -1
  128. package/dist/src/tools/glob.test.js +25 -2
  129. package/dist/src/tools/glob.test.js.map +1 -1
  130. package/dist/src/tools/grep.d.ts +1 -1
  131. package/dist/src/tools/grep.js +81 -29
  132. package/dist/src/tools/grep.js.map +1 -1
  133. package/dist/src/tools/grep.test.js +72 -5
  134. package/dist/src/tools/grep.test.js.map +1 -1
  135. package/dist/src/tools/ls.js +4 -3
  136. package/dist/src/tools/ls.js.map +1 -1
  137. package/dist/src/tools/ls.test.d.ts +6 -0
  138. package/dist/src/tools/ls.test.js +356 -0
  139. package/dist/src/tools/ls.test.js.map +1 -0
  140. package/dist/src/tools/mcp-client.js +8 -14
  141. package/dist/src/tools/mcp-client.js.map +1 -1
  142. package/dist/src/tools/mcp-client.test.js +34 -0
  143. package/dist/src/tools/mcp-client.test.js.map +1 -1
  144. package/dist/src/tools/memoryTool.d.ts +17 -2
  145. package/dist/src/tools/memoryTool.js +130 -13
  146. package/dist/src/tools/memoryTool.js.map +1 -1
  147. package/dist/src/tools/memoryTool.test.js +88 -3
  148. package/dist/src/tools/memoryTool.test.js.map +1 -1
  149. package/dist/src/tools/read-file.js +8 -6
  150. package/dist/src/tools/read-file.js.map +1 -1
  151. package/dist/src/tools/read-file.test.js +30 -2
  152. package/dist/src/tools/read-file.test.js.map +1 -1
  153. package/dist/src/tools/read-many-files.js +22 -12
  154. package/dist/src/tools/read-many-files.js.map +1 -1
  155. package/dist/src/tools/read-many-files.test.js +35 -2
  156. package/dist/src/tools/read-many-files.test.js.map +1 -1
  157. package/dist/src/tools/shell.js +8 -4
  158. package/dist/src/tools/shell.js.map +1 -1
  159. package/dist/src/tools/shell.test.js +33 -1
  160. package/dist/src/tools/shell.test.js.map +1 -1
  161. package/dist/src/tools/tool-error.d.ts +22 -0
  162. package/dist/src/tools/tool-error.js +27 -0
  163. package/dist/src/tools/tool-error.js.map +1 -0
  164. package/dist/src/tools/tool-registry.test.js +8 -0
  165. package/dist/src/tools/tool-registry.test.js.map +1 -1
  166. package/dist/src/tools/tools.d.ts +8 -0
  167. package/dist/src/tools/tools.js.map +1 -1
  168. package/dist/src/tools/write-file.js +5 -3
  169. package/dist/src/tools/write-file.js.map +1 -1
  170. package/dist/src/tools/write-file.test.js +36 -2
  171. package/dist/src/tools/write-file.test.js.map +1 -1
  172. package/dist/src/utils/bfsFileSearch.js +51 -27
  173. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  174. package/dist/src/utils/bfsFileSearch.test.js +59 -0
  175. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  176. package/dist/src/utils/editCorrector.js +2 -2
  177. package/dist/src/utils/editCorrector.js.map +1 -1
  178. package/dist/src/utils/editor.d.ts +1 -1
  179. package/dist/src/utils/editor.js +9 -0
  180. package/dist/src/utils/editor.js.map +1 -1
  181. package/dist/src/utils/editor.test.js +21 -1
  182. package/dist/src/utils/editor.test.js.map +1 -1
  183. package/dist/src/utils/fileUtils.js +12 -1
  184. package/dist/src/utils/fileUtils.js.map +1 -1
  185. package/dist/src/utils/fileUtils.test.js +29 -1
  186. package/dist/src/utils/fileUtils.test.js.map +1 -1
  187. package/dist/src/utils/flashFallback.integration.test.js +8 -0
  188. package/dist/src/utils/flashFallback.integration.test.js.map +1 -1
  189. package/dist/src/utils/memoryDiscovery.d.ts +1 -1
  190. package/dist/src/utils/memoryDiscovery.js +54 -75
  191. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  192. package/dist/src/utils/memoryDiscovery.test.js +4 -3
  193. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  194. package/dist/src/utils/memoryImportProcessor.d.ts +19 -12
  195. package/dist/src/utils/memoryImportProcessor.js +241 -82
  196. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  197. package/dist/src/utils/memoryImportProcessor.test.js +595 -50
  198. package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
  199. package/dist/src/utils/nextSpeakerChecker.js +3 -23
  200. package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
  201. package/dist/src/utils/nextSpeakerChecker.test.js +2 -2
  202. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  203. package/dist/src/utils/retry.d.ts +3 -0
  204. package/dist/src/utils/retry.js.map +1 -1
  205. package/dist/src/utils/retry.test.js.map +1 -1
  206. package/dist/src/utils/secure-browser-launcher.d.ts +23 -0
  207. package/dist/src/utils/secure-browser-launcher.js +164 -0
  208. package/dist/src/utils/secure-browser-launcher.js.map +1 -0
  209. package/dist/src/utils/secure-browser-launcher.test.d.ts +6 -0
  210. package/dist/src/utils/secure-browser-launcher.test.js +149 -0
  211. package/dist/src/utils/secure-browser-launcher.test.js.map +1 -0
  212. package/dist/src/utils/summarizer.js +2 -2
  213. package/dist/src/utils/summarizer.js.map +1 -1
  214. package/dist/src/utils/workspaceContext.d.ts +47 -0
  215. package/dist/src/utils/workspaceContext.js +106 -0
  216. package/dist/src/utils/workspaceContext.js.map +1 -0
  217. package/dist/src/utils/workspaceContext.test.d.ts +6 -0
  218. package/dist/src/utils/workspaceContext.test.js +209 -0
  219. package/dist/src/utils/workspaceContext.test.js.map +1 -0
  220. package/dist/tsconfig.tsbuildinfo +1 -1
  221. package/package.json +2 -1
  222. package/dist/google-gemini-cli-core-0.1.13.tgz +0 -0
@@ -0,0 +1,149 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
+ import { openBrowserSecurely } from './secure-browser-launcher.js';
8
+ // Create mock function using vi.hoisted
9
+ const mockExecFile = vi.hoisted(() => vi.fn());
10
+ // Mock modules
11
+ vi.mock('node:child_process');
12
+ vi.mock('node:util', () => ({
13
+ promisify: () => mockExecFile,
14
+ }));
15
+ describe('secure-browser-launcher', () => {
16
+ let originalPlatform;
17
+ beforeEach(() => {
18
+ vi.clearAllMocks();
19
+ mockExecFile.mockResolvedValue({ stdout: '', stderr: '' });
20
+ originalPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
21
+ });
22
+ afterEach(() => {
23
+ if (originalPlatform) {
24
+ Object.defineProperty(process, 'platform', originalPlatform);
25
+ }
26
+ });
27
+ function setPlatform(platform) {
28
+ Object.defineProperty(process, 'platform', {
29
+ value: platform,
30
+ configurable: true,
31
+ });
32
+ }
33
+ describe('URL validation', () => {
34
+ it('should allow valid HTTP URLs', async () => {
35
+ setPlatform('darwin');
36
+ await openBrowserSecurely('http://example.com');
37
+ expect(mockExecFile).toHaveBeenCalledWith('open', ['http://example.com'], expect.any(Object));
38
+ });
39
+ it('should allow valid HTTPS URLs', async () => {
40
+ setPlatform('darwin');
41
+ await openBrowserSecurely('https://example.com');
42
+ expect(mockExecFile).toHaveBeenCalledWith('open', ['https://example.com'], expect.any(Object));
43
+ });
44
+ it('should reject non-HTTP(S) protocols', async () => {
45
+ await expect(openBrowserSecurely('file:///etc/passwd')).rejects.toThrow('Unsafe protocol');
46
+ await expect(openBrowserSecurely('javascript:alert(1)')).rejects.toThrow('Unsafe protocol');
47
+ await expect(openBrowserSecurely('ftp://example.com')).rejects.toThrow('Unsafe protocol');
48
+ });
49
+ it('should reject invalid URLs', async () => {
50
+ await expect(openBrowserSecurely('not-a-url')).rejects.toThrow('Invalid URL');
51
+ await expect(openBrowserSecurely('')).rejects.toThrow('Invalid URL');
52
+ });
53
+ it('should reject URLs with control characters', async () => {
54
+ await expect(openBrowserSecurely('http://example.com\nmalicious-command')).rejects.toThrow('invalid characters');
55
+ await expect(openBrowserSecurely('http://example.com\rmalicious-command')).rejects.toThrow('invalid characters');
56
+ await expect(openBrowserSecurely('http://example.com\x00')).rejects.toThrow('invalid characters');
57
+ });
58
+ });
59
+ describe('Command injection prevention', () => {
60
+ it('should prevent PowerShell command injection on Windows', async () => {
61
+ setPlatform('win32');
62
+ // The POC from the vulnerability report
63
+ const maliciousUrl = "http://127.0.0.1:8080/?param=example#$(Invoke-Expression([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('Y2FsYy5leGU='))))";
64
+ await openBrowserSecurely(maliciousUrl);
65
+ // Verify that execFile was called (not exec) and the URL is passed safely
66
+ expect(mockExecFile).toHaveBeenCalledWith('powershell.exe', [
67
+ '-NoProfile',
68
+ '-NonInteractive',
69
+ '-WindowStyle',
70
+ 'Hidden',
71
+ '-Command',
72
+ `Start-Process '${maliciousUrl.replace(/'/g, "''")}'`,
73
+ ], expect.any(Object));
74
+ });
75
+ it('should handle URLs with special shell characters safely', async () => {
76
+ setPlatform('darwin');
77
+ const urlsWithSpecialChars = [
78
+ 'http://example.com/path?param=value&other=$value',
79
+ 'http://example.com/path#fragment;command',
80
+ 'http://example.com/$(whoami)',
81
+ 'http://example.com/`command`',
82
+ 'http://example.com/|pipe',
83
+ 'http://example.com/>redirect',
84
+ ];
85
+ for (const url of urlsWithSpecialChars) {
86
+ await openBrowserSecurely(url);
87
+ // Verify the URL is passed as an argument, not interpreted by shell
88
+ expect(mockExecFile).toHaveBeenCalledWith('open', [url], expect.any(Object));
89
+ }
90
+ });
91
+ it('should properly escape single quotes in URLs on Windows', async () => {
92
+ setPlatform('win32');
93
+ const urlWithSingleQuotes = "http://example.com/path?name=O'Brien&test='value'";
94
+ await openBrowserSecurely(urlWithSingleQuotes);
95
+ // Verify that single quotes are escaped by doubling them
96
+ expect(mockExecFile).toHaveBeenCalledWith('powershell.exe', [
97
+ '-NoProfile',
98
+ '-NonInteractive',
99
+ '-WindowStyle',
100
+ 'Hidden',
101
+ '-Command',
102
+ `Start-Process 'http://example.com/path?name=O''Brien&test=''value'''`,
103
+ ], expect.any(Object));
104
+ });
105
+ });
106
+ describe('Platform-specific behavior', () => {
107
+ it('should use correct command on macOS', async () => {
108
+ setPlatform('darwin');
109
+ await openBrowserSecurely('https://example.com');
110
+ expect(mockExecFile).toHaveBeenCalledWith('open', ['https://example.com'], expect.any(Object));
111
+ });
112
+ it('should use PowerShell on Windows', async () => {
113
+ setPlatform('win32');
114
+ await openBrowserSecurely('https://example.com');
115
+ expect(mockExecFile).toHaveBeenCalledWith('powershell.exe', expect.arrayContaining([
116
+ '-Command',
117
+ `Start-Process 'https://example.com'`,
118
+ ]), expect.any(Object));
119
+ });
120
+ it('should use xdg-open on Linux', async () => {
121
+ setPlatform('linux');
122
+ await openBrowserSecurely('https://example.com');
123
+ expect(mockExecFile).toHaveBeenCalledWith('xdg-open', ['https://example.com'], expect.any(Object));
124
+ });
125
+ it('should throw on unsupported platforms', async () => {
126
+ setPlatform('aix');
127
+ await expect(openBrowserSecurely('https://example.com')).rejects.toThrow('Unsupported platform');
128
+ });
129
+ });
130
+ describe('Error handling', () => {
131
+ it('should handle browser launch failures gracefully', async () => {
132
+ setPlatform('darwin');
133
+ mockExecFile.mockRejectedValueOnce(new Error('Command not found'));
134
+ await expect(openBrowserSecurely('https://example.com')).rejects.toThrow('Failed to open browser');
135
+ });
136
+ it('should try fallback browsers on Linux', async () => {
137
+ setPlatform('linux');
138
+ // First call to xdg-open fails
139
+ mockExecFile.mockRejectedValueOnce(new Error('Command not found'));
140
+ // Second call to gnome-open succeeds
141
+ mockExecFile.mockResolvedValueOnce({ stdout: '', stderr: '' });
142
+ await openBrowserSecurely('https://example.com');
143
+ expect(mockExecFile).toHaveBeenCalledTimes(2);
144
+ expect(mockExecFile).toHaveBeenNthCalledWith(1, 'xdg-open', ['https://example.com'], expect.any(Object));
145
+ expect(mockExecFile).toHaveBeenNthCalledWith(2, 'gnome-open', ['https://example.com'], expect.any(Object));
146
+ });
147
+ });
148
+ });
149
+ //# sourceMappingURL=secure-browser-launcher.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-browser-launcher.test.js","sourceRoot":"","sources":["../../../src/utils/secure-browser-launcher.test.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
6
+ import { DEFAULT_GEMINI_FLASH_LITE_MODEL } from '../config/models.js';
7
7
  import { getResponseText, partToString } from './partUtils.js';
8
8
  /**
9
9
  * The default summarizer for tool results.
@@ -40,7 +40,7 @@ export async function summarizeToolOutput(textToSummarize, geminiClient, abortSi
40
40
  maxOutputTokens,
41
41
  };
42
42
  try {
43
- const parsedResponse = (await geminiClient.generateContent(contents, toolOutputSummarizerConfig, abortSignal, DEFAULT_GEMINI_FLASH_MODEL));
43
+ const parsedResponse = (await geminiClient.generateContent(contents, toolOutputSummarizerConfig, abortSignal, DEFAULT_GEMINI_FLASH_LITE_MODEL));
44
44
  return getResponseText(parsedResponse) || textToSummarize;
45
45
  }
46
46
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../../src/utils/summarizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAc/D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAe,CAC3C,MAAkB,EAClB,aAA2B,EAC3B,YAAyB,EACzB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAExD,MAAM,4BAA4B,GAAG;;;;;;;;;;;;CAYpC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAe,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,CAC7E,mBAAmB,CACjB,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,EAC/B,YAAY,EACZ,WAAW,CACZ,CAAC;AAEJ,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,eAAuB,EACvB,YAA0B,EAC1B,WAAwB,EACxB,kBAA0B,IAAI;IAE9B,8GAA8G;IAC9G,wFAAwF;IACxF,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACjE,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,MAAM,MAAM,GAAG,4BAA4B,CAAC,OAAO,CACjD,mBAAmB,EACnB,MAAM,CAAC,eAAe,CAAC,CACxB,CAAC,OAAO,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1E,MAAM,0BAA0B,GAA0B;QACxD,eAAe;KAChB,CAAC;IACF,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,CAAC,MAAM,YAAY,CAAC,eAAe,CACxD,QAAQ,EACR,0BAA0B,EAC1B,WAAW,EACX,0BAA0B,CAC3B,CAAuC,CAAC;QACzC,OAAO,eAAe,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QACzD,OAAO,eAAe,CAAC;IACzB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../../src/utils/summarizer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAc/D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAe,CAC3C,MAAkB,EAClB,aAA2B,EAC3B,YAAyB,EACzB,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAExD,MAAM,4BAA4B,GAAG;;;;;;;;;;;;CAYpC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAe,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,CAC7E,mBAAmB,CACjB,YAAY,CAAC,MAAM,CAAC,UAAU,CAAC,EAC/B,YAAY,EACZ,WAAW,CACZ,CAAC;AAEJ,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,eAAuB,EACvB,YAA0B,EAC1B,WAAwB,EACxB,kBAA0B,IAAI;IAE9B,8GAA8G;IAC9G,wFAAwF;IACxF,IAAI,CAAC,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACjE,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,MAAM,MAAM,GAAG,4BAA4B,CAAC,OAAO,CACjD,mBAAmB,EACnB,MAAM,CAAC,eAAe,CAAC,CACxB,CAAC,OAAO,CAAC,mBAAmB,EAAE,eAAe,CAAC,CAAC;IAEhD,MAAM,QAAQ,GAAc,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1E,MAAM,0BAA0B,GAA0B;QACxD,eAAe;KAChB,CAAC;IACF,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,CAAC,MAAM,YAAY,CAAC,eAAe,CACxD,QAAQ,EACR,0BAA0B,EAC1B,WAAW,EACX,+BAA+B,CAChC,CAAuC,CAAC;QACzC,OAAO,eAAe,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;QACzD,OAAO,eAAe,CAAC;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * WorkspaceContext manages multiple workspace directories and validates paths
8
+ * against them. This allows the CLI to operate on files from multiple directories
9
+ * in a single session.
10
+ */
11
+ export declare class WorkspaceContext {
12
+ private directories;
13
+ /**
14
+ * Creates a new WorkspaceContext with the given initial directory and optional additional directories.
15
+ * @param initialDirectory The initial working directory (usually cwd)
16
+ * @param additionalDirectories Optional array of additional directories to include
17
+ */
18
+ constructor(initialDirectory: string, additionalDirectories?: string[]);
19
+ /**
20
+ * Adds a directory to the workspace.
21
+ * @param directory The directory path to add (can be relative or absolute)
22
+ * @param basePath Optional base path for resolving relative paths (defaults to cwd)
23
+ */
24
+ addDirectory(directory: string, basePath?: string): void;
25
+ /**
26
+ * Internal method to add a directory with validation.
27
+ */
28
+ private addDirectoryInternal;
29
+ /**
30
+ * Gets a copy of all workspace directories.
31
+ * @returns Array of absolute directory paths
32
+ */
33
+ getDirectories(): readonly string[];
34
+ /**
35
+ * Checks if a given path is within any of the workspace directories.
36
+ * @param pathToCheck The path to validate
37
+ * @returns True if the path is within the workspace, false otherwise
38
+ */
39
+ isPathWithinWorkspace(pathToCheck: string): boolean;
40
+ /**
41
+ * Checks if a path is within a given root directory.
42
+ * @param pathToCheck The absolute path to check
43
+ * @param rootDirectory The absolute root directory
44
+ * @returns True if the path is within the root directory, false otherwise
45
+ */
46
+ private isPathWithinRoot;
47
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ /**
9
+ * WorkspaceContext manages multiple workspace directories and validates paths
10
+ * against them. This allows the CLI to operate on files from multiple directories
11
+ * in a single session.
12
+ */
13
+ export class WorkspaceContext {
14
+ directories;
15
+ /**
16
+ * Creates a new WorkspaceContext with the given initial directory and optional additional directories.
17
+ * @param initialDirectory The initial working directory (usually cwd)
18
+ * @param additionalDirectories Optional array of additional directories to include
19
+ */
20
+ constructor(initialDirectory, additionalDirectories = []) {
21
+ this.directories = new Set();
22
+ this.addDirectoryInternal(initialDirectory);
23
+ for (const dir of additionalDirectories) {
24
+ this.addDirectoryInternal(dir);
25
+ }
26
+ }
27
+ /**
28
+ * Adds a directory to the workspace.
29
+ * @param directory The directory path to add (can be relative or absolute)
30
+ * @param basePath Optional base path for resolving relative paths (defaults to cwd)
31
+ */
32
+ addDirectory(directory, basePath = process.cwd()) {
33
+ this.addDirectoryInternal(directory, basePath);
34
+ }
35
+ /**
36
+ * Internal method to add a directory with validation.
37
+ */
38
+ addDirectoryInternal(directory, basePath = process.cwd()) {
39
+ const absolutePath = path.isAbsolute(directory)
40
+ ? directory
41
+ : path.resolve(basePath, directory);
42
+ if (!fs.existsSync(absolutePath)) {
43
+ throw new Error(`Directory does not exist: ${absolutePath}`);
44
+ }
45
+ const stats = fs.statSync(absolutePath);
46
+ if (!stats.isDirectory()) {
47
+ throw new Error(`Path is not a directory: ${absolutePath}`);
48
+ }
49
+ let realPath;
50
+ try {
51
+ realPath = fs.realpathSync(absolutePath);
52
+ }
53
+ catch (_error) {
54
+ throw new Error(`Failed to resolve path: ${absolutePath}`);
55
+ }
56
+ this.directories.add(realPath);
57
+ }
58
+ /**
59
+ * Gets a copy of all workspace directories.
60
+ * @returns Array of absolute directory paths
61
+ */
62
+ getDirectories() {
63
+ return Array.from(this.directories);
64
+ }
65
+ /**
66
+ * Checks if a given path is within any of the workspace directories.
67
+ * @param pathToCheck The path to validate
68
+ * @returns True if the path is within the workspace, false otherwise
69
+ */
70
+ isPathWithinWorkspace(pathToCheck) {
71
+ try {
72
+ const absolutePath = path.resolve(pathToCheck);
73
+ let resolvedPath = absolutePath;
74
+ if (fs.existsSync(absolutePath)) {
75
+ try {
76
+ resolvedPath = fs.realpathSync(absolutePath);
77
+ }
78
+ catch (_error) {
79
+ return false;
80
+ }
81
+ }
82
+ for (const dir of this.directories) {
83
+ if (this.isPathWithinRoot(resolvedPath, dir)) {
84
+ return true;
85
+ }
86
+ }
87
+ return false;
88
+ }
89
+ catch (_error) {
90
+ return false;
91
+ }
92
+ }
93
+ /**
94
+ * Checks if a path is within a given root directory.
95
+ * @param pathToCheck The absolute path to check
96
+ * @param rootDirectory The absolute root directory
97
+ * @returns True if the path is within the root directory, false otherwise
98
+ */
99
+ isPathWithinRoot(pathToCheck, rootDirectory) {
100
+ const relative = path.relative(rootDirectory, pathToCheck);
101
+ return (!relative.startsWith(`..${path.sep}`) &&
102
+ relative !== '..' &&
103
+ !path.isAbsolute(relative));
104
+ }
105
+ }
106
+ //# sourceMappingURL=workspaceContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceContext.js","sourceRoot":"","sources":["../../../src/utils/workspaceContext.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,209 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import { WorkspaceContext } from './workspaceContext.js';
10
+ vi.mock('fs');
11
+ describe('WorkspaceContext', () => {
12
+ let workspaceContext;
13
+ // Use path module to create platform-agnostic paths
14
+ const mockCwd = path.resolve(path.sep, 'home', 'user', 'project');
15
+ const mockExistingDir = path.resolve(path.sep, 'home', 'user', 'other-project');
16
+ const mockNonExistentDir = path.resolve(path.sep, 'home', 'user', 'does-not-exist');
17
+ const mockSymlinkDir = path.resolve(path.sep, 'home', 'user', 'symlink');
18
+ const mockRealPath = path.resolve(path.sep, 'home', 'user', 'real-directory');
19
+ beforeEach(() => {
20
+ vi.resetAllMocks();
21
+ // Mock fs.existsSync
22
+ vi.mocked(fs.existsSync).mockImplementation((path) => {
23
+ const pathStr = path.toString();
24
+ return (pathStr === mockCwd ||
25
+ pathStr === mockExistingDir ||
26
+ pathStr === mockSymlinkDir ||
27
+ pathStr === mockRealPath);
28
+ });
29
+ // Mock fs.statSync
30
+ vi.mocked(fs.statSync).mockImplementation((path) => {
31
+ const pathStr = path.toString();
32
+ if (pathStr === mockNonExistentDir) {
33
+ throw new Error('ENOENT');
34
+ }
35
+ return {
36
+ isDirectory: () => true,
37
+ };
38
+ });
39
+ // Mock fs.realpathSync
40
+ vi.mocked(fs.realpathSync).mockImplementation((path) => {
41
+ const pathStr = path.toString();
42
+ if (pathStr === mockSymlinkDir) {
43
+ return mockRealPath;
44
+ }
45
+ return pathStr;
46
+ });
47
+ });
48
+ describe('initialization', () => {
49
+ it('should initialize with a single directory (cwd)', () => {
50
+ workspaceContext = new WorkspaceContext(mockCwd);
51
+ const directories = workspaceContext.getDirectories();
52
+ expect(directories).toHaveLength(1);
53
+ expect(directories[0]).toBe(mockCwd);
54
+ });
55
+ it('should validate and resolve directories to absolute paths', () => {
56
+ const absolutePath = path.join(mockCwd, 'subdir');
57
+ vi.mocked(fs.existsSync).mockImplementation((p) => p === mockCwd || p === absolutePath);
58
+ vi.mocked(fs.realpathSync).mockImplementation((p) => p.toString());
59
+ workspaceContext = new WorkspaceContext(mockCwd, [absolutePath]);
60
+ const directories = workspaceContext.getDirectories();
61
+ expect(directories).toContain(absolutePath);
62
+ });
63
+ it('should reject non-existent directories', () => {
64
+ expect(() => {
65
+ new WorkspaceContext(mockCwd, [mockNonExistentDir]);
66
+ }).toThrow('Directory does not exist');
67
+ });
68
+ it('should handle empty initialization', () => {
69
+ workspaceContext = new WorkspaceContext(mockCwd, []);
70
+ const directories = workspaceContext.getDirectories();
71
+ expect(directories).toHaveLength(1);
72
+ expect(directories[0]).toBe(mockCwd);
73
+ });
74
+ });
75
+ describe('adding directories', () => {
76
+ beforeEach(() => {
77
+ workspaceContext = new WorkspaceContext(mockCwd);
78
+ });
79
+ it('should add valid directories', () => {
80
+ workspaceContext.addDirectory(mockExistingDir);
81
+ const directories = workspaceContext.getDirectories();
82
+ expect(directories).toHaveLength(2);
83
+ expect(directories).toContain(mockExistingDir);
84
+ });
85
+ it('should resolve relative paths to absolute', () => {
86
+ // Since we can't mock path.resolve, we'll test with absolute paths
87
+ workspaceContext.addDirectory(mockExistingDir);
88
+ const directories = workspaceContext.getDirectories();
89
+ expect(directories).toContain(mockExistingDir);
90
+ });
91
+ it('should reject non-existent directories', () => {
92
+ expect(() => {
93
+ workspaceContext.addDirectory(mockNonExistentDir);
94
+ }).toThrow('Directory does not exist');
95
+ });
96
+ it('should prevent duplicate directories', () => {
97
+ workspaceContext.addDirectory(mockExistingDir);
98
+ workspaceContext.addDirectory(mockExistingDir);
99
+ const directories = workspaceContext.getDirectories();
100
+ expect(directories.filter((d) => d === mockExistingDir)).toHaveLength(1);
101
+ });
102
+ it('should handle symbolic links correctly', () => {
103
+ workspaceContext.addDirectory(mockSymlinkDir);
104
+ const directories = workspaceContext.getDirectories();
105
+ expect(directories).toContain(mockRealPath);
106
+ expect(directories).not.toContain(mockSymlinkDir);
107
+ });
108
+ });
109
+ describe('path validation', () => {
110
+ beforeEach(() => {
111
+ workspaceContext = new WorkspaceContext(mockCwd, [mockExistingDir]);
112
+ });
113
+ it('should accept paths within workspace directories', () => {
114
+ const validPath1 = path.join(mockCwd, 'src', 'file.ts');
115
+ const validPath2 = path.join(mockExistingDir, 'lib', 'module.js');
116
+ expect(workspaceContext.isPathWithinWorkspace(validPath1)).toBe(true);
117
+ expect(workspaceContext.isPathWithinWorkspace(validPath2)).toBe(true);
118
+ });
119
+ it('should reject paths outside workspace', () => {
120
+ const invalidPath = path.resolve(path.dirname(mockCwd), 'outside-workspace', 'file.txt');
121
+ expect(workspaceContext.isPathWithinWorkspace(invalidPath)).toBe(false);
122
+ });
123
+ it('should resolve symbolic links before validation', () => {
124
+ const symlinkPath = path.join(mockCwd, 'symlink-file');
125
+ const realPath = path.join(mockCwd, 'real-file');
126
+ vi.mocked(fs.existsSync).mockReturnValue(true);
127
+ vi.mocked(fs.realpathSync).mockImplementation((p) => {
128
+ if (p === symlinkPath) {
129
+ return realPath;
130
+ }
131
+ return p.toString();
132
+ });
133
+ expect(workspaceContext.isPathWithinWorkspace(symlinkPath)).toBe(true);
134
+ });
135
+ it('should handle nested directories correctly', () => {
136
+ const nestedPath = path.join(mockCwd, 'deeply', 'nested', 'path', 'file.txt');
137
+ expect(workspaceContext.isPathWithinWorkspace(nestedPath)).toBe(true);
138
+ });
139
+ it('should handle edge cases (root, parent references)', () => {
140
+ const rootPath = '/';
141
+ const parentPath = path.dirname(mockCwd);
142
+ expect(workspaceContext.isPathWithinWorkspace(rootPath)).toBe(false);
143
+ expect(workspaceContext.isPathWithinWorkspace(parentPath)).toBe(false);
144
+ });
145
+ it('should handle non-existent paths correctly', () => {
146
+ const nonExistentPath = path.join(mockCwd, 'does-not-exist.txt');
147
+ vi.mocked(fs.existsSync).mockImplementation((p) => p !== nonExistentPath);
148
+ // Should still validate based on path structure
149
+ expect(workspaceContext.isPathWithinWorkspace(nonExistentPath)).toBe(true);
150
+ });
151
+ });
152
+ describe('getDirectories', () => {
153
+ it('should return a copy of directories array', () => {
154
+ workspaceContext = new WorkspaceContext(mockCwd);
155
+ const dirs1 = workspaceContext.getDirectories();
156
+ const dirs2 = workspaceContext.getDirectories();
157
+ expect(dirs1).not.toBe(dirs2); // Different array instances
158
+ expect(dirs1).toEqual(dirs2); // Same content
159
+ });
160
+ });
161
+ describe('symbolic link security', () => {
162
+ beforeEach(() => {
163
+ workspaceContext = new WorkspaceContext(mockCwd);
164
+ });
165
+ it('should follow symlinks but validate resolved path', () => {
166
+ const symlinkInsideWorkspace = path.join(mockCwd, 'link-to-subdir');
167
+ const resolvedInsideWorkspace = path.join(mockCwd, 'subdir');
168
+ vi.mocked(fs.existsSync).mockReturnValue(true);
169
+ vi.mocked(fs.realpathSync).mockImplementation((p) => {
170
+ if (p === symlinkInsideWorkspace) {
171
+ return resolvedInsideWorkspace;
172
+ }
173
+ return p.toString();
174
+ });
175
+ expect(workspaceContext.isPathWithinWorkspace(symlinkInsideWorkspace)).toBe(true);
176
+ });
177
+ it('should prevent sandbox escape via symlinks', () => {
178
+ const symlinkEscape = path.join(mockCwd, 'escape-link');
179
+ const resolvedOutside = path.resolve(mockCwd, '..', 'outside-file');
180
+ vi.mocked(fs.existsSync).mockImplementation((p) => {
181
+ const pathStr = p.toString();
182
+ return (pathStr === symlinkEscape ||
183
+ pathStr === resolvedOutside ||
184
+ pathStr === mockCwd);
185
+ });
186
+ vi.mocked(fs.realpathSync).mockImplementation((p) => {
187
+ if (p.toString() === symlinkEscape) {
188
+ return resolvedOutside;
189
+ }
190
+ return p.toString();
191
+ });
192
+ vi.mocked(fs.statSync).mockImplementation((p) => ({
193
+ isDirectory: () => p.toString() !== resolvedOutside,
194
+ }));
195
+ workspaceContext = new WorkspaceContext(mockCwd);
196
+ expect(workspaceContext.isPathWithinWorkspace(symlinkEscape)).toBe(false);
197
+ });
198
+ it('should handle circular symlinks', () => {
199
+ const circularLink = path.join(mockCwd, 'circular');
200
+ vi.mocked(fs.existsSync).mockReturnValue(true);
201
+ vi.mocked(fs.realpathSync).mockImplementation(() => {
202
+ throw new Error('ELOOP: too many symbolic links encountered');
203
+ });
204
+ // Should handle the error gracefully
205
+ expect(workspaceContext.isPathWithinWorkspace(circularLink)).toBe(false);
206
+ });
207
+ });
208
+ });
209
+ //# sourceMappingURL=workspaceContext.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaceContext.test.js","sourceRoot":"","sources":["../../../src/utils/workspaceContext.test.ts"],"names":[],"mappings":"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"}