@google/gemini-cli-core 0.5.0-preview.1 → 0.7.0-nightly.20250912.68035591

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 (231) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +12 -2
  3. package/dist/google-gemini-cli-core-0.6.0-nightly.tgz +0 -0
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/src/config/config.d.ts +24 -1
  8. package/dist/src/config/config.js +58 -15
  9. package/dist/src/config/config.js.map +1 -1
  10. package/dist/src/config/config.test.js +11 -15
  11. package/dist/src/config/config.test.js.map +1 -1
  12. package/dist/src/config/models.d.ts +14 -0
  13. package/dist/src/config/models.js +26 -0
  14. package/dist/src/config/models.js.map +1 -1
  15. package/dist/src/config/models.test.d.ts +6 -0
  16. package/dist/src/config/models.test.js +55 -0
  17. package/dist/src/config/models.test.js.map +1 -0
  18. package/dist/src/confirmation-bus/index.d.ts +7 -0
  19. package/dist/src/confirmation-bus/index.js +8 -0
  20. package/dist/src/confirmation-bus/index.js.map +1 -0
  21. package/dist/src/confirmation-bus/message-bus.d.ts +17 -0
  22. package/dist/src/confirmation-bus/message-bus.js +81 -0
  23. package/dist/src/confirmation-bus/message-bus.js.map +1 -0
  24. package/dist/src/confirmation-bus/message-bus.test.d.ts +6 -0
  25. package/dist/src/confirmation-bus/message-bus.test.js +164 -0
  26. package/dist/src/confirmation-bus/message-bus.test.js.map +1 -0
  27. package/dist/src/confirmation-bus/types.d.ts +38 -0
  28. package/dist/src/confirmation-bus/types.js +15 -0
  29. package/dist/src/confirmation-bus/types.js.map +1 -0
  30. package/dist/src/core/client.d.ts +4 -1
  31. package/dist/src/core/client.js +46 -18
  32. package/dist/src/core/client.js.map +1 -1
  33. package/dist/src/core/client.test.js +156 -46
  34. package/dist/src/core/client.test.js.map +1 -1
  35. package/dist/src/core/contentGenerator.d.ts +0 -1
  36. package/dist/src/core/contentGenerator.js +0 -4
  37. package/dist/src/core/contentGenerator.js.map +1 -1
  38. package/dist/src/core/contentGenerator.test.js +0 -3
  39. package/dist/src/core/contentGenerator.test.js.map +1 -1
  40. package/dist/src/core/coreToolScheduler.d.ts +4 -3
  41. package/dist/src/core/coreToolScheduler.js +42 -5
  42. package/dist/src/core/coreToolScheduler.js.map +1 -1
  43. package/dist/src/core/coreToolScheduler.test.js +34 -0
  44. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  45. package/dist/src/core/geminiChat.d.ts +1 -22
  46. package/dist/src/core/geminiChat.js +15 -135
  47. package/dist/src/core/geminiChat.js.map +1 -1
  48. package/dist/src/core/geminiChat.test.js +59 -312
  49. package/dist/src/core/geminiChat.test.js.map +1 -1
  50. package/dist/src/core/nonInteractiveToolExecutor.test.js +48 -0
  51. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  52. package/dist/src/core/subagent.js +1 -1
  53. package/dist/src/core/subagent.js.map +1 -1
  54. package/dist/src/core/subagent.test.js +9 -8
  55. package/dist/src/core/subagent.test.js.map +1 -1
  56. package/dist/src/core/turn.d.ts +2 -1
  57. package/dist/src/core/turn.js +2 -2
  58. package/dist/src/core/turn.js.map +1 -1
  59. package/dist/src/core/turn.test.js +18 -18
  60. package/dist/src/core/turn.test.js.map +1 -1
  61. package/dist/src/generated/git-commit.d.ts +2 -2
  62. package/dist/src/generated/git-commit.js +2 -2
  63. package/dist/src/generated/git-commit.js.map +1 -1
  64. package/dist/src/ide/ide-client.d.ts +27 -0
  65. package/dist/src/ide/ide-client.js +85 -5
  66. package/dist/src/ide/ide-client.js.map +1 -1
  67. package/dist/src/ide/ide-client.test.js +53 -0
  68. package/dist/src/ide/ide-client.test.js.map +1 -1
  69. package/dist/src/ide/ideContext.d.ts +34 -20
  70. package/dist/src/ide/ideContext.js +20 -33
  71. package/dist/src/ide/ideContext.js.map +1 -1
  72. package/dist/src/ide/ideContext.test.js +37 -39
  73. package/dist/src/ide/ideContext.test.js.map +1 -1
  74. package/dist/src/index.d.ts +3 -1
  75. package/dist/src/index.js +3 -1
  76. package/dist/src/index.js.map +1 -1
  77. package/dist/src/output/json-formatter.d.ts +11 -0
  78. package/dist/src/output/json-formatter.js +30 -0
  79. package/dist/src/output/json-formatter.js.map +1 -0
  80. package/dist/src/output/json-formatter.test.d.ts +6 -0
  81. package/dist/src/output/json-formatter.test.js +266 -0
  82. package/dist/src/output/json-formatter.test.js.map +1 -0
  83. package/dist/src/output/types.d.ts +20 -0
  84. package/dist/src/output/types.js +11 -0
  85. package/dist/src/output/types.js.map +1 -0
  86. package/dist/src/policy/index.d.ts +7 -0
  87. package/dist/src/policy/index.js +8 -0
  88. package/dist/src/policy/index.js.map +1 -0
  89. package/dist/src/policy/policy-engine.d.ts +30 -0
  90. package/dist/src/policy/policy-engine.js +83 -0
  91. package/dist/src/policy/policy-engine.js.map +1 -0
  92. package/dist/src/policy/policy-engine.test.d.ts +6 -0
  93. package/dist/src/policy/policy-engine.test.js +470 -0
  94. package/dist/src/policy/policy-engine.test.js.map +1 -0
  95. package/dist/src/policy/stable-stringify.d.ts +58 -0
  96. package/dist/src/policy/stable-stringify.js +122 -0
  97. package/dist/src/policy/stable-stringify.js.map +1 -0
  98. package/dist/src/policy/types.d.ts +47 -0
  99. package/dist/src/policy/types.js +12 -0
  100. package/dist/src/policy/types.js.map +1 -0
  101. package/dist/src/routing/modelRouterService.d.ts +23 -0
  102. package/dist/src/routing/modelRouterService.js +36 -0
  103. package/dist/src/routing/modelRouterService.js.map +1 -0
  104. package/dist/src/routing/modelRouterService.test.d.ts +6 -0
  105. package/dist/src/routing/modelRouterService.test.js +72 -0
  106. package/dist/src/routing/modelRouterService.test.js.map +1 -0
  107. package/dist/src/routing/routingStrategy.d.ts +62 -0
  108. package/dist/src/routing/routingStrategy.js +7 -0
  109. package/dist/src/routing/routingStrategy.js.map +1 -0
  110. package/dist/src/routing/strategies/compositeStrategy.d.ts +26 -0
  111. package/dist/src/routing/strategies/compositeStrategy.js +67 -0
  112. package/dist/src/routing/strategies/compositeStrategy.js.map +1 -0
  113. package/dist/src/routing/strategies/compositeStrategy.test.d.ts +6 -0
  114. package/dist/src/routing/strategies/compositeStrategy.test.js +123 -0
  115. package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -0
  116. package/dist/src/routing/strategies/defaultStrategy.d.ts +12 -0
  117. package/dist/src/routing/strategies/defaultStrategy.js +20 -0
  118. package/dist/src/routing/strategies/defaultStrategy.js.map +1 -0
  119. package/dist/src/routing/strategies/defaultStrategy.test.d.ts +6 -0
  120. package/dist/src/routing/strategies/defaultStrategy.test.js +26 -0
  121. package/dist/src/routing/strategies/defaultStrategy.test.js.map +1 -0
  122. package/dist/src/routing/strategies/fallbackStrategy.d.ts +12 -0
  123. package/dist/src/routing/strategies/fallbackStrategy.js +25 -0
  124. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -0
  125. package/dist/src/routing/strategies/fallbackStrategy.test.d.ts +6 -0
  126. package/dist/src/routing/strategies/fallbackStrategy.test.js +55 -0
  127. package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -0
  128. package/dist/src/routing/strategies/overrideStrategy.d.ts +15 -0
  129. package/dist/src/routing/strategies/overrideStrategy.js +27 -0
  130. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -0
  131. package/dist/src/routing/strategies/overrideStrategy.test.d.ts +6 -0
  132. package/dist/src/routing/strategies/overrideStrategy.test.js +41 -0
  133. package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -0
  134. package/dist/src/services/fileDiscoveryService.d.ts +10 -0
  135. package/dist/src/services/fileDiscoveryService.js +31 -17
  136. package/dist/src/services/fileDiscoveryService.js.map +1 -1
  137. package/dist/src/services/loopDetectionService.d.ts +5 -0
  138. package/dist/src/services/loopDetectionService.js +13 -2
  139. package/dist/src/services/loopDetectionService.js.map +1 -1
  140. package/dist/src/services/loopDetectionService.test.js +15 -0
  141. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  142. package/dist/src/services/shellExecutionService.d.ts +34 -2
  143. package/dist/src/services/shellExecutionService.js +177 -43
  144. package/dist/src/services/shellExecutionService.js.map +1 -1
  145. package/dist/src/services/shellExecutionService.test.js +153 -56
  146. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  147. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +4 -2
  148. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +31 -4
  149. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  150. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +6 -2
  151. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +14 -2
  152. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  153. package/dist/src/telemetry/index.d.ts +2 -2
  154. package/dist/src/telemetry/index.js +2 -2
  155. package/dist/src/telemetry/index.js.map +1 -1
  156. package/dist/src/telemetry/loggers.d.ts +2 -1
  157. package/dist/src/telemetry/loggers.js +20 -5
  158. package/dist/src/telemetry/loggers.js.map +1 -1
  159. package/dist/src/telemetry/loggers.test.js +50 -35
  160. package/dist/src/telemetry/loggers.test.js.map +1 -1
  161. package/dist/src/telemetry/metrics.d.ts +1 -1
  162. package/dist/src/telemetry/metrics.js +2 -2
  163. package/dist/src/telemetry/metrics.js.map +1 -1
  164. package/dist/src/telemetry/types.d.ts +23 -3
  165. package/dist/src/telemetry/types.js +25 -3
  166. package/dist/src/telemetry/types.js.map +1 -1
  167. package/dist/src/tools/edit.js +2 -3
  168. package/dist/src/tools/edit.js.map +1 -1
  169. package/dist/src/tools/edit.test.js +2 -8
  170. package/dist/src/tools/edit.test.js.map +1 -1
  171. package/dist/src/tools/glob.d.ts +5 -1
  172. package/dist/src/tools/glob.js +24 -17
  173. package/dist/src/tools/glob.js.map +1 -1
  174. package/dist/src/tools/glob.test.js +51 -0
  175. package/dist/src/tools/glob.test.js.map +1 -1
  176. package/dist/src/tools/ls.js +19 -32
  177. package/dist/src/tools/ls.js.map +1 -1
  178. package/dist/src/tools/ls.test.js +140 -280
  179. package/dist/src/tools/ls.test.js.map +1 -1
  180. package/dist/src/tools/read-many-files.d.ts +1 -1
  181. package/dist/src/tools/read-many-files.js +17 -49
  182. package/dist/src/tools/read-many-files.js.map +1 -1
  183. package/dist/src/tools/ripGrep.d.ts +4 -0
  184. package/dist/src/tools/ripGrep.js +11 -1
  185. package/dist/src/tools/ripGrep.js.map +1 -1
  186. package/dist/src/tools/ripGrep.test.js +51 -1
  187. package/dist/src/tools/ripGrep.test.js.map +1 -1
  188. package/dist/src/tools/shell.d.ts +12 -2
  189. package/dist/src/tools/shell.js +12 -16
  190. package/dist/src/tools/shell.js.map +1 -1
  191. package/dist/src/tools/shell.test.js +2 -33
  192. package/dist/src/tools/shell.test.js.map +1 -1
  193. package/dist/src/tools/smart-edit.js +2 -3
  194. package/dist/src/tools/smart-edit.js.map +1 -1
  195. package/dist/src/tools/smart-edit.test.js +2 -8
  196. package/dist/src/tools/smart-edit.test.js.map +1 -1
  197. package/dist/src/tools/tools.d.ts +6 -4
  198. package/dist/src/tools/tools.js +2 -2
  199. package/dist/src/tools/tools.js.map +1 -1
  200. package/dist/src/tools/write-file.js +2 -3
  201. package/dist/src/tools/write-file.js.map +1 -1
  202. package/dist/src/tools/write-file.test.js +78 -0
  203. package/dist/src/tools/write-file.test.js.map +1 -1
  204. package/dist/src/utils/bfsFileSearch.js +11 -5
  205. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  206. package/dist/src/utils/errors.d.ts +6 -0
  207. package/dist/src/utils/errors.js +10 -0
  208. package/dist/src/utils/errors.js.map +1 -1
  209. package/dist/src/utils/geminiIgnoreParser.d.ts +18 -0
  210. package/dist/src/utils/geminiIgnoreParser.js +61 -0
  211. package/dist/src/utils/geminiIgnoreParser.js.map +1 -0
  212. package/dist/src/utils/geminiIgnoreParser.test.d.ts +6 -0
  213. package/dist/src/utils/geminiIgnoreParser.test.js +50 -0
  214. package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -0
  215. package/dist/src/utils/gitIgnoreParser.d.ts +3 -9
  216. package/dist/src/utils/gitIgnoreParser.js +60 -69
  217. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  218. package/dist/src/utils/gitIgnoreParser.test.js +18 -53
  219. package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
  220. package/dist/src/utils/terminalSerializer.d.ts +28 -0
  221. package/dist/src/utils/terminalSerializer.js +432 -0
  222. package/dist/src/utils/terminalSerializer.js.map +1 -0
  223. package/dist/src/utils/terminalSerializer.test.d.ts +6 -0
  224. package/dist/src/utils/terminalSerializer.test.js +176 -0
  225. package/dist/src/utils/terminalSerializer.test.js.map +1 -0
  226. package/dist/tsconfig.tsbuildinfo +1 -1
  227. package/package.json +1 -1
  228. package/dist/google-gemini-cli-core-0.5.0-preview.tgz +0 -0
  229. package/dist/src/utils/ide-trust.d.ts +0 -10
  230. package/dist/src/utils/ide-trust.js +0 -14
  231. package/dist/src/utils/ide-trust.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/tools/ls.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/tools/ls.ts"],"names":[],"mappings":"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"}
