Skip to content

Commit 46560d5

Browse files
Merge pull request #244 from salesforcecli/er/update-validate-agent
W-19995335: update validate agent
2 parents acf0e2b + b455c4b commit 46560d5

File tree

6 files changed

+1149
-1008
lines changed

6 files changed

+1149
-1008
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"@salesforce/core": "^8.23.1",
1414
"@salesforce/kit": "^3.2.3",
1515
"@salesforce/sf-plugins-core": "^12.2.4",
16-
"@salesforce/source-deploy-retrieve": "^12.22.1",
16+
"@salesforce/source-deploy-retrieve": "^12.25.0",
1717
"@salesforce/types": "^1.4.0",
1818
"ansis": "^3.3.2",
1919
"fast-xml-parser": "^4.5.1",

src/commands/agent/publish/authoring-bundle.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { Agent, findAuthoringBundle } from '@salesforce/agents';
2323
import { RequestStatus, type ScopedPostRetrieve } from '@salesforce/source-deploy-retrieve';
2424
import { ensureArray } from '@salesforce/kit';
2525
import { FlaggablePrompt, promptForAgentFiles } from '../../../flags.js';
26+
import { throwAgentCompilationError } from '../../../common.js';
2627

2728
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
2829
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.publish.authoring-bundle');
@@ -103,12 +104,15 @@ export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishA
103104
const conn = targetOrg.getConnection(flags['api-version']);
104105

105106
// First compile the .agent file to get the Agent JSON
106-
const agentJson = await Agent.compileAgentScript(
107+
const compileResponse = await Agent.compileAgentScript(
107108
conn,
108109
readFileSync(join(authoringBundleDir, `${apiName}.agent`), 'utf8')
109110
);
110-
mso.skipTo('Publish Agent');
111-
111+
if (compileResponse.status === 'success') {
112+
mso.skipTo('Publish Agent');
113+
} else {
114+
throwAgentCompilationError(compileResponse.errors);
115+
}
112116
// Then publish the Agent JSON to create the agent
113117
// Set up lifecycle listeners for retrieve events
114118
Lifecycle.getInstance().on('scopedPreRetrieve', () => {
@@ -129,7 +133,7 @@ export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishA
129133
}
130134
return Promise.resolve();
131135
});
132-
const result = await Agent.publishAgentJson(conn, this.project!, agentJson);
136+
const result = await Agent.publishAgentJson(conn, this.project!, compileResponse.compiledArtifact);
133137
mso.stop();
134138

