Skip to content

Commit 59f74af

Browse files
authored
Merge pull request #119 from salesforcecli/ew/gen-ai-planner-bundle
W-18171905 Support genAiPlannerBundles for agent generate template
2 parents f14bec0 + 7286743 commit 59f74af

File tree

9 files changed

+41
-326
lines changed

9 files changed

+41
-326
lines changed

schemas/agent-generate-template.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
"AgentGenerateTemplateResult": {
66
"type": "object",
77
"properties": {
8-
"genAiPlannerPath": {
8+
"genAiPlannerBundlePath": {
99
"type": "string"
1010
},
1111
"botTemplatePath": {
1212
"type": "string"
1313
}
1414
},
15-
"required": ["genAiPlannerPath", "botTemplatePath"],
15+
"required": ["genAiPlannerBundlePath", "botTemplatePath"],
1616
"additionalProperties": false
1717
}
1818
}

src/commands/agent/generate/template.ts

+16-12
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import type {
2020
ConversationVariable,
2121
} from '@salesforce/types/metadata';
2222

23-
export type GenAiPlannerExt = {
24-
GenAiPlanner: GenAiPlanner & { botTemplate?: string };
23+
export type GenAiPlannerBundleExt = {
24+
GenAiPlannerBundle: GenAiPlanner & { botTemplate?: string };
2525
};
2626

2727
export type BotTemplateExt = {
@@ -46,7 +46,7 @@ Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
4646
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.generate.template');
4747

4848
export type AgentGenerateTemplateResult = {
49-
genAiPlannerPath: string;
49+
genAiPlannerBundlePath: string;
5050
botTemplatePath: string;
5151
};
5252
export default class AgentGenerateTemplate extends SfCommand<AgentGenerateTemplateResult> {
@@ -82,41 +82,45 @@ export default class AgentGenerateTemplate extends SfCommand<AgentGenerateTempla
8282
const builder = new XMLBuilder({ format: true, ignoreAttributes: false, indentBy: ' ' });
8383

8484
const botName = basename(agentFile, '.bot-meta.xml');
85-
// Since we are cloning the GenAiPlanner, we need to use a different name than the Agent (Bot) we started with
85+
// Since we are cloning the GenAiPlannerBundle, we need to use a different name than the Agent (Bot) we started with
8686
// We will use this name for the BotTemplate also to make it clear they are related
8787
const finalFilename = `${botName}_v${botVersion}_Template`;
8888

8989
// Build the base dir from the AgentFile
9090
const basePath = resolve(dirname(agentFile), '..', '..');
9191
const botDir = join(basePath, 'bots', botName);
92-
const genAiPlannerDir = join(basePath, 'genAiPlanners');
92+
const genAiPlannerBundleDir = join(basePath, 'genAiPlannerBundles');
9393
const botTemplateDir = join(basePath, 'botTemplates');
9494

9595
const botTemplateFilePath = join(botTemplateDir, `${finalFilename}.botTemplate-meta.xml`);
96-
const clonedGenAiPlannerFilePath = join(genAiPlannerDir, `${finalFilename}.genAiPlanner-meta.xml`);
96+
const clonedGenAiPlannerBundleFilePath = join(
97+
genAiPlannerBundleDir,
98+
finalFilename,
99+
`${finalFilename}.genAiPlannerBundle`
100+
);
97101

98102
// Parse the metadata files as JSON
99103
const botJson = xmlToJson<BotExt>(join(botDir, `${botName}.bot-meta.xml`), parser);
100104
const botVersionJson = xmlToJson<BotVersionExt>(join(botDir, `v${botVersion}.botVersion-meta.xml`), parser);
101-
const genAiPlannerMetaJson = xmlToJson<GenAiPlannerExt>(
102-
join(genAiPlannerDir, `${botName}.genAiPlanner-meta.xml`),
105+
const genAiPlannerBundleMetaJson = xmlToJson<GenAiPlannerBundleExt>(
106+
join(genAiPlannerBundleDir, botName, `${botName}.genAiPlannerBundle`),
103107
parser
104108
);
105109

106110
// Modify the metadata files for final output
107111
// TODO: Confirm this name (might be conversationDefinitionPlanners)
108-
genAiPlannerMetaJson.GenAiPlanner.botTemplate = finalFilename;
112+
genAiPlannerBundleMetaJson.GenAiPlannerBundle.botTemplate = finalFilename;
109113
const botTemplate = convertBotToBotTemplate(botJson, botVersionJson, finalFilename, botTemplateFilePath);
110114

111115
// Build and save the metadata files
112-
jsonToXml<GenAiPlannerExt>(clonedGenAiPlannerFilePath, genAiPlannerMetaJson, builder);
116+
jsonToXml<GenAiPlannerBundleExt>(clonedGenAiPlannerBundleFilePath, genAiPlannerBundleMetaJson, builder);
113117
jsonToXml<BotTemplateExt>(botTemplateFilePath, botTemplate, builder);
114118

115119
this.log(`\nSaved BotTemplate to:\n - ${botTemplateFilePath}`);
116-
this.log(`Saved GenAiPlanner to:\n - ${clonedGenAiPlannerFilePath}`);
120+
this.log(`Saved GenAiPlannerBundle to:\n - ${clonedGenAiPlannerBundleFilePath}`);
117121

118122
return {
119-
genAiPlannerPath: clonedGenAiPlannerFilePath,
123+
genAiPlannerBundlePath: clonedGenAiPlannerBundleFilePath,
120124
botTemplatePath: botTemplateFilePath,
121125
};
122126
}

test/commands/agent/generate/template.nut.ts

+17-14
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { expect } from 'chai';
1212
import {
1313
AgentGenerateTemplateResult,
1414
BotTemplateExt,
15-
GenAiPlannerExt,
15+
GenAiPlannerBundleExt,
1616
} from '../../../../src/commands/agent/generate/template.js';
1717

1818
describe('agent generate template NUTs', () => {
@@ -42,7 +42,7 @@ describe('agent generate template NUTs', () => {
4242
);
4343
});
4444

45-
it('Converts an Agent into an BotTemplate and GenAiPlanner', async () => {
45+
it('Converts an Agent into an BotTemplate and GenAiPlannerBundle', async () => {
4646
const agentVersion = 1;
4747
const agentFile = join(
4848
'force-app',
@@ -64,19 +64,20 @@ describe('agent generate template NUTs', () => {
6464
'botTemplates',
6565
'Guest_Experience_Agent_v1_Template.botTemplate-meta.xml'
6666
);
67-
const genAiPlannerFilePath = join(
67+
const genAiPlannerBundleFilePath = join(
6868
'force-app',
6969
'main',
7070
'default',
71-
'genAiPlanners',
72-
'Guest_Experience_Agent_v1_Template.genAiPlanner-meta.xml'
71+
'genAiPlannerBundles',
72+
'Guest_Experience_Agent_v1_Template',
73+
'Guest_Experience_Agent_v1_Template.genAiPlannerBundle'
7374
);
7475

7576
const generatedBotTemplateFilePath = resolve(session.project.dir, botTemplateFilePath);
76-
const generatedGenAiPlannerFilePath = resolve(session.project.dir, genAiPlannerFilePath);
77+
const generatedGenAiPlannerBundleFilePath = resolve(session.project.dir, genAiPlannerBundleFilePath);
7778
// Ensure it returns the paths to the generated files
7879
expect(output?.result.botTemplatePath).to.equal(generatedBotTemplateFilePath);
79-
expect(output?.result.genAiPlannerPath).to.equal(generatedGenAiPlannerFilePath);
80+
expect(output?.result.genAiPlannerBundlePath).to.equal(generatedGenAiPlannerBundleFilePath);
8081

8182
// Compare generated files with mock files
8283
const mockBotTemplateFilePath = join(
@@ -86,12 +87,12 @@ describe('agent generate template NUTs', () => {
8687
'MOCK-XML',
8788
botTemplateFilePath
8889
);
89-
const mockGenAiPlannerFilePath = join(
90+
const mockGenAiPlannerBundleFilePath = join(
9091
'test',
9192
'mock-projects',
9293
'agent-generate-template',
9394
'MOCK-XML',
94-
genAiPlannerFilePath
95+
genAiPlannerBundleFilePath
9596
);
9697

9798
const parser = new XMLParser({ ignoreAttributes: false });
@@ -103,10 +104,12 @@ describe('agent generate template NUTs', () => {
103104
const mockBotTemplateFile = parser.parse(readFileSync(mockBotTemplateFilePath, 'utf-8')) as BotTemplateExt;
104105
expect(generatedBotTemplateFile).to.deep.equal(mockBotTemplateFile);
105106

106-
const generatedGenAiPlannerFile = parser.parse(
107-
readFileSync(generatedGenAiPlannerFilePath, 'utf-8')
108-
) as GenAiPlannerExt;
109-
const mockGenAiPlannerFile = parser.parse(readFileSync(mockGenAiPlannerFilePath, 'utf-8')) as GenAiPlannerExt;
110-
expect(generatedGenAiPlannerFile).to.deep.equal(mockGenAiPlannerFile);
107+
const generatedGenAiPlannerBundleFile = parser.parse(
108+
readFileSync(generatedGenAiPlannerBundleFilePath, 'utf-8')
109+
) as GenAiPlannerBundleExt;
110+
const mockGenAiPlannerBundleFile = parser.parse(
111+
readFileSync(mockGenAiPlannerBundleFilePath, 'utf-8')
112+
) as GenAiPlannerBundleExt;
113+
expect(generatedGenAiPlannerBundleFile).to.deep.equal(mockGenAiPlannerBundleFile);
111114
});
112115
});
+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<GenAiPlanner xmlns="http://soap.sforce.com/2006/04/metadata">
2+
<GenAiPlannerBundle xmlns="http://soap.sforce.com/2006/04/metadata">
33
<description>Deliver personalized customer interactions with an autonomous AI agent. Agentforce Service Agent intelligently supports your customers with common inquiries and escalates complex issues.</description>
44
<genAiFunctions>
55
<genAiFunctionName>EmployeeCopilot__AnswerQuestionsWithKnowledge</genAiFunctionName>
@@ -16,4 +16,4 @@
1616
<masterLabel>Guest Experience Agent</masterLabel>
1717
<plannerType>AiCopilot__ReAct</plannerType>
1818
<botTemplate>Guest_Experience_Agent_v1_Template</botTemplate>
19-
</GenAiPlanner>
19+
</GenAiPlannerBundle>

test/mock-projects/agent-generate-template/force-app/main/default/bots/Copilot_for_Salesforce/Copilot_for_Salesforce.bot-meta.xml

-182
This file was deleted.

0 commit comments

Comments
 (0)