Skip to content

Commit

Permalink
Merge pull request #39 from forcedotcom/cd/support-mpd
Browse files Browse the repository at this point in the history
feat: support opening agents in MPD projects W-17961897
  • Loading branch information
WillieRuemmele authored Mar 11, 2025
2 parents 9c02119 + bcb3579 commit 92f55a0
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 59 deletions.
80 changes: 46 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
],
"main": "lib/src/extension.js",
"dependencies": {
"@salesforce/agents-bundle": "0.12.1",
"@salesforce/core-bundle": "8.8.2",
"@salesforce/agents-bundle": "0.13.0",
"@salesforce/core-bundle": "8.8.5",
"cross-spawn": "^7.0.6",
"fast-xml-parser": "^4.5.1",
"semver": "^7.7.0",
Expand Down
20 changes: 11 additions & 9 deletions src/commands/openAgentInOrg.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import * as vscode from 'vscode';
import { Commands } from '../enums/commands';
import { SfProject } from '@salesforce/core-bundle';
import * as path from 'path';
import { Agent } from '@salesforce/agents-bundle';
import { sync } from 'cross-spawn';
import { CoreExtensionService } from '../services/coreExtensionService';

export const registerOpenAgentInOrgCommand = () => {
return vscode.commands.registerCommand(Commands.openAgentInOrg, async () => {
// TODO: maybe an Agent.listLocal() or something similar in the library
const telemetryService = CoreExtensionService.getTelemetryService();
const channelService = CoreExtensionService.getChannelService();
telemetryService.sendCommandEvent(Commands.openAgentInOrg);
const project = SfProject.getInstance();
const defaultPath = project.getDefaultPackage().fullPath;
const agents = (
await vscode.workspace.fs.readDirectory(vscode.Uri.file(path.join(defaultPath, 'main', 'default', 'bots')))
).map(f => f[0]);

const agents = await Agent.list(project);
if (agents.length === 0) {
vscode.window.showErrorMessage(`Could not find agents in the current project.`);
channelService.appendLine('Could not find agents in the current project.');
channelService.appendLine('Suggestion: retrieve your agents (Bot) metadata locally.');
return;
}
// we need to prompt the user which agent to ope
const agentName = await vscode.window.showQuickPick(agents, { title: 'Choose which Agent to open' });
const agentName = await vscode.window.showQuickPick(agents, { placeHolder: 'Agent name (type to search)' });

if (!agentName) {
telemetryService.sendException('no_agent_selected', 'No Agent selected');
throw new Error('No Agent selected');
return;
}

await vscode.window.withProgress(
Expand Down
20 changes: 6 additions & 14 deletions test/commands/openAgentInOrg.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import * as vscode from 'vscode';
import { registerOpenAgentInOrgCommand } from '../../src/commands/openAgentInOrg';
import { Commands } from '../../src/enums/commands';
import { SfProject } from '@salesforce/core-bundle';
import * as path from 'path';
import { sync } from 'cross-spawn';
import { CoreExtensionService } from '../../src/services/coreExtensionService';
import { Agent } from '@salesforce/agents-bundle';

jest.mock('cross-spawn', () => ({
sync: jest.fn()
Expand All @@ -13,7 +13,6 @@ jest.mock('cross-spawn', () => ({
describe('registerOpenAgentInOrgCommand', () => {
let commandSpy: jest.SpyInstance;
let projectSpy: jest.SpyInstance;
let fsSpy: jest.SpyInstance;
let quickPickSpy: jest.SpyInstance;
let progressSpy: jest.SpyInstance;
let errorMessageSpy: jest.SpyInstance;
Expand All @@ -23,15 +22,15 @@ describe('registerOpenAgentInOrgCommand', () => {
};
beforeEach(() => {
jest.spyOn(CoreExtensionService, 'getTelemetryService').mockReturnValue(fakeTelemetryInstance);
// @ts-ignore
jest.spyOn(CoreExtensionService, 'getChannelService').mockReturnValue({});

jest.spyOn(Agent, 'list').mockResolvedValue(['Agent1', 'Agent2']);

commandSpy = jest.spyOn(vscode.commands, 'registerCommand');
projectSpy = jest.spyOn(SfProject, 'getInstance').mockReturnValue({
getDefaultPackage: jest.fn().mockReturnValue({ fullPath: '/fake/path' })
} as unknown as SfProject);
fsSpy = jest.spyOn(vscode.workspace.fs, 'readDirectory').mockResolvedValue([
['Agent1', 1],
['Agent2', 1]
]);
quickPickSpy = jest.spyOn(vscode.window, 'showQuickPick').mockResolvedValue([{ title: 'Agent1' }] as any);
errorMessageSpy = jest.spyOn(vscode.window, 'showErrorMessage').mockImplementation();
progressSpy = jest
Expand All @@ -55,17 +54,10 @@ describe('registerOpenAgentInOrgCommand', () => {

expect(progressSpy).toHaveBeenCalled();
expect(projectSpy).toHaveBeenCalled();
expect(fsSpy).toHaveBeenCalledWith(vscode.Uri.file(path.join('/fake/path', 'main', 'default', 'bots')));
expect(quickPickSpy).toHaveBeenCalledWith(['Agent1', 'Agent2'], { title: 'Choose which Agent to open' });
expect(quickPickSpy).toHaveBeenCalledWith(['Agent1', 'Agent2'], { placeHolder: 'Agent name (type to search)' });
expect(sync).toHaveBeenCalledWith('sf', ['org', 'open', 'agent', '--name', [{ title: 'Agent1' }]]);
});

it('throws error when no agent is selected', async () => {
quickPickSpy.mockResolvedValue(undefined);
registerOpenAgentInOrgCommand();
await expect(commandSpy.mock.calls[0][1]()).rejects.toThrow('No Agent selected');
});

it('shows error message when command fails', async () => {
(sync as jest.Mock).mockReturnValue({ status: 1, stderr: Buffer.from('Error opening agent') });
registerOpenAgentInOrgCommand();
Expand Down

0 comments on commit 92f55a0

Please sign in to comment.