135139
return {

src/commands/agent/validate/authoring-bundle.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
1919
import { Messages, SfError } from '@salesforce/core';
2020
import { MultiStageOutput } from '@oclif/multi-stage-output';
2121
import { Agent, findAuthoringBundle } from '@salesforce/agents';
22-
import { Duration, sleep } from '@salesforce/kit';
2322
import { colorize } from '@oclif/core/ux';
23+
import { throwAgentCompilationError } from '../../../common.js';
2424
import { FlaggablePrompt, promptForAgentFiles } from '../../../flags.js';
2525

2626
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
@@ -103,25 +103,31 @@ export default class AgentValidateAuthoringBundle extends SfCommand<AgentValidat
103103
mso.skipTo('Validating Authoring Bundle');
104104
const targetOrg = flags['target-org'];
105105
const conn = targetOrg.getConnection(flags['api-version']);
106-
// Call Agent.compileAgent() API
107-
await sleep(Duration.seconds(2));
108-
await Agent.compileAgentScript(conn, readFileSync(join(authoringBundleDir, `${apiName}.agent`), 'utf8'));
109-
mso.updateData({ status: 'COMPLETED' });
110-
mso.stop('completed');
111-
return {
112-
success: true,
113-
};
106+
const result = await Agent.compileAgentScript(
107+
conn,
108+
readFileSync(join(authoringBundleDir, `${apiName}.agent`), 'utf8')
109+
);
110+
if (result.status === 'success') {
111+
mso.updateData({ status: 'COMPLETED' });
112+
mso.stop('completed');
113+
return {
114+
success: true,
115+
};
116+
} else {
117+
throwAgentCompilationError(result.errors);
118+
}
114119
} catch (error) {
115120
// Handle validation errors
116121
const err = SfError.wrap(error);
117122
let count = 0;
118-
const formattedError = err.message
123+
const rawError = err.message ? err.message : err.name;
124+
const formattedError = rawError
119125
.split('\n')
120126
.map((line) => {
121127
count += 1;
122128
const type = line.split(':')[0];
123-
const rest = line.substring(line.indexOf(':')).trim();
124-
return `- ${colorize('red', type)} ${rest}`;
129+
const rest = line.includes(':') ? line.substring(line.indexOf(':')).trim() : '';
130+
return `- ${colorize('red', type)}${rest}`;
125131
})
126132
.join('\n');
127133

src/common.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2025, Salesforce, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import { EOL } from 'node:os';
17+
import { SfError } from '@salesforce/core';
18+
import { CompilationError } from '@salesforce/agents';
19+
20+
/**
21+
* Utility function to generate SfError when there are agent compilation errors.
22+
*
23+
* @param compilationErrors - The compilation errors as strings, CompilationError objects, or array of either
24+
* @throws SfError - Always throws a Salesforce CLI error
25+
*/
26+
export function throwAgentCompilationError(compilationErrors: CompilationError[]): never {
27+
if (compilationErrors.length === 0) {
28+
throw SfError.create({
29+
name: 'CompileAgentScriptError',
30+
message: 'Unknown compilation error occurred',
31+
data: compilationErrors,
32+
});
33+
}
34+
35+
const errors = compilationErrors;
36+
37+
throw SfError.create({
38+
name: 'CompileAgentScriptError',
39+
message: errors.map((e) => `${e.errorType}: ${e.description} [Ln ${e.lineStart}, Col ${e.colStart}]`).join(EOL),
40+
data: errors,
41+
});
42+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2025, Salesforce, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { expect } from 'chai';
18+
import { SfError } from '@salesforce/core';
19+
import { type CompilationError } from '@salesforce/agents';
20+
import AgentValidateAuthoringBundle, {
21+
type AgentValidateAuthoringBundleResult,
22+
} from '../../../../src/commands/agent/validate/authoring-bundle.js';
23+
import { throwAgentCompilationError } from '../../../../src/common.js';
24+
25+
describe('Agent Validate Authoring Bundle', () => {
26+
describe('prompt configuration', () => {
27+
it('should have correct prompt messages', () => {
28+
const prompts = AgentValidateAuthoringBundle['FLAGGABLE_PROMPTS'];
29+
30+
expect(prompts['api-name'].message).to.equal('API name of the authoring bundle you want to validate.');
31+
expect(prompts['api-name'].promptMessage).to.equal('API name of the authoring bundle to validate');
32+
});
33+
});
34+
35+
describe('command result type', () => {
36+
it('should export correct result type', () => {
37+
const result: AgentValidateAuthoringBundleResult = {
38+
success: true,
39+
};
40+
expect(result.success).to.be.true;
41+
expect(result.errors).to.be.undefined;
42+
});
43+
44+
it('should support error result type', () => {
45+
const result: AgentValidateAuthoringBundleResult = {
46+
success: false,
47+
errors: ['Compilation failed', 'Invalid syntax'],
48+
};
49+
expect(result.success).to.be.false;
50+
expect(result.errors).to.deep.equal(['Compilation failed', 'Invalid syntax']);
51+
});
52+
});
53+
54+
describe('throwAgentCompilationError utility', () => {
55+
it('should throw SfError with compilation errors', () => {
56+
const errors: CompilationError[] = [
57+
{
58+
errorType: 'SyntaxError',
59+
description: 'Invalid syntax',
60+
lineStart: 10,
61+
colStart: 5,
62+
lineEnd: 10,
63+
colEnd: 10,
64+
},
65+
{ errorType: 'SyntaxError', description: 'Unknown error', lineStart: 15, colStart: 1, lineEnd: 15, colEnd: 5 },
66+
];
67+
68+
try {
69+
throwAgentCompilationError(errors);
70+
expect.fail('Expected function to throw an error');
71+
} catch (error) {
72+
expect(error).to.be.instanceOf(SfError);
73+
expect((error as SfError).name).to.equal('CompileAgentScriptError');
74+
expect((error as SfError).message).to.include('SyntaxError: Invalid syntax [Ln 10, Col 5]');
75+
expect((error as SfError).message).to.include('SyntaxError: Unknown error [Ln 15, Col 1]');
76+
}
77+
});
78+
79+
it('should handle empty error array', () => {
80+
try {
81+
throwAgentCompilationError([]);
82+
expect.fail('Expected function to throw an error');
83+
} catch (error) {
84+
expect(error).to.be.instanceOf(SfError);
85+
expect((error as SfError).name).to.equal('CompileAgentScriptError');
86+
expect((error as SfError).message).to.equal('Unknown compilation error occurred');
87+
}
88+
});
89+
});
90+
});

0 commit comments

Comments
 (0)