diff --git a/.vscode/launch.json b/.vscode/launch.json index 68765b6af..670087730 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,7 @@ "999999", "--colors", "-g", - ".*addAsync.*" + "Test.0600 OrchestratorHelper.parseLuFile()" ], "cwd": "${workspaceFolder}/packages/orchestratorlib", "internalConsoleOptions": "openOnSessionStart", diff --git a/packages/orchestrator/src/commands/orchestrator/create.ts b/packages/orchestrator/src/commands/orchestrator/create.ts index 1990d4a5b..c4e0624bf 100644 --- a/packages/orchestrator/src/commands/orchestrator/create.ts +++ b/packages/orchestrator/src/commands/orchestrator/create.ts @@ -81,7 +81,7 @@ export default class OrchestratorCreate extends Command { settings.SnapshotPath = snapshotFilePath; settings.persist(); } catch (error) { - throw (new CLIError(error)); + throw (new CLIError(error as Error)); } } diff --git a/packages/orchestratorlib/src/orchestratorhelper.ts b/packages/orchestratorlib/src/orchestratorhelper.ts index 5b3d74d43..790a142da 100644 --- a/packages/orchestratorlib/src/orchestratorhelper.ts +++ b/packages/orchestratorlib/src/orchestratorhelper.ts @@ -352,7 +352,7 @@ export class OrchestratorHelper { default: throw new Error(`Unknown file type ${ext}`); } - } catch (error) { + } catch (error: any) { throw new Error(`${error.message}${os.EOL}Failed to parse ${filePath}`); } } @@ -421,15 +421,15 @@ export class OrchestratorHelper { if (!luContent || luContent.length === 0) { return; } - const luObject: any = { - content: luContent, - id: luFile, - }; - const luisObject: any = await LuisBuilder.fromLUAsync([luObject], OrchestratorHelper.findLuFiles); - if (Utility.toPrintDetailedDebuggingLogToConsole) { - UtilityDispatcher.debuggingNamedLog1('OrchestratorHelper.parseLuContent(): calling getIntentsEntitiesUtterances()', luisObject, 'luisObject'); - } try { + const luObject: any = { + content: luContent, + id: luFile, + }; + const luisObject: any = await LuisBuilder.fromLUAsync([luObject], OrchestratorHelper.findLuFiles); + if (Utility.toPrintDetailedDebuggingLogToConsole) { + UtilityDispatcher.debuggingNamedLog1('OrchestratorHelper.parseLuContent(): calling getIntentsEntitiesUtterances()', luisObject, 'luisObject'); + } const rvLu: boolean = OrchestratorHelper.getIntentsEntitiesUtterances( luisObject, hierarchicalLabel, @@ -440,9 +440,8 @@ export class OrchestratorHelper { if (!rvLu) { throw new Error('Failed to parse LUIS or JSON file on intent/entity labels'); } - } catch (error) { - Utility.debuggingLog(`EXCEPTION calling getIntentsEntitiesUtterances(), error=${error}`); - throw error; + } catch (error: any) { + throw new Error(`Failed parsing lu file ${luFile} ${error.text}`); } } @@ -602,20 +601,19 @@ export class OrchestratorHelper { return; } - const newlines: string[] = []; - lines.forEach((line: string) => { - if (line.toLowerCase().indexOf('@qna.pair.source =') < 0) { - newlines.push(line); - } - }); - - // Utility.debuggingLog('OrchestratorHelper.parseQnaFile() ready to call QnaMakerBuilder.fromContent()'); - const qnaNormalized: string = Utility.cleanStringOnTabs(newlines.join('\n')); // ---- NOTE ---- QnaMakerBuilder does not like TAB - const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); - if (qnaObject) { + try { + const newlines: string[] = []; + lines.forEach((line: string) => { + if (line.toLowerCase().indexOf('@qna.pair.source =') < 0) { + newlines.push(line); + } + }); + // Utility.debuggingLog('OrchestratorHelper.parseQnaFile() ready to call QnaMakerBuilder.fromContent()'); + const qnaNormalized: string = Utility.cleanStringOnTabs(newlines.join('\n')); // ---- NOTE ---- QnaMakerBuilder does not like TAB + const qnaObject: any = await QnaMakerBuilder.fromContent(qnaNormalized); OrchestratorHelper.getQnaQuestionsAsUtterances(qnaObject, hierarchicalLabel, utteranceLabelsMap, utteranceLabelDuplicateMap); - } else { - throw new Error(`Failed parsing qna file ${qnaFile}`); + } catch (error: any) { + throw new Error(`Failed parsing qna file ${qnaFile} ${error.text}`); } } diff --git a/packages/orchestratorlib/test/fixtures/parser/invalid.lu b/packages/orchestratorlib/test/fixtures/parser/invalid.lu new file mode 100644 index 000000000..638d8a8cd --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/invalid.lu @@ -0,0 +1,17 @@ + +> LUIS application information +> !# @app.name = Weather +> !# @app.desc = Weather LUIS application - Bot Builder Samples +> !# @app.versionId = 0.1 +> !# @app.culture = en-us +> !# @app.luis_schema_version = 4.0.0 + + +> # Intent definitions +- current weather ? +- do {@Location=florida} residents usually need ice + +## Get Weather Forecast +- forecast in celcius +- get the forcast for me +- i want to know the temperature at {@Location=death valley} \ No newline at end of file diff --git a/packages/orchestratorlib/test/fixtures/parser/invalid.qna b/packages/orchestratorlib/test/fixtures/parser/invalid.qna new file mode 100644 index 000000000..8d4c5c016 --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/invalid.qna @@ -0,0 +1,10 @@ +**Prompts:** +- [Files that Cannot Sync +](#1) + + + +## ? Files that Cannot Sync +``` +Files that cannot sync. +``` diff --git a/packages/orchestratorlib/test/fixtures/parser/valid.lu b/packages/orchestratorlib/test/fixtures/parser/valid.lu new file mode 100644 index 000000000..e755da466 --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/valid.lu @@ -0,0 +1,71 @@ + +> LUIS application information +> !# @app.name = Weather +> !# @app.desc = Weather LUIS application - Bot Builder Samples +> !# @app.versionId = 0.1 +> !# @app.culture = en-us +> !# @app.luis_schema_version = 4.0.0 + + +> # Intent definitions + +## Get Weather Condition +- current weather ? +- do {@Location=florida} residents usually need ice scrapers +- get {@Location=florence} temperature in september +- get for me the weather conditions in {@Location=sonoma county} +- get the daily temperature {@Location=greenwood indiana} +- get the weather at {@Location=saint george utah} +- how much rain does {@Location=chambersburg} get a year +- show average rainfall for {@Location=boise} +- temperature of {@Location=delhi} in celsius please +- was last year about this time as wet as it is now in the {@Location=south} ? +- what is the rain volume in {@Location=sonoma county} ? +- what to wear in march in {@Location=california} +- what's the weather like in {@Location=minneapolis} +- weather in {@Location_PatternAny} +- how's the weather in {@Location_PatternAny} +- current weather in {@Location_PatternAny} + + +## Get Weather Forecast +- forecast in celcius +- get the forcast for me +- i want to know the temperature at {@Location=death valley} +- provide me by {@Location=toronto} weather please +- show me the forecast at {@Location=alabama} +- soliciting today's weather +- what is the weather in {@Location=redmond} ? +- what is the weather today at 10 day {@Location=durham} ? +- what will the weather be tomorrow in {@Location=new york} ? +- what's the weather going to be like in {@Location=hawaii} ? +- will it be raining in {@Location=ranchi} +- will it rain this weekend +- will it snow today +- what's the forecast for next week in {@Location_PatternAny} +- show me the forecast for {@Location_PatternAny} +- what's the forecast for {@Location_PatternAny} + + +## None + + +> # Entity definitions + +@ ml Location + + +> # PREBUILT Entity definitions + + +> # Phrase list definitions + + +> # List entities + +> # RegEx entities + + +> # Pattern.Any entities + +@ patternany Location_PatternAny diff --git a/packages/orchestratorlib/test/fixtures/parser/valid.qna b/packages/orchestratorlib/test/fixtures/parser/valid.qna new file mode 100644 index 000000000..ff959c68a --- /dev/null +++ b/packages/orchestratorlib/test/fixtures/parser/valid.qna @@ -0,0 +1,22 @@ +# ?store hours +``` +Most our stores are open M-F 9AM-10PM. +``` +**Prompts:** +- [Seattle store](#1) +- [Portland store](#2) + + + +# ?seattle +``` +The Seattle store is open M-F 9AM-10PM. +``` + + + +# ?when is the portland store open +- portland store hours +``` +The Portland store is open 24/7. +``` \ No newline at end of file diff --git a/packages/orchestratorlib/test/orchestratorhelper.test.ts b/packages/orchestratorlib/test/orchestratorhelper.test.ts index 251734514..19b03cbf9 100644 --- a/packages/orchestratorlib/test/orchestratorhelper.test.ts +++ b/packages/orchestratorlib/test/orchestratorhelper.test.ts @@ -425,7 +425,6 @@ describe('Test Suite - orchestratorhelper', () => { assert.ok((utteranceEntityLabelsMap.get(utterance) as Label[]).length === 3, `(utteranceEntityLabelsMap.get(utterance) as Label[]).length=${(utteranceEntityLabelsMap.get(utterance) as Label[]).length}`); }); - it('Test.0300 OrchestratorHelper.getJsonIntentEntityScoresUtterances()', function () { Utility.resetFlagToPrintDebuggingLogToConsole(UnitTestHelper.getDefaultUnitTestDebuggingLogFlag()); this.timeout(UnitTestHelper.getDefaultUnitTestTimeout()); @@ -588,4 +587,54 @@ describe('Test Suite - orchestratorhelper', () => { assert.ok(result.has('Add item'), 'Incorrect result from getUtteranceLabelsMap, missing Add item utterance'); assert.ok(result.has('delete to do go shopping'), 'Incorrect result from getUtteranceLabelsMap, missing delete to do go shopping utterance'); }); + it('Test.0600 OrchestratorHelper.parseQnaFile()', async () => { + const validFile: string = './test/fixtures/parser/valid.qna'; + const inValidFile: string = './test/fixtures/parser/invalid.qna'; + const utteranceLabelsMap: Map> = new Map>(); + const utteranceLabelDuplicateMap: Map> = new Map>(); + try { + await OrchestratorHelper.parseQnaFile( + inValidFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap); + assert.fail('Invalid syntax exception is not thrown.'); + } catch {} + assert.ok(utteranceLabelsMap.size === 0); + await OrchestratorHelper.parseQnaFile( + validFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap); + assert.ok(utteranceLabelsMap.size > 0); + }); + it('Test.0600 OrchestratorHelper.parseLuFile()', async () => { + const validFile: string = './test/fixtures/parser/valid.lu'; + const inValidFile: string = './test/fixtures/parser/invalid.lu'; + const utteranceLabelsMap: Map> = new Map>(); + const utteranceLabelDuplicateMap: Map> = new Map>(); + const utteranceEntityLabelsMap: Map = new Map(); + const utteranceEntityLabelDuplicateMap: Map = new Map(); + + try { + await OrchestratorHelper.parseLuFile( + inValidFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap, + utteranceEntityLabelsMap, + utteranceEntityLabelDuplicateMap); + assert.fail('Invalid syntax exception is not thrown.'); + } catch {} + assert.ok(utteranceLabelsMap.size === 0); + + await OrchestratorHelper.parseLuFile( + validFile, + '', + utteranceLabelsMap, + utteranceLabelDuplicateMap, + utteranceEntityLabelsMap, + utteranceEntityLabelDuplicateMap); + assert.ok(utteranceLabelsMap.size > 0); + }); });