Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/agents/scriptAgentPublisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,14 @@ export class ScriptAgentPublisher {
* and locates the corresponding authoring bundle directory and metadata file.
*
* @returns An object containing:
* - developerName: The cleaned developer name without version suffixes
* - developerName: The agent's developer name
* - bundleDir: The path to the authoring bundle directory
* - bundleMetaPath: The full path to the bundle-meta.xml file
*
* @throws SfError if the authoring bundle directory or metadata file cannot be found
*/
private validateDeveloperName(): { developerName: string; bundleDir: string; bundleMetaPath: string } {
const developerName = this.agentJson.globalConfiguration.developerName.replace(/_v\d$/, '');
const developerName = this.agentJson.globalConfiguration.developerName;
const defaultPackagePath = path.resolve(this.project.getDefaultPackage().path);

// Try to find the authoring bundle directory by recursively searching from the default package path
Expand Down
46 changes: 45 additions & 1 deletion test/agentPublisher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { join } from 'node:path';
import { join, resolve } from 'node:path';
import { mkdir, rm, writeFile, readFile } from 'node:fs/promises';
import { expect } from 'chai';
import { MockTestOrgData, TestContext } from '@salesforce/core/testSetup';
Expand Down Expand Up @@ -301,6 +301,50 @@ describe('AgentPublisher', () => {
expect(refreshStub.called).to.be.false;
expect(connection.accessToken).to.equal(originalAccessToken);
});

it('should publish and deploy the real test_agent directory the search resolved', async () => {
await createTestBundleStructure('test_agent'); // real on-disk bundle dir

// Drive the publisher with a name that ends in the _<N> version convention.
const localAgentJson: AgentJson = {
...agentJson,
globalConfiguration: {
...agentJson.globalConfiguration,
developerName: 'test_agent',
},
};

process.env.SF_MOCK_DIR = join('test', 'mocks', 'publishNewAgent-Success');

$$.SANDBOX.stub(connection, 'singleRecordQuery')
.withArgs("SELECT Id FROM BotDefinition WHERE DeveloperName='test_agent'")
.throws(new Error('No records found'))
.withArgs("SELECT DeveloperName FROM BotVersion WHERE Id='0Bv000000000002'")
.resolves({ DeveloperName: 'developerNameDummy' });

// skipMetadataRetrieve=true so retrieveAgentMetadata is bypassed (no need to stub it).
publisher = new ScriptAgentPublisher(connection, sfProject, localAgentJson, true);

$$.SANDBOX.stub(utils, 'useNamedUserJwt').resolves(connection);
$$.SANDBOX.stub(connection, 'refreshAuth').resolves();

// Let the REAL deployAuthoringBundle run; stub only the org boundary it calls.
const pollStatusStub = $$.SANDBOX.stub().resolves({ response: { success: true } } as never);
const deployStub = $$.SANDBOX.stub().resolves({ pollStatus: pollStatusStub } as unknown);
const fromSourceStub = $$.SANDBOX.stub(ComponentSet, 'fromSource').returns({ deploy: deployStub } as never);

const result = await publisher.publishAgentJson();

// The real findAuthoringBundle resolved test_agent, and publish deployed THAT dir.
expect(fromSourceStub.calledOnce).to.be.true;

expect(fromSourceStub.firstCall.args[0]).to.equal(
resolve(join('force-app', 'main', 'default', 'aiAuthoringBundles', 'test_agent'))
);

expect(result).to.have.property('developerName', 'test_agent');
});

});

describe('getPublishedBotId', () => {
Expand Down
8 changes: 4 additions & 4 deletions test/testData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const compileAgentScriptResponseSuccess: CompileAgentScriptResponse = {
compiledArtifact: {
schemaVersion: '2.0',
globalConfiguration: {
developerName: 'test_agent_v1',
developerName: 'test_agent',

@nico-pappagianis nico-pappagianis Jun 25, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test data is only used by agentPublisher.test.ts and encodes incorrect behavior.

agentPublisher.test.ts tests validated that the developer name's _v<N> was stripped which should not happen. Developer names should not be altered for bundle lookup.

This is likely a misunderstood implementation of versioning as described here, but it is an outright bug.

In other words, testing that we strip _v<N> from developer names is incorrect test behavior.

label: '',
description: '',
enableEnhancedEventLogs: false,
Expand All @@ -31,7 +31,7 @@ export const compileAgentScriptResponseSuccess: CompileAgentScriptResponse = {
contextVariables: [],
},
agentVersion: {
developerName: 'test_agent_v1',
developerName: 'test_agent',
plannerType: 'Atlas__ConcurrentMultiAgentOrchestration',
systemMessages: [],
modalityParameters: {
Expand Down Expand Up @@ -120,7 +120,7 @@ start_agent agent_router:
export const testAgentJson: AgentJson = {
schemaVersion: '2.0',
globalConfiguration: {
developerName: 'test_agent_v1',
developerName: 'test_agent',
label: 'Test Agent',
description: 'A test agent',
agentType: 'AgentforceServiceAgent',
Expand All @@ -131,7 +131,7 @@ export const testAgentJson: AgentJson = {
contextVariables: [],
},
agentVersion: {
developerName: 'test_agent_v1',
developerName: 'test_agent',
company: 'Test Company',
role: 'Test Role',
plannerType: 'Atlas__ConcurrentMultiAgentOrchestration',
Expand Down
Loading