Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
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
3 changes: 1 addition & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@
"NODE_ENV": "development",
"DEBUG": "composer*",
"COMPOSER_DEV_TOOLS": "true",
"COMPOSER_ENABLE_ONEAUTH": "true",
"COMPOSER_PVA_TOPICS": "true"
"COMPOSER_ENABLE_ONEAUTH": "true"
},
"outputCapture": "std",
"preLaunchTask": "electron: build",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type TopicsListProps = {
};

export const TopicsList: React.FC<TopicsListProps> = ({ topics, onToggle, textWidth, projectId }) => {
const linkTooltip = formatMessage('Open in Power Virtual Agents');
const linkTooltip = formatMessage('Edit in Power Virtual Agents');

const renderTopic = (topic: DialogInfo) => {
const isSystemTopic = get(topic.content, 'isSystemTopic', false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,59 +78,12 @@ describe('Power Virtual Agents provider', () => {
mockFetch.mockResolvedValueOnce(mockResult);
const result = await provider.downloadBotContent();

expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('?includeTopics'), expect.any(Object));
expect(result.eTag).toBe('W/"Version"');
expect((result.zipPath as string).includes('bot-assets-'));
expect(Buffer.from(result.urlSuffix, 'base64').toString()).toBe('dialogs/myDialog');
});

it('should not include topics by default', async () => {
process.env.COMPOSER_PVA_TOPICS = 'any-value-other-than-true';
const mockResult = {
body: {
pipe: jest.fn(),
},
headers: {
get: (header) => {
if (header === 'content-type') {
return 'application/zip';
}
if (header === 'etag') {
return 'W/"Version"';
}
},
},
};
mockFetch.mockResolvedValueOnce(mockResult);
await provider.downloadBotContent();

expect(mockFetch).not.toHaveBeenCalledWith(expect.stringContaining('?includeTopics'), expect.any(Object));
delete process.env.COMPOSER_PVA_TOPICS;
});

it('should include topics if env variable is set', async () => {
process.env.COMPOSER_PVA_TOPICS = 'true';
const mockResult = {
body: {
pipe: jest.fn(),
},
headers: {
get: (header) => {
if (header === 'content-type') {
return 'application/zip';
}
if (header === 'etag') {
return 'W/"Version"';
}
},
},
};
mockFetch.mockResolvedValueOnce(mockResult);
await provider.downloadBotContent();

expect(mockFetch).toHaveBeenCalledWith(expect.stringContaining('?includeTopics'), expect.any(Object));
delete process.env.COMPOSER_PVA_TOPICS;
});

it('should throw if the zip response does not have the correct header', async () => {
const mockResult = {
body: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ export class PowerVirtualAgentsProvider extends ExternalContentProvider<PowerVir

private getContentUrl(): string {
const { envId, baseUrl, botId } = this.metadata;
const query = process.env.COMPOSER_PVA_TOPICS === 'true' ? '?includeTopics=true' : '';
return `${baseUrl || getBaseUrl()}/environments/${envId}/bots/${botId}/composer/content${query}`;
return `${baseUrl || getBaseUrl()}/environments/${envId}/bots/${botId}/composer/content?includeTopics=true`;
}

private async getRequestHeaders() {
Expand Down
3 changes: 2 additions & 1 deletion Composer/packages/server/src/models/bot/botProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -822,14 +822,15 @@ export class BotProject implements IBotProject {
const paths = this.fileStorage.globSync(
[
...BotStructureFilesPatterns,
...PVATopicFilePatterns,
'!(generated/**)',
'!(runtime/**)',
'!(bin/**)',
'!(obj/**)',
'!(scripts/**)',
'!(settings/appsettings.json)',
'!(**/luconfig.json)',
].concat(process.env.COMPOSER_PVA_TOPICS === 'true' ? PVATopicFilePatterns : []),
],
root
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,14 @@ export const ComboBoxField: React.FC<ComboBoxFieldProps> = (props) => {
<FieldLabel description={description} helpLink={uiOptions?.helpLink} id={id} label={label} required={required} />
<ComboBox
useComboBoxAsMenuWidth
autoComplete="off"
autoComplete="on"
id={id}
options={options}
selectedKey={comboboxTitle ? 'customTitle' : value}
styles={{ optionsContainerWrapper: { maxHeight: '540px' } }}
onBlur={() => onBlur?.(id, value)}
onChange={onChange}
onFocus={() => onFocus?.(id, value)}
onItemClick={onChange}
onRenderOption={onRenderOption}
/>
</React.Fragment>
Expand Down
3 changes: 1 addition & 2 deletions extensions/pvaPublish/src/node/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,7 @@ export const pull = async (
const accessToken = await getAccessToken(creds);

// fetch zip containing bot content
const query = process.env.COMPOSER_PVA_TOPICS === 'true' ? '?includeTopics=true' : '';
const url = `${base}api/botmanagement/${API_VERSION}/environments/${envId}/bots/${botId}/composer/content${query}`;
const url = `${base}api/botmanagement/${API_VERSION}/environments/${envId}/bots/${botId}/composer/content?includeTopics=true`;
const options: RequestInit = {
method: 'GET',
headers: getAuthHeaders(accessToken, tenantId),
Expand Down