问题
I have a dialog where I delegate Alexa to collect two slots and ask the confirmation prompt. If the user says "no" to the confirmation prompt, I want to restart the dialog by deleting the slot values and setting the intent confirmationStatus to "NONE".
While Alexa starts to elicit the first slot, the confirmation status remains as "DENIED" which leads to a loop. I used the method described here to reset the status.
This is the updated intent sent back from my skill
{
"name": "StartSingleGameIntent",
"confirmationStatus": "NONE",
"slots": {
"player_one": {
"name": "player_one",
"confirmationStatus": "NONE",
"source": "USER"
},
"player_two": {
"name": "player_two",
"confirmationStatus": "NONE",
"source": "USER"
}
}
}
But the next request still has the "DENIED" status:
{
"name": "StartSingleGameIntent",
"confirmationStatus": "DENIED",
"slots": {
"player_one": {
"name": "player_one",
"value": "ben",
"confirmationStatus": "NONE",
"source": "USER"
},
"player_two": {
"name": "player_two",
"confirmationStatus": "NONE"
}
}
}
Here are my handlers:
const StartSingleGameStartedIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
Alexa.getIntentName(handlerInput.requestEnvelope) === 'StartGameIntent' &&
Alexa.getDialogState(handlerInput.requestEnvelope) === 'STARTED';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDelegateDirective(handlerInput.requestEnvelope.request.intent).getResponse();
}
};
const StartSingleGameInProgressIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
Alexa.getIntentName(handlerInput.requestEnvelope) === 'StartGameIntent' &&
Alexa.getDialogState(handlerInput.requestEnvelope) === 'IN_PROGRESS';
},
handle(handlerInput) {
const currentIntent = handlerInput.requestEnvelope.request.intent;
console.log("Dialog in progress %s", JSON.stringify(currentIntent));
if (currentIntent.confirmationStatus === "DENIED") {
let intent = handlerInput.requestEnvelope.request.intent;
intent.confirmationStatus = "NONE";
Object.keys(intent.slots).forEach(slotName => {
const slot = intent.slots[slotName];
delete slot.value;
});
console.log("New intent %s", JSON.stringify(intent));
const speechText = "Ok, let's try again";
return handlerInput.responseBuilder
.speak(speechText)
.addDirective({
type: "Dialog.Delegate",
updatedIntent: intent
})
.getResponse();
}
// if Intent is confirmed, delegate to complete dialog
return handlerInput.responseBuilder.addDelegateDirective(currentIntent).getResponse();
}
};
const StartSingleGameCompletedIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' &&
Alexa.getIntentName(handlerInput.requestEnvelope) === 'StartGameIntent' &&
Alexa.getDialogState(handlerInput.requestEnvelope) === 'COMPLETED';
},
handle(handlerInput) {
console.log("Status COMPLETED");
const currentIntent = handlerInput.requestEnvelope.request.intent;
const playerOne = currentIntent.slots.player_one.value;
const playerTwo = currentIntent.slots.player_two.value;
const speech = 'Ok, ' + playerOne + ' versus ' + playerTwo + '!';
return handlerInput.responseBuilder.speak(speech).withShouldEndSession(true).getResponse();
}
};
And here is the relevant part from the interaction model
{
"interactionModel": {
"languageModel": {
"invocationName": "kicker tracker",
"intents": [
{
"name": "StartSingleGameIntent",
"slots": [
{
"name": "player_one",
"type": "AMAZON.FirstName",
"samples": [
"{player_one}"
]
},
{
"name": "player_two",
"type": "AMAZON.FirstName",
"samples": [
"{player_two}"
]
}
],
"samples": [
"{player_one} versus {player_two}",
"{player_one} against {player_two}"
]
}
],
"types": []
},
"dialog": {
"intents": [
{
"name": "StartGameIntent",
"delegationStrategy": "SKILL_RESPONSE",
"confirmationRequired": true,
"prompts": {
"confirmation": "Confirm.Intent.331442628749"
},
"slots": [
{
"name": "player_one",
"type": "AMAZON.FirstName",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.1074854715089.1393950695631"
}
},
{
"name": "player_two",
"type": "AMAZON.FirstName",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.1074854715089.404108193608"
}
}
]
}
],
"delegationStrategy": "ALWAYS"
},
"prompts": [
{
"id": "Elicit.Slot.1074854715089.1393950695631",
"variations": [
{
"type": "PlainText",
"value": "Who is the first player?"
}
]
},
{
"id": "Elicit.Slot.1074854715089.404108193608",
"variations": [
{
"type": "PlainText",
"value": "Who plays against {player_one} ?"
}
]
},
{
"id": "Confirm.Intent.331442628749",
"variations": [
{
"type": "PlainText",
"value": "{player_one} versus {player_two}, correct?"
}
]
}
]
}
}
来源:https://stackoverflow.com/questions/59895154/intent-confirmationstatus-cannot-be-changed-with-dialog-delegate-directive