[@powerpages] Chat Variable and Org Handling (#1029)

* remove variables

* Updated org auth handling

* refactor: Renamed fxn

* refactor: Initialize organization details in OrgHandlerUtils

This commit refactors the `initializeOrgDetails` function in `OrgHandlerUtils.ts` to improve the initialization of organization details. It now retrieves stored organization details from the global state and returns them if available. If not, it uses the PAC wrapper to fetch the organization details and stores them in the global state for future use. This change enhances the efficiency and reliability of the organization details initialization process.

---------

Co-authored-by: amitjoshi <amitjoshi@microsoft.com>
This commit is contained in:
amitjoshi438 2024-09-04 17:18:18 +05:30 коммит произвёл GitHub
Родитель fe3db7f100
Коммит 6244d69fae
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 79 добавлений и 38 удалений

Просмотреть файл

@ -80,6 +80,7 @@
"Active auth profile is not found or has expired. Please try again.": "Active auth profile is not found or has expired. Please try again.",
"Something went wrong. Dont worry, you can try again.": "Something went wrong. Dont worry, you can try again.",
"Make sure AI-generated content is accurate and appropriate before using. [Learn more](https://go.microsoft.com/fwlink/?linkid=2240145) | [View terms](https://go.microsoft.com/fwlink/?linkid=2189520)": "Make sure AI-generated content is accurate and appropriate before using. [Learn more](https://go.microsoft.com/fwlink/?linkid=2240145) | [View terms](https://go.microsoft.com/fwlink/?linkid=2189520)",
"Checking for active auth profile...": "Checking for active auth profile...",
"Hi! Power Pages lets you build secure, professional websites that you can quickly configure and publish across web browsers and devices.\n\nTo create your website, visit the [Power Pages](https://powerpages.microsoft.com/).\nReturn to this chat and @powerpages can help you write and edit your website code.": "Hi! Power Pages lets you build secure, professional websites that you can quickly configure and publish across web browsers and devices.\n\nTo create your website, visit the [Power Pages](https://powerpages.microsoft.com/).\nReturn to this chat and @powerpages can help you write and edit your website code.",
"Select Folder for new PCF Control/Do not translate 'PCF' as it is a product name.": {
"message": "Select Folder for new PCF Control",
@ -254,4 +255,4 @@
"The {0} represents profile's Azure Cloud Instances"
]
}
}
}

Просмотреть файл

@ -63,6 +63,9 @@
<trans-unit id="++CODE++9885d66d0771f63c5a4b5d3b8cbe26be8832bc941243f5b18573975750a9986b">
<source xml:lang="en">Check the URL and verify the parameters are correct</source>
</trans-unit>
<trans-unit id="++CODE++c724a9256b7af89455e04cc3611e5df1030c25f92652356f205c15f02c2da28e">
<source xml:lang="en">Checking for active auth profile...</source>
</trans-unit>
<trans-unit id="++CODE++e1c3ec6d279ce7c1a208abce1314435297d8369739967d8a9db962ab572c617f">
<source xml:lang="en">Choose page template</source>
</trans-unit>

Просмотреть файл

@ -51,5 +51,6 @@ export const ERROR_CONSTANTS = {
LANGUAGE_CODE_ID_VALUE_NULL: "Language code ID is empty",
LANGUAGE_CODE_EMPTY: "Language code is empty",
BULKHEAD_LIMITS_EXCEEDED: "Bulkhead queue limits exceeded",
NPS_FAILED_AUTH: "Failed to authenticate with NPS"
NPS_FAILED_AUTH: "Failed to authenticate with NPS",
PAC_AUTH_FAILED : "Failed to fetch org details from PAC"
};

Просмотреть файл

