mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Missing prompt contribution should not break chat (#281451)
This commit is contained in:
@@ -16,7 +16,7 @@ import { IModelService } from '../../../../../../editor/common/services/model.js
|
||||
import { localize } from '../../../../../../nls.js';
|
||||
import { IConfigurationService } from '../../../../../../platform/configuration/common/configuration.js';
|
||||
import { IExtensionDescription } from '../../../../../../platform/extensions/common/extensions.js';
|
||||
import { IFileService } from '../../../../../../platform/files/common/files.js';
|
||||
import { FileOperationError, FileOperationResult, IFileService } from '../../../../../../platform/files/common/files.js';
|
||||
import { IExtensionService } from '../../../../../services/extensions/common/extensions.js';
|
||||
import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js';
|
||||
import { ILabelService } from '../../../../../../platform/label/common/label.js';
|
||||
@@ -387,7 +387,7 @@ export class PromptsService extends Disposable implements IPromptsService {
|
||||
let agentFiles = await this.listPromptFiles(PromptsType.agent, token);
|
||||
const disabledAgents = this.getDisabledPromptFiles(PromptsType.agent);
|
||||
agentFiles = agentFiles.filter(promptPath => !disabledAgents.has(promptPath.uri));
|
||||
const customAgents = await Promise.all(
|
||||
const customAgentsResults = await Promise.allSettled(
|
||||
agentFiles.map(async (promptPath): Promise<ICustomAgent> => {
|
||||
const uri = promptPath.uri;
|
||||
const ast = await this.parseNew(uri, token);
|
||||
@@ -432,6 +432,23 @@ export class PromptsService extends Disposable implements IPromptsService {
|
||||
return { uri, name, description, model, tools, handOffs, argumentHint, target, infer, agentInstructions, source };
|
||||
})
|
||||
);
|
||||
|
||||
const customAgents: ICustomAgent[] = [];
|
||||
for (let i = 0; i < customAgentsResults.length; i++) {
|
||||
const result = customAgentsResults[i];
|
||||
if (result.status === 'fulfilled') {
|
||||
customAgents.push(result.value);
|
||||
} else {
|
||||
const uri = agentFiles[i].uri;
|
||||
const error = result.reason;
|
||||
if (error instanceof FileOperationError && error.fileOperationResult === FileOperationResult.FILE_NOT_FOUND) {
|
||||
this.logger.warn(`[computeCustomAgents] Skipping agent file that does not exist: ${uri}`, error.message);
|
||||
} else {
|
||||
this.logger.error(`[computeCustomAgents] Failed to parse agent file: ${uri}`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return customAgents;
|
||||
}
|
||||
|
||||
|
||||
@@ -1202,6 +1202,57 @@ suite('PromptsService', () => {
|
||||
|
||||
registered.dispose();
|
||||
});
|
||||
|
||||
test('Contributed agent file that does not exist should not crash', async () => {
|
||||
const nonExistentUri = URI.parse('file://extensions/my-extension/nonexistent.agent.md');
|
||||
const existingUri = URI.parse('file://extensions/my-extension/existing.agent.md');
|
||||
const extension = {
|
||||
identifier: { value: 'test.my-extension' }
|
||||
} as unknown as IExtensionDescription;
|
||||
|
||||
// Only create the existing file
|
||||
await mockFiles(fileService, [
|
||||
{
|
||||
path: existingUri.path,
|
||||
contents: [
|
||||
'---',
|
||||
'name: \'Existing Agent\'',
|
||||
'description: \'An agent that exists\'',
|
||||
'---',
|
||||
'I am an existing agent.',
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
// Register both agents (one exists, one doesn't)
|
||||
const registered1 = service.registerContributedFile(
|
||||
PromptsType.agent,
|
||||
'NonExistent Agent',
|
||||
'An agent that does not exist',
|
||||
nonExistentUri,
|
||||
extension
|
||||
);
|
||||
|
||||
const registered2 = service.registerContributedFile(
|
||||
PromptsType.agent,
|
||||
'Existing Agent',
|
||||
'An agent that exists',
|
||||
existingUri,
|
||||
extension
|
||||
);
|
||||
|
||||
// Verify that getCustomAgents doesn't crash and returns only the valid agent
|
||||
const agents = await service.getCustomAgents(CancellationToken.None);
|
||||
|
||||
// Should only get the existing agent, not the non-existent one
|
||||
assert.strictEqual(agents.length, 1, 'Should only return the agent that exists');
|
||||
assert.strictEqual(agents[0].name, 'Existing Agent');
|
||||
assert.strictEqual(agents[0].description, 'An agent that exists');
|
||||
assert.strictEqual(agents[0].uri.toString(), existingUri.toString());
|
||||
|
||||
registered1.dispose();
|
||||
registered2.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
suite('findClaudeSkills', () => {
|
||||
|
||||
Reference in New Issue
Block a user