Skip to content

Commit 90915ae

Browse files
chore: merge main, resolve conflicts
2 parents 564dcc8 + f8e6962 commit 90915ae

File tree

7 files changed

+1768
-1243
lines changed

7 files changed

+1768
-1243
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## [1.23.6](https://github.com/salesforcecli/plugin-agent/compare/1.23.5...1.23.6) (2025-07-25)
2+
3+
### Bug Fixes
4+
5+
- read from genAiPlanner/Bundle ([19397d4](https://github.com/salesforcecli/plugin-agent/commit/19397d4a013a51ca7f6409828085eec9cbcd9a3f))
6+
17
## [1.23.5](https://github.com/salesforcecli/plugin-agent/compare/1.23.4...1.23.5) (2025-07-23)
28

39
### Bug Fixes

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ EXAMPLES
130130
$ sf agent create --name "Resort Manager" --spec specs/resortManagerAgent.yaml --preview
131131
```
132132

133-
_See code: [src/commands/agent/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/create.ts)_
133+
_See code: [src/commands/agent/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/create.ts)_
134134

135135
## `sf agent generate agent-spec`
136136

@@ -235,7 +235,7 @@ EXAMPLES
235235
$ sf agent generate agent-spec --tone formal --agent-user resortmanager@myorg.com
236236
```
237237

238-
_See code: [src/commands/agent/generate/agent-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/generate/agent-spec.ts)_
238+
_See code: [src/commands/agent/generate/agent-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/generate/agent-spec.ts)_
239239

240240
## `sf agent generate template`
241241

@@ -283,7 +283,7 @@ EXAMPLES
283283
force-app/main/default/bots/My_Awesome_Agent/My_Awesome_Agent.bot-meta.xml --agent-version 1
284284
```
285285

286-
_See code: [src/commands/agent/generate/template.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/generate/template.ts)_
286+
_See code: [src/commands/agent/generate/template.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/generate/template.ts)_
287287

288288
## `sf agent generate test-spec`
289289

@@ -341,7 +341,7 @@ EXAMPLES
341341
force-app//main/default/aiEvaluationDefinitions/Resort_Manager_Tests.aiEvaluationDefinition-meta.xml
342342
```
343343

344-
_See code: [src/commands/agent/generate/test-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/generate/test-spec.ts)_
344+
_See code: [src/commands/agent/generate/test-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/generate/test-spec.ts)_
345345

346346
## `sf agent preview`
347347

@@ -404,7 +404,7 @@ EXAMPLES
404404
transcripts/my-preview
405405
```
406406

407-
_See code: [src/commands/agent/preview.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/preview.ts)_
407+
_See code: [src/commands/agent/preview.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/preview.ts)_
408408

409409
## `sf agent test create`
410410

@@ -459,7 +459,7 @@ EXAMPLES
459459
$ sf agent test create --spec specs/Resort_Manager-testSpec.yaml --api-name Resort_Manager_Test --preview
460460
```
461461

462-
_See code: [src/commands/agent/test/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/test/create.ts)_
462+
_See code: [src/commands/agent/test/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/test/create.ts)_
463463

464464
## `sf agent test list`
465465

@@ -494,7 +494,7 @@ EXAMPLES
494494
$ sf agent test list --target-org my-org
495495
```
496496

497-
_See code: [src/commands/agent/test/list.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/test/list.ts)_
497+
_See code: [src/commands/agent/test/list.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/test/list.ts)_
498498

499499
## `sf agent test results`
500500

@@ -550,7 +550,7 @@ FLAG DESCRIPTIONS
550550
test results aren't written.
551551
```
552552

553-
_See code: [src/commands/agent/test/results.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/test/results.ts)_
553+
_See code: [src/commands/agent/test/results.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/test/results.ts)_
554554

555555
## `sf agent test resume`
556556

@@ -613,7 +613,7 @@ FLAG DESCRIPTIONS
613613
test results aren't written.
614614
```
615615

616-
_See code: [src/commands/agent/test/resume.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/test/resume.ts)_
616+
_See code: [src/commands/agent/test/resume.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/test/resume.ts)_
617617

618618
## `sf agent test run`
619619

@@ -677,6 +677,6 @@ FLAG DESCRIPTIONS
677677
test results aren't written.
678678
```
679679

680-
_See code: [src/commands/agent/test/run.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.5/src/commands/agent/test/run.ts)_
680+
_See code: [src/commands/agent/test/run.ts](https://github.com/salesforcecli/plugin-agent/blob/1.23.6/src/commands/agent/test/run.ts)_
681681

682682
<!-- commandsstop -->

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@salesforce/plugin-agent",
33
"description": "Commands to interact with Salesforce agents",
4-
"version": "1.23.5",
4+
"version": "1.23.6",
55
"author": "Salesforce",
66
"bugs": "https://github.com/forcedotcom/cli/issues",
77
"dependencies": {
@@ -10,10 +10,10 @@
1010
"@oclif/core": "^4",
1111
"@oclif/multi-stage-output": "^0.8.17",
1212
"@salesforce/agents": "0.15.3",
13-
"@salesforce/core": "^8.13.0",
13+
"@salesforce/core": "^8.18.3",
1414
"@salesforce/kit": "^3.2.3",
1515
"@salesforce/sf-plugins-core": "^12.2.0",
16-
"@salesforce/source-deploy-retrieve": "^12.19.3",
16+
"@salesforce/source-deploy-retrieve": "^12.21.4",
1717
"@salesforce/types": "^1.3.0",
1818
"ansis": "^3.3.2",
1919
"fast-xml-parser": "^4.5.1",
@@ -36,6 +36,7 @@
3636
"eslint-plugin-react": "^7.34.3",
3737
"eslint-plugin-react-hooks": "^4.6.2",
3838
"eslint-plugin-sf-plugin": "^1.20.20",
39+
"esmock": "^2.7.1",
3940
"oclif": "^4.17.44",
4041
"ts-node": "^10.9.2",
4142
"typescript": "^5.5.4"

src/commands/agent/generate/test-spec.ts

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44
* Licensed under the BSD 3-Clause license.
55
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
66
*/
7-
import { readFile } from 'node:fs/promises';
7+
import * as fs from 'node:fs';
88
import { join, parse } from 'node:path';
99
import { existsSync } from 'node:fs';
1010
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
11-
import { Messages, SfProject } from '@salesforce/core';
11+
import { Messages, SfError, SfProject } from '@salesforce/core';
1212
import { AgentTest } from '@salesforce/agents';
1313
import { select, input, confirm, checkbox } from '@inquirer/prompts';
1414
import { XMLParser } from 'fast-xml-parser';
1515
import { ComponentSet, ComponentSetBuilder } from '@salesforce/source-deploy-retrieve';
1616
import { warn } from '@oclif/core/errors';
17+
import { ensureArray } from '@salesforce/kit';
1718
import { theme } from '../../../inquirer-theme.js';
1819
import yesNoOrCancel from '../../../yes-no-cancel.js';
1920

@@ -36,11 +37,6 @@ type TestCase = {
3637
}>;
3738
};
3839

39-
function castArray<T>(value: T | T[]): T[] {
40-
if (!value) return [];
41-
return Array.isArray(value) ? value : [value];
42-
}
43-
4440
/**
4541
* Prompts the user for test case information through interactive prompts.
4642
*
@@ -79,10 +75,10 @@ async function promptForTestCase(genAiPlugins: Record<string, string>, genAiFunc
7975
// the actions from the plugin are read from the GenAiPlugin file
8076
let actions: string[] = [];
8177
if (genAiPlugins[expectedTopic]) {
82-
const genAiPluginXml = await readFile(genAiPlugins[expectedTopic], 'utf-8');
78+
const genAiPluginXml = await fs.promises.readFile(genAiPlugins[expectedTopic], 'utf-8');
8379
const parser = new XMLParser();
8480
const parsed = parser.parse(genAiPluginXml) as { GenAiPlugin: { genAiFunctions: Array<{ functionName: string }> } };
85-
actions = castArray(parsed.GenAiPlugin.genAiFunctions ?? []).map((f) => f.functionName);
81+
actions = ensureArray(parsed.GenAiPlugin.genAiFunctions ?? []).map((f) => f.functionName);
8682
}
8783

8884
const expectedActions = (
@@ -215,7 +211,7 @@ async function promptForCustomEvaluations(): Promise<NonNullable<TestCase['custo
215211
return customEvaluations;
216212
}
217213

218-
function getMetadataFilePaths(cs: ComponentSet, type: string): Record<string, string> {
214+
export function getMetadataFilePaths(cs: ComponentSet, type: string): Record<string, string> {
219215
return [...cs.filter((component) => component.type.name === type && component.fullName !== '*')].reduce<
220216
Record<string, string>
221217
>(
@@ -249,52 +245,103 @@ function getMetadataFilePaths(cs: ComponentSet, type: string): Record<string, st
249245
* - genAiPlugins: Record of plugin names to their file paths
250246
* - genAiFunctions: Array of function names
251247
*/
252-
async function getPluginsAndFunctions(
248+
export async function getPluginsAndFunctions(
253249
subjectName: string,
254250
cs: ComponentSet
255251
): Promise<{
256252
genAiPlugins: Record<string, string>;
257253
genAiFunctions: string[];
258254
}> {
259255
const botVersions = getMetadataFilePaths(cs, 'Bot');
260-
const genAiPlanners = getMetadataFilePaths(cs, 'GenAiPlanner');
256+
let genAiFunctions: string[] = [];
257+
let genAiPlugins: Record<string, string> = {};
261258

262259
const parser = new XMLParser();
263-
const botVersionXml = await readFile(botVersions[subjectName], 'utf-8');
260+
const botVersionXml = await fs.promises.readFile(botVersions[subjectName], 'utf-8');
264261
const parsedBotVersion = parser.parse(botVersionXml) as {
265262
BotVersion: { conversationDefinitionPlanners: { genAiPlannerName: string } };
266263
};
267264

268-
const plannerXml = await readFile(
269-
genAiPlanners[parsedBotVersion.BotVersion.conversationDefinitionPlanners.genAiPlannerName ?? subjectName],
270-
'utf-8'
271-
);
272-
const parsedPlanner = parser.parse(plannerXml) as {
273-
GenAiPlanner: {
274-
genAiPlugins: Array<{ genAiPluginName: string }>;
275-
genAiFunctions: Array<{ genAiFunctionName: string }>;
265+
try {
266+
// if the users still have genAiPlanner, not the bundle, we can work with that
267+
const genAiPlanners = getMetadataFilePaths(cs, 'GenAiPlanner');
268+
269+
const plannerXml = await fs.promises.readFile(
270+
genAiPlanners[parsedBotVersion.BotVersion.conversationDefinitionPlanners.genAiPlannerName ?? subjectName],
271+
'utf-8'
272+
);
273+
const parsedPlanner = parser.parse(plannerXml) as {
274+
GenAiPlanner: {
275+
genAiPlugins: Array<{ genAiPluginName: string }>;
276+
genAiFunctions: Array<{ genAiFunctionName: string }>;
277+
};
276278
};
277-
};
279+
genAiFunctions = ensureArray(parsedPlanner.GenAiPlanner.genAiFunctions).map(
280+
({ genAiFunctionName }) => genAiFunctionName
281+
);
278282

279-
const genAiFunctions = castArray(parsedPlanner.GenAiPlanner.genAiFunctions).map(
280-
({ genAiFunctionName }) => genAiFunctionName
281-
);
283+
genAiPlugins = ensureArray(parsedPlanner.GenAiPlanner.genAiPlugins).reduce(
284+
(acc, { genAiPluginName }) => ({
285+
...acc,
286+
[genAiPluginName]: cs.getComponentFilenamesByNameAndType({
287+
fullName: genAiPluginName,
288+
type: 'GenAiPlugin',
289+
})[0],
290+
}),
291+
{}
292+
);
293+
} catch (e) {
294+
// do nothing, we were trying to read the old genAiPlanner
295+
}
282296

283-
const genAiPlugins = castArray(parsedPlanner.GenAiPlanner.genAiPlugins).reduce(
284-
(acc, { genAiPluginName }) => ({
285-
...acc,
286-
[genAiPluginName]: cs.getComponentFilenamesByNameAndType({
287-
fullName: genAiPluginName,
288-
type: 'GenAiPlugin',
289-
})[0],
290-
}),
291-
{}
292-
);
297+
try {
298+
if (genAiFunctions.length === 0 && Object.keys(genAiPlugins).length === 0) {
299+
// if we've already found functions and plugins from the genAiPlanner, don't try to read the bundle
300+
const genAiPlannerBundles = getMetadataFilePaths(cs, 'GenAiPlannerBundle');
301+
const plannerBundleXml = await fs.promises.readFile(
302+
genAiPlannerBundles[parsedBotVersion.BotVersion.conversationDefinitionPlanners.genAiPlannerName ?? subjectName],
303+
'utf-8'
304+
);
305+
const parsedPlannerBundle = parser.parse(plannerBundleXml) as {
306+
GenAiPlannerBundle: {
307+
genAiPlugins: Array<
308+
| {
309+
genAiPluginName: string;
310+
}
311+
| { genAiPluginName: string; genAiCustomizedPlugin: { genAiFunctions: Array<{ functionName: string }> } }
312+
>;
313+
};
314+
};
315+
genAiFunctions = ensureArray(parsedPlannerBundle.GenAiPlannerBundle.genAiPlugins)
316+
.filter((f) => 'genAiCustomizedPlugin' in f)
317+
.map(
318+
({ genAiCustomizedPlugin }) =>
319+
genAiCustomizedPlugin.genAiFunctions.find((plugin) => plugin.functionName !== '')!.functionName
320+
);
321+
322+
genAiPlugins = ensureArray(parsedPlannerBundle.GenAiPlannerBundle.genAiPlugins).reduce(
323+
(acc, { genAiPluginName }) => ({
324+
...acc,
325+
[genAiPluginName]: cs.getComponentFilenamesByNameAndType({
326+
fullName: genAiPluginName,
327+
type: 'GenAiPlugin',
328+
})[0],
329+
}),
330+
{}
331+
);
332+
}
333+
} catch (e) {
334+
throw new SfError(
335+
`Error parsing GenAiPlannerBundle: ${
336+
parsedBotVersion.BotVersion.conversationDefinitionPlanners.genAiPlannerName ?? subjectName
337+
}`
338+
);
339+
}
293340

294341
return { genAiPlugins, genAiFunctions };
295342
}
296343

297-
function ensureYamlExtension(filePath: string): string {
344+
export function ensureYamlExtension(filePath: string): string {
298345
const parsedPath = parse(filePath);
299346

300347
if (parsedPath.ext === '.yaml' || parsedPath.ext === '.yml') return filePath;
@@ -391,7 +438,7 @@ export default class AgentGenerateTestSpec extends SfCommand<void> {
391438

392439
const cs = await ComponentSetBuilder.build({
393440
metadata: {
394-
metadataEntries: ['GenAiPlanner', 'GenAiPlugin', 'Bot'],
441+
metadataEntries: ['GenAiPlanner', 'GenAiPlannerBundle', 'GenAiPlugin', 'Bot'],
395442
directoryPaths,
396443
},
397444
});

0 commit comments

Comments
 (0)