@ -12,9 +12,9 @@ import { sendApiRequest } from '../../copilot/IntelligenceApiService';
import { PacWrapper } from '../../../client/pac/PacWrapper';
import { intelligenceAPIAuthentication } from '../../services/AuthenticationProvider';
import { ActiveOrgOutput } from '../../../client/pac/PacTypes';
import { AUTHENTICATION_FAILED_MSG, COPILOT_NOT_AVAILABLE_MSG, DISCLAIMER_MESSAGE, INVALID_RESPONSE, NO_PROMPT_MESSAGE, PAC_AUTH_NOT_FOUND, POWERPAGES_CHAT_PARTICIPANT_ID, RESPONSE_AWAITED_MSG, RESPONSE_SCENARIOS, SKIP_CODES, STATER_PROMPTS, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ERROR, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_INVOKED, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ORG_DETAILS, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ORG_DETAILS_NOT_FOUND, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_SCENARIO, WELCOME_MESSAGE, WELCOME_PROMPT } from './PowerPagesChatParticipantConstants';
import { AUTHENTICATION_FAILED_MSG, COPILOT_NOT_AVAILABLE_MSG, DISCLAIMER_MESSAGE, INVALID_RESPONSE, NO_PROMPT_MESSAGE, PAC_AUTH_INPUT, PAC_AUTH_NOT_FOUND, POWERPAGES_CHAT_PARTICIPANT_ID, RESPONSE_AWAITED_MSG, RESPONSE_SCENARIOS, SKIP_CODES, STATER_PROMPTS, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ERROR, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_INVOKED, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ORG_DETAILS, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ORG_DETAILS_NOT_FOUND, VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_SCENARIO, WELCOME_MESSAGE, WELCOME_PROMPT } from './PowerPagesChatParticipantConstants';
import { ORG_DETAILS_KEY, handleOrgChangeSuccess, initializeOrgDetails } from '../../utilities/OrgHandlerUtils';
import { createAndReferenceLocation, getComponentInfo, getEndpoint, provideChatParticipantFollowups, handleChatParticipantFeedback, createErrorResult, createSuccessResult } from './PowerPagesChatParticipantUtils';
import { createAndReferenceLocation, getComponentInfo, getEndpoint, provideChatParticipantFollowups, handleChatParticipantFeedback, createErrorResult, createSuccessResult, removeChatVariables } from './PowerPagesChatParticipantUtils';
import { checkCopilotAvailability, fetchRelatedFiles, getActiveEditorContent } from '../../utilities/Utils';
import { IIntelligenceAPIEndpointInformation } from '../../services/Interfaces';
import { v4 as uuidv4 } from 'uuid';
@ -87,10 +87,14 @@ export class PowerPagesChatParticipant {
//_token: vscode.CancellationToken
): Promise<IPowerPagesChatResult> => {
try {
stream.progress(RESPONSE_AWAITED_MSG);
this.telemetry.sendTelemetryEvent(VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_INVOKED, { sessionId: this.powerPagesAgentSessionId });
await this.initializeOrgDetails();
if (!this.isOrgDetailsInitialized) {
stream.progress(PAC_AUTH_INPUT);
await this.initializeOrgDetails();
}
stream.progress(RESPONSE_AWAITED_MSG);
if (!this.orgID || !this.environmentID) {
this.telemetry.sendTelemetryEvent(VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_ORG_DETAILS_NOT_FOUND, { sessionId: this.powerPagesAgentSessionId });
@ -114,7 +118,9 @@ export class PowerPagesChatParticipant {
return createErrorResult(COPILOT_NOT_AVAILABLE_MSG, RESPONSE_SCENARIOS.COPILOT_NOT_AVAILABLE, this.orgID);
}
const userPrompt = request.prompt;
let userPrompt = request.prompt;
userPrompt = removeChatVariables(userPrompt);
if (userPrompt === WELCOME_PROMPT) {
stream.markdown(WELCOME_MESSAGE);
@ -193,11 +199,20 @@ export class PowerPagesChatParticipant {
}
};
private async initializeOrgDetails(): Promise<void> {
const { orgID, orgUrl, environmentID } = await initializeOrgDetails(this.isOrgDetailsInitialized, this.extensionContext, this._pacWrapper);
this.orgID = orgID;
this.orgUrl = orgUrl;
this.environmentID = environmentID;
private async initializeOrgDetails(): Promise<void> {
try {
const { orgID, orgUrl, environmentID } = await initializeOrgDetails(this.isOrgDetailsInitialized, this.extensionContext, this._pacWrapper);
if (!orgID) {
return;
}
this.orgID = orgID;
this.orgUrl = orgUrl;
this.environmentID = environmentID;
this.isOrgDetailsInitialized = true;
} catch (error) {
return;
}
}
private async handleOrgChangeSuccess(orgDetails: ActiveOrgOutput): Promise<void> {

Просмотреть файл

@ -25,7 +25,7 @@ export const RESPONSE_SCENARIOS = {
WEB_API_PROMPT: 'WEB_API_PROMPT',
WELCOME_PROMPT: 'WELCOME_PROMPT'
};
// Localized strings
export const EXPLAIN_CODE_PROMPT = vscode.l10n.t('Explain the following code {% include \'Page Copy\'%}');
export const WEB_API_PROMPT = vscode.l10n.t('Write web API code to query active contact records.');
@ -39,6 +39,7 @@ export const PAC_AUTH_NOT_FOUND = vscode.l10n.t('Active auth profile is not foun
export const INVALID_RESPONSE = vscode.l10n.t('Something went wrong. Dont worry, you can try again.');
export const DISCLAIMER_MESSAGE = vscode.l10n.t('Make sure AI-generated content is accurate and appropriate before using. [Learn more](https://go.microsoft.com/fwlink/?linkid=2240145) | [View terms](https://go.microsoft.com/fwlink/?linkid=2189520)');
export const NO_PROMPT_MESSAGE = vscode.l10n.t('Hi! Power Pages lets you build secure, professional websites that you can quickly configure and publish across web browsers and devices.\n\nTo create your website, visit the [Power Pages](https://powerpages.microsoft.com/).\nReturn to this chat and @powerpages can help you write and edit your website code.');
export const PAC_AUTH_INPUT = vscode.l10n.t("Checking for active auth profile...");
// Telemetry Event Names
export const VSCODE_EXTENSION_GITHUB_POWER_PAGES_AGENT_INVOKED = 'GitHubPowerPagesAgentInvoked';

Просмотреть файл

@ -110,3 +110,16 @@ export function createSuccessResult(command: string, scenario: string, orgId: st
};
}
export function removeChatVariables(userPrompt: string): string {
const variablesToRemove = [
'#editor',
'#selection',
'#terminalLastCommand',
'#terminalSelection',
'#vscodeAPI'
];
const regex = new RegExp(variablesToRemove.join('|'), 'g');
return userPrompt.replace(regex, '').trim();
}

Просмотреть файл

@ -9,6 +9,7 @@ import { PacWrapper } from '../../client/pac/PacWrapper';
import { IOrgDetails } from '../chat-participants/powerpages/PowerPagesChatParticipantTypes';
import { SUCCESS } from '../constants';
import { createAuthProfileExp } from '../copilot/utils/copilotUtil';
import { ERROR_CONSTANTS } from '../ErrorConstants';
export const ORG_DETAILS_KEY = 'orgDetails';
@ -16,46 +17,52 @@ export function handleOrgChangeSuccess(
orgDetails: ActiveOrgOutput,
extensionContext: ExtensionContext
): IOrgDetails {
const orgID = orgDetails.OrgId;
const orgUrl = orgDetails.OrgUrl;
const environmentID = orgDetails.EnvironmentId;
const { OrgId: orgID, OrgUrl: orgUrl, EnvironmentId: environmentID } = orgDetails;
extensionContext.globalState.update(ORG_DETAILS_KEY, { orgID, orgUrl, environmentID });
return { orgID, orgUrl, environmentID };
}
async function fetchOrgDetailsFromPac(pacWrapper: PacWrapper, extensionContext: ExtensionContext): Promise<IOrgDetails> {
const pacActiveOrg = await pacWrapper.activeOrg();
if (pacActiveOrg && pacActiveOrg.Status === SUCCESS) {
return handleOrgChangeSuccess(pacActiveOrg.Results, extensionContext);
}
throw new Error(ERROR_CONSTANTS.PAC_AUTH_FAILED);
}
export async function initializeOrgDetails(
isOrgDetailsInitialized: boolean,
extensionContext: ExtensionContext,
pacWrapper?: PacWrapper
): Promise<{ orgID: string, orgUrl: string, environmentID: string }> {
): Promise<IOrgDetails> {
const orgDetails: IOrgDetails = { orgID: '', orgUrl: '', environmentID: '' };
if (isOrgDetailsInitialized) {
return { orgID: '', orgUrl: '', environmentID: '' };
return orgDetails;
}
const orgDetails: IOrgDetails | undefined = extensionContext.globalState.get(ORG_DETAILS_KEY);
let orgID = '';
let orgUrl = '';
let environmentID = '';
// Get stored organization details from global state
const storedOrgDetails: IOrgDetails | undefined = extensionContext.globalState.get(ORG_DETAILS_KEY);
if (storedOrgDetails && storedOrgDetails.orgID && storedOrgDetails.orgUrl && storedOrgDetails.environmentID) {
return storedOrgDetails;
}
if (orgDetails && orgDetails.orgID && orgDetails.orgUrl && orgDetails.environmentID) {
orgID = orgDetails.orgID;
orgUrl = orgDetails.orgUrl;
environmentID = orgDetails.environmentID;
} else {
if (pacWrapper) {
const pacActiveOrg = await pacWrapper.activeOrg();
if (pacActiveOrg && pacActiveOrg.Status === SUCCESS) {
const orgDetails = handleOrgChangeSuccess(pacActiveOrg.Results, extensionContext);
orgID = orgDetails.orgID;
orgUrl = orgDetails.orgUrl;
environmentID = orgDetails.environmentID;
} else {
await createAuthProfileExp(pacWrapper);
}
if (pacWrapper) {
try {
const fetchedOrgDetails = await fetchOrgDetailsFromPac(pacWrapper, extensionContext);
orgDetails.orgID = fetchedOrgDetails.orgID;
orgDetails.orgUrl = fetchedOrgDetails.orgUrl;
orgDetails.environmentID = fetchedOrgDetails.environmentID;
} catch (error) {
await createAuthProfileExp(pacWrapper);
const fetchedOrgDetails = await fetchOrgDetailsFromPac(pacWrapper, extensionContext);
orgDetails.orgID = fetchedOrgDetails.orgID;
orgDetails.orgUrl = fetchedOrgDetails.orgUrl;
orgDetails.environmentID = fetchedOrgDetails.environmentID;
}
}
return { orgID, orgUrl, environmentID };
return orgDetails;
}