@@ -3,361 +3,234 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- /* eslint-disable @typescript-eslint/no-explicit-any */
7
- import { describe, it, expect, beforeEach, vi } from 'vitest';
8
- import fs from 'node:fs';
6
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
+ import fs from 'node:fs/promises';
9
8
  import path from 'node:path';
10
- vi.mock('fs', () => ({
11
- default: {
12
- statSync: vi.fn(),
13
- readdirSync: vi.fn(),
14
- },
15
- statSync: vi.fn(),
16
- readdirSync: vi.fn(),
17
- mkdirSync: vi.fn(),
18
- }));
9
+ import os from 'node:os';
19
10
  import { LSTool } from './ls.js';
11
+ import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
20
12
  import { ToolErrorType } from './tool-error.js';
13
+ import { createMockWorkspaceContext } from '../test-utils/mockWorkspaceContext.js';
21
14
  describe('LSTool', () => {
22
15
  let lsTool;
16
+ let tempRootDir;
17
+ let tempSecondaryDir;
23
18
  let mockConfig;
24
- let mockWorkspaceContext;
25
- let mockFileService;
26
- const mockPrimaryDir = '/home/user/project';
27
- const mockSecondaryDir = '/home/user/other-project';
28
- beforeEach(() => {
29
- vi.resetAllMocks();
30
- // Mock WorkspaceContext
31
- mockWorkspaceContext = {
32
- getDirectories: vi
33
- .fn()
34
- .mockReturnValue([mockPrimaryDir, mockSecondaryDir]),
35
- isPathWithinWorkspace: vi
36
- .fn()
37
- .mockImplementation((path) => path.startsWith(mockPrimaryDir) ||
38
- path.startsWith(mockSecondaryDir)),
39
- addDirectory: vi.fn(),
40
- };
41
- // Mock FileService
42
- mockFileService = {
43
- shouldGitIgnoreFile: vi.fn().mockReturnValue(false),
44
- shouldGeminiIgnoreFile: vi.fn().mockReturnValue(false),
45
- };
46
- // Mock Config
19
+ const abortSignal = new AbortController().signal;
20
+ beforeEach(async () => {
21
+ tempRootDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ls-tool-root-'));
22
+ tempSecondaryDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ls-tool-secondary-'));
23
+ const mockWorkspaceContext = createMockWorkspaceContext(tempRootDir, [
24
+ tempSecondaryDir,
25
+ ]);
47
26
  mockConfig = {
48
- getTargetDir: vi.fn().mockReturnValue(mockPrimaryDir),
49
- getWorkspaceContext: vi.fn().mockReturnValue(mockWorkspaceContext),
50
- getFileService: vi.fn().mockReturnValue(mockFileService),
51
- getFileFilteringOptions: vi.fn().mockReturnValue({
27
+ getTargetDir: () => tempRootDir,
28
+ getWorkspaceContext: () => mockWorkspaceContext,
29
+ getFileService: () => new FileDiscoveryService(tempRootDir),
30
+ getFileFilteringOptions: () => ({
52
31
  respectGitIgnore: true,
53
32
  respectGeminiIgnore: true,
54
33
  }),
55
34
  };
56
35
  lsTool = new LSTool(mockConfig);
57
36
  });
37
+ afterEach(async () => {
38
+ await fs.rm(tempRootDir, { recursive: true, force: true });
39
+ await fs.rm(tempSecondaryDir, { recursive: true, force: true });
40
+ });
58
41
  describe('parameter validation', () => {
59
- it('should accept valid absolute paths within workspace', () => {
60
- const params = {
61
- path: '/home/user/project/src',
62
- };
63
- vi.mocked(fs.statSync).mockReturnValue({
64
- isDirectory: () => true,
65
- });
66
- const invocation = lsTool.build(params);
42
+ it('should accept valid absolute paths within workspace', async () => {
43
+ const testPath = path.join(tempRootDir, 'src');
44
+ await fs.mkdir(testPath);
45
+ const invocation = lsTool.build({ path: testPath });
67
46
  expect(invocation).toBeDefined();
68
47
  });
69
48
  it('should reject relative paths', () => {
70
- const params = {
71
- path: './src',
72
- };
73
- expect(() => lsTool.build(params)).toThrow('Path must be absolute: ./src');
49
+ expect(() => lsTool.build({ path: './src' })).toThrow('Path must be absolute: ./src');
74
50
  });
75
51
  it('should reject paths outside workspace with clear error message', () => {
76
- const params = {
77
- path: '/etc/passwd',
78
- };
79
- expect(() => lsTool.build(params)).toThrow('Path must be within one of the workspace directories: /home/user/project, /home/user/other-project');
52
+ expect(() => lsTool.build({ path: '/etc/passwd' })).toThrow(`Path must be within one of the workspace directories: ${tempRootDir}, ${tempSecondaryDir}`);
80
53
  });
81
- it('should accept paths in secondary workspace directory', () => {
82
- const params = {
83
- path: '/home/user/other-project/lib',
84
- };
85
- vi.mocked(fs.statSync).mockReturnValue({
86
- isDirectory: () => true,
87
- });
88
- const invocation = lsTool.build(params);
54
+ it('should accept paths in secondary workspace directory', async () => {
55
+ const testPath = path.join(tempSecondaryDir, 'lib');
56
+ await fs.mkdir(testPath);
57
+ const invocation = lsTool.build({ path: testPath });
89
58
  expect(invocation).toBeDefined();
90
59
  });
91
60
  });
92
61
  describe('execute', () => {
93
62
  it('should list files in a directory', async () => {
94
- const testPath = '/home/user/project/src';
95
- const mockFiles = ['file1.ts', 'file2.ts', 'subdir'];
96
- const mockStats = {
97
- isDirectory: vi.fn(),
98
- mtime: new Date(),
99
- size: 1024,
100
- };
101
- vi.mocked(fs.statSync).mockImplementation((path) => {
102
- const pathStr = path.toString();
103
- if (pathStr === testPath) {
104
- return { isDirectory: () => true };
105
- }
106
- // For individual files
107
- if (pathStr.toString().endsWith('subdir')) {
108
- return { ...mockStats, isDirectory: () => true, size: 0 };
109
- }
110
- return { ...mockStats, isDirectory: () => false };
111
- });
112
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
113
- const invocation = lsTool.build({ path: testPath });
114
- const result = await invocation.execute(new AbortController().signal);
63
+ await fs.writeFile(path.join(tempRootDir, 'file1.txt'), 'content1');
64
+ await fs.mkdir(path.join(tempRootDir, 'subdir'));
65
+ await fs.writeFile(path.join(tempSecondaryDir, 'secondary-file.txt'), 'secondary');
66
+ const invocation = lsTool.build({ path: tempRootDir });
67
+ const result = await invocation.execute(abortSignal);
115
68
  expect(result.llmContent).toContain('[DIR] subdir');
116
- expect(result.llmContent).toContain('file1.ts');
117
- expect(result.llmContent).toContain('file2.ts');
118
- expect(result.returnDisplay).toBe('Listed 3 item(s).');
69
+ expect(result.llmContent).toContain('file1.txt');
70
+ expect(result.returnDisplay).toBe('Listed 2 item(s).');
119
71
  });
120
72
  it('should list files from secondary workspace directory', async () => {
121
- const testPath = '/home/user/other-project/lib';
122
- const mockFiles = ['module1.js', 'module2.js'];
123
- vi.mocked(fs.statSync).mockImplementation((path) => {
124
- if (path.toString() === testPath) {
125
- return { isDirectory: () => true };
126
- }
127
- return {
128
- isDirectory: () => false,
129
- mtime: new Date(),
130
- size: 2048,
131
- };
132
- });
133
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
134
- const invocation = lsTool.build({ path: testPath });
135
- const result = await invocation.execute(new AbortController().signal);
136
- expect(result.llmContent).toContain('module1.js');
137
- expect(result.llmContent).toContain('module2.js');
138
- expect(result.returnDisplay).toBe('Listed 2 item(s).');
73
+ await fs.writeFile(path.join(tempRootDir, 'file1.txt'), 'content1');
74
+ await fs.mkdir(path.join(tempRootDir, 'subdir'));
75
+ await fs.writeFile(path.join(tempSecondaryDir, 'secondary-file.txt'), 'secondary');
76
+ const invocation = lsTool.build({ path: tempSecondaryDir });
77
+ const result = await invocation.execute(abortSignal);
78
+ expect(result.llmContent).toContain('secondary-file.txt');
79
+ expect(result.returnDisplay).toBe('Listed 1 item(s).');
139
80
  });
140
81
  it('should handle empty directories', async () => {
141
- const testPath = '/home/user/project/empty';
142
- vi.mocked(fs.statSync).mockReturnValue({
143
- isDirectory: () => true,
144
- });
145
- vi.mocked(fs.readdirSync).mockReturnValue([]);
146
- const invocation = lsTool.build({ path: testPath });
147
- const result = await invocation.execute(new AbortController().signal);
148
- expect(result.llmContent).toBe('Directory /home/user/project/empty is empty.');
82
+ const emptyDir = path.join(tempRootDir, 'empty');
83
+ await fs.mkdir(emptyDir);
84
+ const invocation = lsTool.build({ path: emptyDir });
85
+ const result = await invocation.execute(abortSignal);
86
+ expect(result.llmContent).toBe(`Directory ${emptyDir} is empty.`);
149
87
  expect(result.returnDisplay).toBe('Directory is empty.');
150
88
  });
151
89
  it('should respect ignore patterns', async () => {
152
- const testPath = '/home/user/project/src';
153
- const mockFiles = ['test.js', 'test.spec.js', 'index.js'];
154
- vi.mocked(fs.statSync).mockImplementation((path) => {
155
- const pathStr = path.toString();
156
- if (pathStr === testPath) {
157
- return { isDirectory: () => true };
158
- }
159
- return {
160
- isDirectory: () => false,
161
- mtime: new Date(),
162
- size: 1024,
163
- };
164
- });
165
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
90
+ await fs.writeFile(path.join(tempRootDir, 'file1.txt'), 'content1');
91
+ await fs.writeFile(path.join(tempRootDir, 'file2.log'), 'content1');
166
92
  const invocation = lsTool.build({
167
- path: testPath,
168
- ignore: ['*.spec.js'],
93
+ path: tempRootDir,
94
+ ignore: ['*.log'],
169
95
  });
170
- const result = await invocation.execute(new AbortController().signal);
171
- expect(result.llmContent).toContain('test.js');
172
- expect(result.llmContent).toContain('index.js');
173
- expect(result.llmContent).not.toContain('test.spec.js');
174
- expect(result.returnDisplay).toBe('Listed 2 item(s).');
96
+ const result = await invocation.execute(abortSignal);
97
+ expect(result.llmContent).toContain('file1.txt');
98
+ expect(result.llmContent).not.toContain('file2.log');
99
+ expect(result.returnDisplay).toBe('Listed 1 item(s).');
175
100
  });
176
101
  it('should respect gitignore patterns', async () => {
177
- const testPath = '/home/user/project/src';
178
- const mockFiles = ['file1.js', 'file2.js', 'ignored.js'];
179
- vi.mocked(fs.statSync).mockImplementation((path) => {
180
- const pathStr = path.toString();
181
- if (pathStr === testPath) {
182
- return { isDirectory: () => true };
183
- }
184
- return {
185
- isDirectory: () => false,
186
- mtime: new Date(),
187
- size: 1024,
188
- };
189
- });
190
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
191
- mockFileService.shouldGitIgnoreFile.mockImplementation((path) => path.includes('ignored.js'));
192
- const invocation = lsTool.build({ path: testPath });
193
- const result = await invocation.execute(new AbortController().signal);
194
- expect(result.llmContent).toContain('file1.js');
195
- expect(result.llmContent).toContain('file2.js');
196
- expect(result.llmContent).not.toContain('ignored.js');
197
- expect(result.returnDisplay).toBe('Listed 2 item(s). (1 git-ignored)');
102
+ await fs.writeFile(path.join(tempRootDir, 'file1.txt'), 'content1');
103
+ await fs.writeFile(path.join(tempRootDir, 'file2.log'), 'content1');
104
+ await fs.writeFile(path.join(tempRootDir, '.git'), '');
105
+ await fs.writeFile(path.join(tempRootDir, '.gitignore'), '*.log');
106
+ const invocation = lsTool.build({ path: tempRootDir });
107
+ const result = await invocation.execute(abortSignal);
108
+ expect(result.llmContent).toContain('file1.txt');
109
+ expect(result.llmContent).not.toContain('file2.log');
110
+ // .git is always ignored by default.
111
+ expect(result.returnDisplay).toBe('Listed 2 item(s). (2 git-ignored)');
198
112
  });
199
113
  it('should respect geminiignore patterns', async () => {
200
- const testPath = '/home/user/project/src';
201
- const mockFiles = ['file1.js', 'file2.js', 'private.js'];
202
- vi.mocked(fs.statSync).mockImplementation((path) => {
203
- const pathStr = path.toString();
204
- if (pathStr === testPath) {
205
- return { isDirectory: () => true };
206
- }
207
- return {
208
- isDirectory: () => false,
209
- mtime: new Date(),
210
- size: 1024,
211
- };
212
- });
213
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
214
- mockFileService.shouldGeminiIgnoreFile.mockImplementation((path) => path.includes('private.js'));
215
- const invocation = lsTool.build({ path: testPath });
216
- const result = await invocation.execute(new AbortController().signal);
217
- expect(result.llmContent).toContain('file1.js');
218
- expect(result.llmContent).toContain('file2.js');
219
- expect(result.llmContent).not.toContain('private.js');
114
+ await fs.writeFile(path.join(tempRootDir, 'file1.txt'), 'content1');
115
+ await fs.writeFile(path.join(tempRootDir, 'file2.log'), 'content1');
116
+ await fs.writeFile(path.join(tempRootDir, '.geminiignore'), '*.log');
117
+ const invocation = lsTool.build({ path: tempRootDir });
118
+ const result = await invocation.execute(abortSignal);
119
+ expect(result.llmContent).toContain('file1.txt');
120
+ expect(result.llmContent).not.toContain('file2.log');
220
121
  expect(result.returnDisplay).toBe('Listed 2 item(s). (1 gemini-ignored)');
221
122
  });
222
123
  it('should handle non-directory paths', async () => {
223
- const testPath = '/home/user/project/file.txt';
224
- vi.mocked(fs.statSync).mockReturnValue({
225
- isDirectory: () => false,
226
- });
124
+ const testPath = path.join(tempRootDir, 'file1.txt');
125
+ await fs.writeFile(testPath, 'content1');
227
126
  const invocation = lsTool.build({ path: testPath });
228
- const result = await invocation.execute(new AbortController().signal);
127
+ const result = await invocation.execute(abortSignal);
229
128
  expect(result.llmContent).toContain('Path is not a directory');
230
129
  expect(result.returnDisplay).toBe('Error: Path is not a directory.');
231
130
  expect(result.error?.type).toBe(ToolErrorType.PATH_IS_NOT_A_DIRECTORY);
232
131
  });
233
132
  it('should handle non-existent paths', async () => {
234
- const testPath = '/home/user/project/does-not-exist';
235
- vi.mocked(fs.statSync).mockImplementation(() => {
236
- throw new Error('ENOENT: no such file or directory');
237
- });
133
+ const testPath = path.join(tempRootDir, 'does-not-exist');
238
134
  const invocation = lsTool.build({ path: testPath });
239
- const result = await invocation.execute(new AbortController().signal);
135
+ const result = await invocation.execute(abortSignal);
240
136
  expect(result.llmContent).toContain('Error listing directory');
241
137
  expect(result.returnDisplay).toBe('Error: Failed to list directory.');
242
138
  expect(result.error?.type).toBe(ToolErrorType.LS_EXECUTION_ERROR);
243
139
  });
244
140
  it('should sort directories first, then files alphabetically', async () => {
245
- const testPath = '/home/user/project/src';
246
- const mockFiles = ['z-file.ts', 'a-dir', 'b-file.ts', 'c-dir'];
247
- vi.mocked(fs.statSync).mockImplementation((path) => {
248
- if (path.toString() === testPath) {
249
- return { isDirectory: () => true };
250
- }
251
- if (path.toString().endsWith('-dir')) {
252
- return {
253
- isDirectory: () => true,
254
- mtime: new Date(),
255
- size: 0,
256
- };
257
- }
258
- return {
259
- isDirectory: () => false,
260
- mtime: new Date(),
261
- size: 1024,
262
- };
263
- });
264
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
265
- const invocation = lsTool.build({ path: testPath });
266
- const result = await invocation.execute(new AbortController().signal);
267
- const lines = (typeof result.llmContent === 'string' ? result.llmContent : '').split('\n');
268
- const entries = lines.slice(1).filter((line) => line.trim()); // Skip header
269
- expect(entries[0]).toBe('[DIR] a-dir');
270
- expect(entries[1]).toBe('[DIR] c-dir');
271
- expect(entries[2]).toBe('b-file.ts');
272
- expect(entries[3]).toBe('z-file.ts');
141
+ await fs.writeFile(path.join(tempRootDir, 'a-file.txt'), 'content1');
142
+ await fs.writeFile(path.join(tempRootDir, 'b-file.txt'), 'content1');
143
+ await fs.mkdir(path.join(tempRootDir, 'x-dir'));
144
+ await fs.mkdir(path.join(tempRootDir, 'y-dir'));
145
+ const invocation = lsTool.build({ path: tempRootDir });
146
+ const result = await invocation.execute(abortSignal);
147
+ const lines = (typeof result.llmContent === 'string' ? result.llmContent : '')
148
+ .split('\n')
149
+ .filter(Boolean);
150
+ const entries = lines.slice(1); // Skip header
151
+ expect(entries[0]).toBe('[DIR] x-dir');
152
+ expect(entries[1]).toBe('[DIR] y-dir');
153
+ expect(entries[2]).toBe('a-file.txt');
154
+ expect(entries[3]).toBe('b-file.txt');
273
155
  });
274
156
  it('should handle permission errors gracefully', async () => {
275
- const testPath = '/home/user/project/restricted';
276
- vi.mocked(fs.statSync).mockReturnValue({
277
- isDirectory: () => true,
278
- });
279
- vi.mocked(fs.readdirSync).mockImplementation(() => {
280
- throw new Error('EACCES: permission denied');
281
- });
282
- const invocation = lsTool.build({ path: testPath });
283
- const result = await invocation.execute(new AbortController().signal);
157
+ const restrictedDir = path.join(tempRootDir, 'restricted');
158
+ await fs.mkdir(restrictedDir);
159
+ // To simulate a permission error in a cross-platform way,
160
+ // we mock fs.readdir to throw an error.
161
+ const error = new Error('EACCES: permission denied');
162
+ vi.spyOn(fs, 'readdir').mockRejectedValueOnce(error);
163
+ const invocation = lsTool.build({ path: restrictedDir });
164
+ const result = await invocation.execute(abortSignal);
284
165
  expect(result.llmContent).toContain('Error listing directory');
285
166
  expect(result.llmContent).toContain('permission denied');
286
167
  expect(result.returnDisplay).toBe('Error: Failed to list directory.');
287
168
  expect(result.error?.type).toBe(ToolErrorType.LS_EXECUTION_ERROR);
288
169
  });
289
- it('should throw for invalid params at build time', async () => {
170
+ it('should throw for invalid params at build time', () => {
290
171
  expect(() => lsTool.build({ path: '../outside' })).toThrow('Path must be absolute: ../outside');
291
172
  });
292
173
  it('should handle errors accessing individual files during listing', async () => {
293
- const testPath = '/home/user/project/src';
294
- const mockFiles = ['accessible.ts', 'inaccessible.ts'];
295
- vi.mocked(fs.statSync).mockImplementation((path) => {
296
- if (path.toString() === testPath) {
297
- return { isDirectory: () => true };
174
+ await fs.writeFile(path.join(tempRootDir, 'file1.txt'), 'content1');
175
+ const problematicFile = path.join(tempRootDir, 'problematic.txt');
176
+ await fs.writeFile(problematicFile, 'content2');
177
+ // To simulate an error on a single file in a cross-platform way,
178
+ // we mock fs.stat to throw for a specific file. This avoids
179
+ // platform-specific behavior with things like dangling symlinks.
180
+ const originalStat = fs.stat;
181
+ const statSpy = vi.spyOn(fs, 'stat').mockImplementation(async (p) => {
182
+ if (p.toString() === problematicFile) {
183
+ throw new Error('Simulated stat error');
298
184
  }
299
- if (path.toString().endsWith('inaccessible.ts')) {
300
- throw new Error('EACCES: permission denied');
301
- }
302
- return {
303
- isDirectory: () => false,
304
- mtime: new Date(),
305
- size: 1024,
306
- };
185
+ return originalStat(p);
307
186
  });
308
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
309
187
  // Spy on console.error to verify it's called
310
188
  const consoleErrorSpy = vi
311
189
  .spyOn(console, 'error')
312
190
  .mockImplementation(() => { });
313
- const invocation = lsTool.build({ path: testPath });
314
- const result = await invocation.execute(new AbortController().signal);
315
- // Should still list the accessible file
316
- expect(result.llmContent).toContain('accessible.ts');
317
- expect(result.llmContent).not.toContain('inaccessible.ts');
191
+ const invocation = lsTool.build({ path: tempRootDir });
192
+ const result = await invocation.execute(abortSignal);
193
+ // Should still list the other files
194
+ expect(result.llmContent).toContain('file1.txt');
195
+ expect(result.llmContent).not.toContain('problematic.txt');
318
196
  expect(result.returnDisplay).toBe('Listed 1 item(s).');
319
197
  // Verify error was logged
320
- expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Error accessing'));
198
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringMatching(/Error accessing.*problematic\.txt/s));
199
+ statSpy.mockRestore();
321
200
  consoleErrorSpy.mockRestore();
322
201
  });
323
202
  });
324
203
  describe('getDescription', () => {
325
204
  it('should return shortened relative path', () => {
205
+ const deeplyNestedDir = path.join(tempRootDir, 'deeply', 'nested');
326
206
  const params = {
327
- path: `${mockPrimaryDir}/deeply/nested/directory`,
207
+ path: path.join(deeplyNestedDir, 'directory'),
328
208
  };
329
- vi.mocked(fs.statSync).mockReturnValue({
330
- isDirectory: () => true,
331
- });
332
209
  const invocation = lsTool.build(params);
333
210
  const description = invocation.getDescription();
334
211
  expect(description).toBe(path.join('deeply', 'nested', 'directory'));
335
212
  });
336
213
  it('should handle paths in secondary workspace', () => {
337
214
  const params = {
338
- path: `${mockSecondaryDir}/lib`,
215
+ path: path.join(tempSecondaryDir, 'lib'),
339
216
  };
340
- vi.mocked(fs.statSync).mockReturnValue({
341
- isDirectory: () => true,
342
- });
343
217
  const invocation = lsTool.build(params);
344
218
  const description = invocation.getDescription();
345
- expect(description).toBe(path.join('..', 'other-project', 'lib'));
219
+ const expected = path.relative(tempRootDir, params.path);
220
+ expect(description).toBe(expected);
346
221
  });
347
222
  });
348
223
  describe('workspace boundary validation', () => {
349
- it('should accept paths in primary workspace directory', () => {
350
- const params = { path: `${mockPrimaryDir}/src` };
351
- vi.mocked(fs.statSync).mockReturnValue({
352
- isDirectory: () => true,
353
- });
224
+ it('should accept paths in primary workspace directory', async () => {
225
+ const testPath = path.join(tempRootDir, 'src');
226
+ await fs.mkdir(testPath);
227
+ const params = { path: testPath };
354
228
  expect(lsTool.build(params)).toBeDefined();
355
229
  });
356
- it('should accept paths in secondary workspace directory', () => {
357
- const params = { path: `${mockSecondaryDir}/lib` };
358
- vi.mocked(fs.statSync).mockReturnValue({
359
- isDirectory: () => true,
360
- });
230
+ it('should accept paths in secondary workspace directory', async () => {
231
+ const testPath = path.join(tempSecondaryDir, 'lib');
232
+ await fs.mkdir(testPath);
233
+ const params = { path: testPath };
361
234
  expect(lsTool.build(params)).toBeDefined();
362
235
  });
363
236
  it('should reject paths outside all workspace directories', () => {
@@ -365,24 +238,11 @@ describe('LSTool', () => {
365
238
  expect(() => lsTool.build(params)).toThrow('Path must be within one of the workspace directories');
366
239
  });
367
240
  it('should list files from secondary workspace directory', async () => {
368
- const testPath = `${mockSecondaryDir}/tests`;
369
- const mockFiles = ['test1.spec.ts', 'test2.spec.ts'];
370
- vi.mocked(fs.statSync).mockImplementation((path) => {
371
- if (path.toString() === testPath) {
372
- return { isDirectory: () => true };
373
- }
374
- return {
375
- isDirectory: () => false,
376
- mtime: new Date(),
377
- size: 512,
378
- };
379
- });
380
- vi.mocked(fs.readdirSync).mockReturnValue(mockFiles);
381
- const invocation = lsTool.build({ path: testPath });
382
- const result = await invocation.execute(new AbortController().signal);
383
- expect(result.llmContent).toContain('test1.spec.ts');
384
- expect(result.llmContent).toContain('test2.spec.ts');
385
- expect(result.returnDisplay).toBe('Listed 2 item(s).');
241
+ await fs.writeFile(path.join(tempSecondaryDir, 'secondary-file.txt'), 'secondary');
242
+ const invocation = lsTool.build({ path: tempSecondaryDir });
243
+ const result = await invocation.execute(abortSignal);
244
+ expect(result.llmContent).toContain('secondary-file.txt');
245
+ expect(result.returnDisplay).toBe('Listed 1 item(s).');
386
246
  });
387
247
  });
388
248
  });