@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.
- package/README.md +32 -0
- package/dist/google-gemini-cli-core-0.1.15.tgz +0 -0
- package/dist/src/code_assist/converter.d.ts +2 -1
- package/dist/src/code_assist/converter.js +2 -1
- package/dist/src/code_assist/converter.js.map +1 -1
- package/dist/src/code_assist/converter.test.js +13 -10
- package/dist/src/code_assist/converter.test.js.map +1 -1
- package/dist/src/code_assist/server.d.ts +2 -2
- package/dist/src/code_assist/server.js +4 -4
- package/dist/src/code_assist/server.js.map +1 -1
- package/dist/src/code_assist/server.test.js +9 -9
- package/dist/src/code_assist/server.test.js.map +1 -1
- package/dist/src/code_assist/setup.js +1 -1
- package/dist/src/code_assist/setup.js.map +1 -1
- package/dist/src/code_assist/setup.test.js +2 -2
- package/dist/src/code_assist/setup.test.js.map +1 -1
- package/dist/src/config/config.d.ts +19 -7
- package/dist/src/config/config.js +37 -13
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +33 -0
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/flashFallback.test.js +23 -47
- package/dist/src/config/flashFallback.test.js.map +1 -1
- package/dist/src/config/models.d.ts +1 -0
- package/dist/src/config/models.js +1 -0
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/core/client.d.ts +3 -1
- package/dist/src/core/client.js +74 -23
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +167 -21
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.d.ts +2 -2
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +1 -3
- package/dist/src/core/coreToolScheduler.js +25 -16
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +76 -1
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +3 -2
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/geminiChat.test.js +2 -2
- package/dist/src/core/geminiChat.test.js.map +1 -1
- package/dist/src/core/logger.d.ts +1 -0
- package/dist/src/core/logger.js +22 -8
- package/dist/src/core/logger.js.map +1 -1
- package/dist/src/core/logger.test.js +60 -9
- package/dist/src/core/logger.test.js.map +1 -1
- package/dist/src/core/nonInteractiveToolExecutor.js +11 -3
- package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
- package/dist/src/core/prompts.js +1 -1
- package/dist/src/core/tokenLimits.js +1 -0
- package/dist/src/core/tokenLimits.js.map +1 -1
- package/dist/src/core/turn.d.ts +3 -0
- package/dist/src/core/turn.js +3 -0
- package/dist/src/core/turn.js.map +1 -1
- package/dist/src/ide/detect-ide.d.ts +10 -0
- package/dist/src/ide/detect-ide.js +24 -0
- package/dist/src/ide/detect-ide.js.map +1 -0
- package/dist/src/ide/ide-client.d.ts +19 -7
- package/dist/src/ide/ide-client.js +100 -36
- package/dist/src/ide/ide-client.js.map +1 -1
- package/dist/src/ide/ide-installer.d.ts +15 -0
- package/dist/src/ide/ide-installer.js +111 -0
- package/dist/src/ide/ide-installer.js.map +1 -0
- package/dist/src/ide/ide-installer.test.d.ts +6 -0
- package/dist/src/ide/ide-installer.test.js +78 -0
- package/dist/src/ide/ide-installer.test.js.map +1 -0
- package/dist/src/ide/ideContext.d.ts +212 -107
- package/dist/src/ide/ideContext.js +45 -44
- package/dist/src/ide/ideContext.js.map +1 -1
- package/dist/src/ide/ideContext.test.js +254 -100
- package/dist/src/ide/ideContext.test.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.js +3 -3
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +9 -8
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/mcp/oauth-utils.js +2 -2
- package/dist/src/mcp/oauth-utils.js.map +1 -1
- package/dist/src/mcp/oauth-utils.test.js +1 -1
- package/dist/src/mcp/oauth-utils.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.d.ts +3 -0
- package/dist/src/services/loopDetectionService.js +18 -0
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/services/loopDetectionService.test.js +90 -11
- package/dist/src/services/loopDetectionService.test.js.map +1 -1
- package/dist/src/services/shellExecutionService.js +7 -4
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/shellExecutionService.test.js +11 -5
- package/dist/src/services/shellExecutionService.test.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +4 -2
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +80 -34
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +6 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +19 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/constants.d.ts +2 -1
- package/dist/src/telemetry/constants.js +2 -1
- package/dist/src/telemetry/constants.js.map +1 -1
- package/dist/src/telemetry/index.d.ts +2 -2
- package/dist/src/telemetry/index.js +2 -2
- package/dist/src/telemetry/index.js.map +1 -1
- package/dist/src/telemetry/loggers.d.ts +3 -2
- package/dist/src/telemetry/loggers.js +21 -5
- package/dist/src/telemetry/loggers.js.map +1 -1
- package/dist/src/telemetry/loggers.test.circular.js +2 -0
- package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +8 -3
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/telemetry.test.js +2 -0
- package/dist/src/telemetry/telemetry.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +19 -4
- package/dist/src/telemetry/types.js +30 -4
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/telemetry/uiTelemetry.test.js +3 -0
- package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
- package/dist/src/test-utils/mockWorkspaceContext.d.ts +13 -0
- package/dist/src/test-utils/mockWorkspaceContext.js +24 -0
- package/dist/src/test-utils/mockWorkspaceContext.js.map +1 -0
- package/dist/src/tools/edit.js +27 -3
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +104 -1
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/glob.js +53 -17
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/glob.test.js +25 -2
- package/dist/src/tools/glob.test.js.map +1 -1
- package/dist/src/tools/grep.d.ts +1 -1
- package/dist/src/tools/grep.js +81 -29
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/grep.test.js +72 -5
- package/dist/src/tools/grep.test.js.map +1 -1
- package/dist/src/tools/ls.js +4 -3
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/ls.test.d.ts +6 -0
- package/dist/src/tools/ls.test.js +356 -0
- package/dist/src/tools/ls.test.js.map +1 -0
- package/dist/src/tools/mcp-client.js +8 -14
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +34 -0
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/memoryTool.d.ts +17 -2
- package/dist/src/tools/memoryTool.js +130 -13
- package/dist/src/tools/memoryTool.js.map +1 -1
- package/dist/src/tools/memoryTool.test.js +88 -3
- package/dist/src/tools/memoryTool.test.js.map +1 -1
- package/dist/src/tools/read-file.js +8 -6
- package/dist/src/tools/read-file.js.map +1 -1
- package/dist/src/tools/read-file.test.js +30 -2
- package/dist/src/tools/read-file.test.js.map +1 -1
- package/dist/src/tools/read-many-files.js +22 -12
- package/dist/src/tools/read-many-files.js.map +1 -1
- package/dist/src/tools/read-many-files.test.js +35 -2
- package/dist/src/tools/read-many-files.test.js.map +1 -1
- package/dist/src/tools/shell.js +8 -4
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/shell.test.js +33 -1
- package/dist/src/tools/shell.test.js.map +1 -1
- package/dist/src/tools/tool-error.d.ts +22 -0
- package/dist/src/tools/tool-error.js +27 -0
- package/dist/src/tools/tool-error.js.map +1 -0
- package/dist/src/tools/tool-registry.test.js +8 -0
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +8 -0
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/write-file.js +5 -3
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +36 -2
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.js +51 -27
- package/dist/src/utils/bfsFileSearch.js.map +1 -1
- package/dist/src/utils/bfsFileSearch.test.js +59 -0
- package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
- package/dist/src/utils/editCorrector.js +2 -2
- package/dist/src/utils/editCorrector.js.map +1 -1
- package/dist/src/utils/editor.d.ts +1 -1
- package/dist/src/utils/editor.js +9 -0
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +21 -1
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/fileUtils.js +12 -1
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +29 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/flashFallback.integration.test.js +8 -0
- package/dist/src/utils/flashFallback.integration.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +1 -1
- package/dist/src/utils/memoryDiscovery.js +54 -75
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +4 -3
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.d.ts +19 -12
- package/dist/src/utils/memoryImportProcessor.js +241 -82
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.test.js +595 -50
- package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.js +3 -23
- package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
- package/dist/src/utils/nextSpeakerChecker.test.js +2 -2
- package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
- package/dist/src/utils/retry.d.ts +3 -0
- package/dist/src/utils/retry.js.map +1 -1
- package/dist/src/utils/retry.test.js.map +1 -1
- package/dist/src/utils/secure-browser-launcher.d.ts +23 -0
- package/dist/src/utils/secure-browser-launcher.js +164 -0
- package/dist/src/utils/secure-browser-launcher.js.map +1 -0
- package/dist/src/utils/secure-browser-launcher.test.d.ts +6 -0
- package/dist/src/utils/secure-browser-launcher.test.js +149 -0
- package/dist/src/utils/secure-browser-launcher.test.js.map +1 -0
- package/dist/src/utils/summarizer.js +2 -2
- package/dist/src/utils/summarizer.js.map +1 -1
- package/dist/src/utils/workspaceContext.d.ts +47 -0
- package/dist/src/utils/workspaceContext.js +106 -0
- package/dist/src/utils/workspaceContext.js.map +1 -0
- package/dist/src/utils/workspaceContext.test.d.ts +6 -0
- package/dist/src/utils/workspaceContext.test.js +209 -0
- package/dist/src/utils/workspaceContext.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- 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 {
|
|
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,
|
|
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,
|
|
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,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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"}
|