问题
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {WebhookClient} = require('dialogflow-fulfillment');
process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements
admin.initializeApp({
credential: admin.credential.applicationDefault(),
databaseURL: "https://my_db.firebaseio.com/",
});
var database = admin.database();
var transition = database.ref('/stage');
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
console.log('Inside :) yessssssss !');
const agent = new WebhookClient({ request, response });
function moveToStage (agent) {
transition.set('2');
agent.add('Welcome to xx console. Please accept the notification on your watch');
}
transition.on('value', (snapshot) => {
console.log("Reading value succesfully from firebase");
console.log(snapshot.val());
if(snapshot.val() == '3'){
agent.add('Thank you for granting me the access.');
// OR
// response.setHeader('Content-Type','applicaiton/json');
// response.send(JSON.stringify({"fulfillmentText": 'Thank you for granting me the access.'}));
}
});
let intentMap = new Map();
intentMap.set('welcome_and_ask_to_sync', moveToStage);
agent.handleRequest(intentMap);
});
I have an intent welcome_and_ask_to_sync
, which has webhook activated.
When that Intent is fired by a successful voice input, it reponds with a text/voice from the agent and updates a field stage
in the respective firebase DB.
Now another external application, under some circumstences, updates that stage
field in the firebase DB.
No this this part in the fulfillment code, wtahces that change
transition.on('value', (snapshot) => {
console.log("Reading value succesfully from firebase");
console.log(snapshot.val());
if(snapshot.val() == '3'){
agent.add('Thank you for granting me the access.');
// OR
// response.setHeader('Content-Type','applicaiton/json');
// response.send(JSON.stringify({"fulfillmentText": 'Thank you for granting me the access.'}));
}
});
The intention here is to then make google home speak something, like in thsi case Thank you for granting me the access.
.
NOTE: I do not need an intent to be fired (sorry for the confusion earlier). I just need google home voice agent to acknowledge this change/trigger.
Now when I watch the logs, I see it breaks here agent.add('Thank you for granting me the access.');
And the err log si somewhat like:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11)
at transition.on (/user_code/index.js:36:22)
at /user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:4465:22
at exceptionGuard (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:691:9)
at EventList.raise (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:9727:17)
at EventQueue.raiseQueuedEventsMatchingPredicate_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:9681:41)
at EventQueue.raiseEventsForChangedPath (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:9665:14)
at Repo.onDataUpdate_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:12770:26)
at PersistentConnection.onDataPush_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:12070:18)
at PersistentConnection.onDataMessage_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:12064:18)
So the basic question remains: How can I make the agent speak/update text response and acknowledge on that DB's field change.
回答1:
The short answer is that you can't - certainly not the way you're doing it.
Once a response is sent from your webhook back to Dialogflow, the HTTPS connection is closed, and any further replies will generate the error that you see.
Furthermore, the conversational model used by AoG and Dialogflow is that the user must always initiate each round of the conversation. It is not possible for AoG to "announce" something at this point. That would be considered somewhat invasive.
You can send a notification through Actions on Google, which would re-start the conversation when the user acknowledged the notification. However, notifications are only sent to smartphones - not to speakers. So this may not meet your needs.
If you're expecting just a few updates that take place fairly quickly after the initial send, you may want to see if you can use a Media Response to keep the conversation going with "hold music" while you wait for more updates. When the "hold music" ends, it will send an event to your Action, and you can either re-start the hold music or reply. In this case, you wouldn't use the .on()
method for updates to come in, but would have to check each time the Media finishes playing to see if there have been updates that are unsent.
来源:https://stackoverflow.com/questions/53532915/how-to-make-a-dialogflow-google-agent-respond-and-acknowledge-on-firebases-fiel