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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const msAppIdRegex = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A
export interface CreateSkillModalProps {
projectId: string;
addRemoteSkill: (manifestUrl: string, endpointName: string) => Promise<void>;
addTriggerToRoot: (dialogId: string, triggerFormData: TriggerFormData, skillId: string) => void;
addTriggerToRoot: (dialogId: string, triggerFormData: TriggerFormData, skillId: string) => Promise<void>;
onDismiss: () => void;
}

Expand All @@ -62,9 +62,6 @@ export const getSkillManifest = async (projectId: string, manifestUrl: string, s
},
});
setSkillManifest(data);
if (!data.dispatchModels) {
setFormDataErrors({ manifestUrl: formatMessage('Miss dispatch modal') });
}
} catch (error) {
setFormDataErrors({ ...error, manifestUrl: formatMessage('Manifest URL can not be accessed') });
}
Expand Down Expand Up @@ -141,23 +138,23 @@ export const CreateSkillModal: React.FC<CreateSkillModalProps> = (props) => {
[projectId, formData]
);

const handleSubmit = (event, content: string, enable: boolean) => {
const handleSubmit = async (event, content: string, enable: boolean) => {
event.preventDefault();
// add a remote skill, add skill identifier into botProj file
addRemoteSkill(formData.manifestUrl, formData.endpointName).then(() => {
TelemetryClient.track('AddNewSkillCompleted');
const skillId = location.href.match(/skill\/([^/]*)/)?.[1];
if (skillId) {
// add trigger with connect to skill action to root bot
const triggerFormData = getTriggerFormData(skillManifest.name, content);
addTriggerToRoot(dialogId, triggerFormData, skillId);
TelemetryClient.track('AddNewTriggerCompleted', { kind: 'Microsoft.OnIntent' });
}
});
await addRemoteSkill(formData.manifestUrl, formData.endpointName);
TelemetryClient.track('AddNewSkillCompleted');
// if added remote skill fail, just not addTrigger to root.
const skillId = location.href.match(/skill\/([^/]*)/)?.[1];
if (skillId) {
// add trigger with connect to skill action to root bot
const triggerFormData = getTriggerFormData(skillManifest.name, content);
await addTriggerToRoot(dialogId, triggerFormData, skillId);
TelemetryClient.track('AddNewTriggerCompleted', { kind: 'Microsoft.OnIntent' });
}

if (enable) {
// update recognizor type to orchestrator
updateRecognizer(projectId, dialogId, SDKKinds.OrchestratorRecognizer);
await updateRecognizer(projectId, dialogId, SDKKinds.OrchestratorRecognizer);
}
};

Expand Down Expand Up @@ -246,9 +243,11 @@ export const CreateSkillModal: React.FC<CreateSkillModalProps> = (props) => {
<StackItem align={'end'}>
<DefaultButton data-testid="SkillFormCancel" text={formatMessage('Cancel')} onClick={onDismiss} />
{skillManifest ? (
isUsingAdaptiveRuntime(runtime) && luFiles.length > 0 ? (
isUsingAdaptiveRuntime(runtime) &&
luFiles.length > 0 &&
skillManifest.dispatchModels?.intents?.length > 0 ? (
<PrimaryButton
disabled={formDataErrors.manifestUrl || !skillManifest.dispatchModels ? true : false}
disabled={formDataErrors.manifestUrl ? true : false}
styles={buttonStyle}
text={formatMessage('Next')}
onClick={(event) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type SelectIntentProps = {
luFeatures: ILUFeaturesConfig;
rootLuFiles: LuFile[];
dialogId: string;
onSubmit: (event: Event, content: string, enable: boolean) => void;
onSubmit: (event: Event, content: string, enable: boolean) => Promise<void>;
onDismiss: () => void;
onUpdateTitle: (title: { title: string; subText: string }) => void;
onBack: () => void;
Expand Down Expand Up @@ -167,28 +167,25 @@ export const SelectIntent: React.FC<SelectIntentProps> = (props) => {
return res;
}, [manifest]);

const updateLuFiles = useCallback(() => {
const updateLuFiles = useCallback(async () => {
const payloads: { projectId: string; id: string; content: string }[] = [];
for (const lufile of rootLuFiles) {
const rootId = lufile.id.split('.');
const language = rootId[rootId.length - 1];
let append = '';
if (language === locale) {
append = displayContent;
} else {
if (language !== locale) {
const intents = multiLanguageIntents[language];
if (!intents) {
continue;
}
append = mergeIntentsContent(intents);
const append = mergeIntentsContent(intents);
payloads.push({
projectId,
id: lufile.id,
content: `${lufile.content}\n# ${manifest.name}\n${append}`,
});
}
payloads.push({
projectId,
id: lufile.id,
content: `${lufile.content}\n# ${manifest.name}\n${append}`,
});
}
batchUpdateLuFiles(payloads);
await batchUpdateLuFiles(payloads);
}, [rootLuFiles, projectId, locale, displayContent, multiLanguageIntents]);

useEffect(() => {
Expand Down Expand Up @@ -259,11 +256,11 @@ export const SelectIntent: React.FC<SelectIntentProps> = (props) => {
}
}, [displayContent]);

const handleSubmit = (ev, enableOchestractor) => {
// append remote lufile into root lu file
updateLuFiles();
const handleSubmit = async (ev, enableOchestractor) => {
// add trigger to root
onSubmit(ev, displayContent, enableOchestractor);
await onSubmit(ev, displayContent, enableOchestractor);
// append remote lufile into different language lu file
await updateLuFiles();
};

return (
Expand Down
5 changes: 3 additions & 2 deletions Composer/packages/client/src/pages/design/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ const Modals: React.FC<ModalsProps> = ({ projectId = '' }) => {
setAddSkillDialogModalVisibility(false);
await addRemoteSkillToBotProject(manifestUrl, endpointName);
}}
addTriggerToRoot={(dialogId, formData, skillId) => {
createTriggerForRemoteSkill(projectId, dialogId, formData, skillId, false);
addTriggerToRoot={async (dialogId, formData, skillId) => {
await createTriggerForRemoteSkill(projectId, dialogId, formData, skillId);
commitChanges();
}}
projectId={projectId}
onDismiss={() => {
Expand Down
2 changes: 1 addition & 1 deletion Composer/packages/client/src/pages/design/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ const SideBar: React.FC<SideBarProps> = React.memo(({ projectId }) => {
: await OpenConfirmModal(formatMessage('Warning'), removeSkillDialog().subTextNoUse);

if (!confirmRemove) return;
removeSkillFromBotProject(skillId);
await removeSkillFromBotProject(skillId);
}

const selectedTrigger = currentDialog?.triggers.find((t) => t.id === selected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const botProjectFileDispatcher = () => {
);
}
});
setRootBotSettingState(callbackHelpers, rootBotProjectId, updatedSettings);
await setRootBotSettingState(callbackHelpers, rootBotProjectId, updatedSettings);
}
});

Expand Down
38 changes: 20 additions & 18 deletions Composer/packages/client/src/recoilModel/dispatchers/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,8 @@ export const projectDispatcher = () => {
const { set, snapshot } = callbackHelpers;

const dispatcher = await snapshot.getPromise(dispatcherState);
const projectDialogsMap = await snapshot.getPromise(projectDialogsMapSelector);
const rootBotProjectId = await snapshot.getPromise(rootBotProjectIdSelector);
// const manifestIdentifier = await snapshot.getPromise(botNameIdentifierState(projectIdToRemove));
const triggerName = await snapshot.getPromise(botDisplayNameState(projectIdToRemove));
const rootDialog = rootBotProjectId && projectDialogsMap[rootBotProjectId].find((dialog) => dialog.isRoot);
// remove the same identifier trigger in root bot
if (rootBotProjectId && rootDialog && rootDialog.triggers.length > 0) {
const index = rootDialog.triggers.findIndex((item) => item.displayName === triggerName);
const content = DialogdeleteTrigger(
projectDialogsMap[rootBotProjectId],
rootDialog?.id,
index,
async (trigger) => await dispatcher.deleteTrigger(rootBotProjectId, rootDialog?.id, trigger)
);
if (content) {
await dispatcher.updateDialog({ id: rootDialog?.id, content, projectId: rootBotProjectId });
}
}
const projectDialogsMap = await snapshot.getPromise(projectDialogsMapSelector);

await dispatcher.removeSkillFromBotProjectFile(projectIdToRemove);
const botRuntimeOperations = await snapshot.getPromise(botRuntimeOperationsSelector);
Expand All @@ -99,7 +83,25 @@ export const projectDispatcher = () => {
const filtered = currentProjects.filter((id) => id !== projectIdToRemove);
return filtered;
});
resetBotStates(callbackHelpers, projectIdToRemove);
await resetBotStates(callbackHelpers, projectIdToRemove);

const triggerName = await snapshot.getPromise(botDisplayNameState(projectIdToRemove));
const rootDialog = rootBotProjectId && projectDialogsMap[rootBotProjectId].find((dialog) => dialog.isRoot);
// remove the same identifier trigger in root bot
if (rootBotProjectId && rootDialog && rootDialog.triggers.length > 0) {
const index = rootDialog.triggers.findIndex((item) => item.displayName === triggerName);
if (index >= 0) {
const content = DialogdeleteTrigger(
projectDialogsMap[rootBotProjectId],
rootDialog?.id,
index,
async (trigger) => await dispatcher.deleteTrigger(rootBotProjectId, rootDialog?.id, trigger)
);
if (content) {
await dispatcher.updateDialog({ id: rootDialog?.id, content, projectId: rootBotProjectId });
}
}
}
if (rootBotProjectId) {
navigateToBot(callbackHelpers, rootBotProjectId, '');
}
Expand Down