mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-01 17:02:29 -07:00
Allow @-includes outside of workspaces (with permission) (#18470)
This commit is contained in:
committed by
GitHub
parent
e73288f25f
commit
262e8384d4
@@ -1188,40 +1188,6 @@ describe('handleAtCommand', () => {
|
||||
expect.stringContaining(`using glob: ${path.join(subDirPath, '**')}`),
|
||||
);
|
||||
});
|
||||
|
||||
it('should skip absolute paths outside workspace', async () => {
|
||||
const outsidePath = '/tmp/outside-workspace.txt';
|
||||
const query = `Check @${outsidePath} please.`;
|
||||
|
||||
const mockWorkspaceContext = {
|
||||
isPathWithinWorkspace: vi.fn((path: string) =>
|
||||
path.startsWith(testRootDir),
|
||||
),
|
||||
getDirectories: () => [testRootDir],
|
||||
addDirectory: vi.fn(),
|
||||
getInitialDirectories: () => [testRootDir],
|
||||
setDirectories: vi.fn(),
|
||||
onDirectoriesChanged: vi.fn(() => () => {}),
|
||||
} as unknown as ReturnType<typeof mockConfig.getWorkspaceContext>;
|
||||
mockConfig.getWorkspaceContext = () => mockWorkspaceContext;
|
||||
|
||||
const result = await handleAtCommand({
|
||||
query,
|
||||
config: mockConfig,
|
||||
addItem: mockAddItem,
|
||||
onDebugMessage: mockOnDebugMessage,
|
||||
messageId: 502,
|
||||
signal: abortController.signal,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
processedQuery: [{ text: `Check @${outsidePath} please.` }],
|
||||
});
|
||||
|
||||
expect(mockOnDebugMessage).toHaveBeenCalledWith(
|
||||
`Path ${outsidePath} is not in the workspace and will be skipped.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not add the user's turn to history, as that is the caller's responsibility", async () => {
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
getErrorMessage,
|
||||
isNodeError,
|
||||
unescapePath,
|
||||
resolveToRealPath,
|
||||
fileExists,
|
||||
ReadManyFilesTool,
|
||||
REFERENCE_CONTENT_START,
|
||||
REFERENCE_CONTENT_END,
|
||||
@@ -152,6 +154,35 @@ function categorizeAtCommands(
|
||||
return { agentParts, resourceParts, fileParts };
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the query contains any file paths that require read permission.
|
||||
* Returns an array of such paths.
|
||||
*/
|
||||
export async function checkPermissions(
|
||||
query: string,
|
||||
config: Config,
|
||||
): Promise<string[]> {
|
||||
const commandParts = parseAllAtCommands(query);
|
||||
const { fileParts } = categorizeAtCommands(commandParts, config);
|
||||
const permissionsRequired: string[] = [];
|
||||
|
||||
for (const part of fileParts) {
|
||||
const pathName = part.content.substring(1);
|
||||
if (!pathName) continue;
|
||||
|
||||
const resolvedPathName = resolveToRealPath(
|
||||
path.resolve(config.getTargetDir(), pathName),
|
||||
);
|
||||
|
||||
if (config.validatePathAccess(resolvedPathName, 'read')) {
|
||||
if (await fileExists(resolvedPathName)) {
|
||||
permissionsRequired.push(resolvedPathName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return permissionsRequired;
|
||||
}
|
||||
|
||||
interface ResolvedFile {
|
||||
part: AtCommandPart;
|
||||
pathSpec: string;
|
||||
@@ -189,17 +220,6 @@ async function resolveFilePaths(
|
||||
continue;
|
||||
}
|
||||
|
||||
const resolvedPathName = path.isAbsolute(pathName)
|
||||
? pathName
|
||||
: path.resolve(config.getTargetDir(), pathName);
|
||||
|
||||
if (!config.isPathAllowed(resolvedPathName)) {
|
||||
onDebugMessage(
|
||||
`Path ${pathName} is not in the workspace and will be skipped.`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const gitIgnored =
|
||||
respectFileIgnore.respectGitIgnore &&
|
||||
fileDiscovery.shouldIgnoreFile(pathName, {
|
||||
@@ -229,9 +249,7 @@ async function resolveFilePaths(
|
||||
|
||||
for (const dir of config.getWorkspaceContext().getDirectories()) {
|
||||
try {
|
||||
const absolutePath = path.isAbsolute(pathName)
|
||||
? pathName
|
||||
: path.resolve(dir, pathName);
|
||||
const absolutePath = path.resolve(dir, pathName);
|
||||
const stats = await fs.stat(absolutePath);
|
||||
|
||||
const relativePath = path.isAbsolute(pathName)
|
||||
|
||||
Reference in New Issue
Block a user