-
Notifications
You must be signed in to change notification settings - Fork 14.2k
fix(skills): respect .gitignore/.geminiignore in skill resource listing #28149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,8 @@ import { ActivateSkillTool } from './activate-skill.js'; | |
| import type { Config } from '../config/config.js'; | ||
| import type { MessageBus } from '../confirmation-bus/message-bus.js'; | ||
| import { createMockMessageBus } from '../test-utils/mock-message-bus.js'; | ||
| import { getFolderStructure } from '../utils/getFolderStructure.js'; | ||
| import type { FileDiscoveryService } from '../services/fileDiscoveryService.js'; | ||
|
|
||
| vi.mock('../utils/getFolderStructure.js', () => ({ | ||
| getFolderStructure: vi.fn().mockResolvedValue('Mock folder structure'), | ||
|
|
@@ -18,9 +20,14 @@ describe('ActivateSkillTool', () => { | |
| let mockConfig: Config; | ||
| let tool: ActivateSkillTool; | ||
| let mockMessageBus: MessageBus; | ||
| let mockFileService: FileDiscoveryService; | ||
|
|
||
| beforeEach(() => { | ||
| mockMessageBus = createMockMessageBus(); | ||
| mockFileService = { | ||
| shouldIgnoreFile: vi.fn(), | ||
| shouldIgnoreDirectory: vi.fn(), | ||
| } as unknown as FileDiscoveryService; | ||
| const skills = [ | ||
| { | ||
| name: 'test-skill', | ||
|
|
@@ -48,8 +55,10 @@ describe('ActivateSkillTool', () => { | |
| }), | ||
| activateSkill: vi.fn(), | ||
| }), | ||
| getFileService: vi.fn().mockReturnValue(mockFileService), | ||
| } as unknown as Config; | ||
| tool = new ActivateSkillTool(mockConfig, mockMessageBus); | ||
| vi.mocked(getFolderStructure).mockClear(); | ||
| }); | ||
|
|
||
| it('should return enhanced description', () => { | ||
|
|
@@ -76,6 +85,24 @@ describe('ActivateSkillTool', () => { | |
| expect(details.prompt).toContain('Mock folder structure'); | ||
| }); | ||
|
|
||
| it('builds the resource list with the file service so ignored paths (e.g. .venv) are honored', async () => { | ||
| const params = { name: 'test-skill' }; | ||
| const invocation = tool.build(params); | ||
| await ( | ||
| invocation as unknown as { | ||
| getConfirmationDetails: (signal: AbortSignal) => Promise<unknown>; | ||
| } | ||
| ).getConfirmationDetails(new AbortController().signal); | ||
|
|
||
| // The skill's folder structure must be built with the file service, so | ||
| // that .gitignore/.geminiignore are respected (issue #27205). Without it, | ||
| // ignored directories are shared with the model. | ||
| expect(getFolderStructure).toHaveBeenCalledWith( | ||
| '/path/to/test-skill', | ||
| expect.objectContaining({ fileService: mockFileService }), | ||
| ); | ||
| }); | ||
|
Comment on lines
+88
to
+104
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of casting the it('builds the resource list with the file service so ignored paths (e.g. .venv) are honored', async () => {
const params = { name: 'test-skill' };
const invocation = tool.build(params);
await invocation.shouldConfirmExecute(
new AbortController().signal,
'ask_user',
);
// The skill's folder structure must be built with the file service, so
// that .gitignore/.geminiignore are respected (issue #27205). Without it,
// ignored directories are shared with the model.
expect(getFolderStructure).toHaveBeenCalledWith(
'/path/to/test-skill',
expect.objectContaining({ fileService: mockFileService }),
);
});References
|
||
|
|
||
| it('should skip confirmation for built-in skills', async () => { | ||
| const builtinSkill = { | ||
| name: 'builtin-skill', | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -64,6 +64,11 @@ class ActivateSkillToolInvocation extends BaseToolInvocation< | |
| if (this.cachedFolderStructure === undefined) { | ||
| this.cachedFolderStructure = await getFolderStructure( | ||
| path.dirname(skillLocation), | ||
| // Pass the file service so the skill's folder structure honors | ||
| // .gitignore/.geminiignore (matching how the workspace structure is | ||
| // built). Without it, ignored directories such as a Python `.venv` | ||
| // are shared with the model, wasting context. See issue #27205. | ||
| { fileService: this.config.getFileService() }, | ||
| ); | ||
| } | ||
|
Comment on lines
64
to
73
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the workspace's To fix this, we should check if the skill directory is inside the workspace. If it is not, we can dynamically instantiate a new if (this.cachedFolderStructure === undefined) {
const skillDir = path.dirname(skillLocation);
const workspaceRoot = this.config.getProjectRoot();
const { isSubpath } = await import('../utils/paths.js');
const { FileDiscoveryService } = await import('../services/fileDiscoveryService.js');
const fileService = isSubpath(workspaceRoot, skillDir)
? this.config.getFileService()
: new FileDiscoveryService(skillDir);
this.cachedFolderStructure = await getFolderStructure(
skillDir,
{ fileService },
);
} |
||
| return this.cachedFolderStructure; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the updated implementation of
ActivateSkillToolcallsgetProjectRoot()to determine if the skill is inside the workspace, we need to mockgetProjectRootin the test configuration to prevent runtime errors during test execution.