Разрешения Google Assistant не сохраняются между запросами

С помощью API.AI и Google Assistant я запрашиваю разрешение на получение имени и местоположения пользователя. Намерение состоит в том, что я смогу один раз запросить разрешение, и последующие запросы к моему действию не будут нуждаться в повторном запросе (поскольку каждый раз, когда пользователь обращается к моему действию, это приведет к очень громкой беседе).

То, что я нахожу, - то, что я только получаю информацию в намерении, связанном с actions_intent_PERMISSION - информация не отправляется в других целях, даже если я уже дал разрешение. (В приведенном ниже примере кода - в конечном итоге повторный запрос разрешения для всех других намерений.)

Я также не вижу, чтобы это разрешение поддерживалось между вызовами моего Действия. Поэтому каждый раз, когда Действие запускается, их (снова) спрашивают, дают ли они разрешение на действие.

Оба поведения кажутся странными. Модели приложений, как правило, не требуют от меня повторной авторизации разрешения на ресурс между вызовами приложения или даже во время его "запуска". Даже веб-страницы сохраняют авторизацию во время сеанса. Я делаю что-то не так, или это поведение, как задумано?

Код, который выполняет выполнение (это выполняется в облачных функциях Google, и есть некоторая дополнительная структура, которая выполняет эти вызовы через Promise - это всего лишь важная часть кода). res.send(200) просто указывает API.AI, что он должен использовать ответы, которые там определены, и это работает без проблем. return Promise.resolve(null); просто гарантирует, что другие резервные условия / ошибки не выполняются.


exports.process = function( req, res ){
  var app = new ApiAiApp({request:req, response:res});

  if( app.isPermissionGranted() ){
    res.send( 200 );
    return Promise.resolve( null );
  } else {
    return askPermission( req, res, app );
  }
};

var askPermission = function( req, res, app ){
  //app.tell('foo');
  let namePermission = app.SupportedPermissions.NAME;
  let preciseLocationPermission = app.SupportedPermissions.DEVICE_PRECISE_LOCATION;

  // Ask for more than one permission. User can authorize all or none.
  app.askForPermissions('To address you by name and know your location',
    [namePermission, preciseLocationPermission]);
  return Promise.resolve( null );
};

API.AI намерение, которое обрабатывает actions_intent_PERMISSION запрос:

Результат локации

Другое намерение, которое должно иметь полезную нагрузку пользователя / местоположения, но которое никогда не вызывается с этой информацией

простой тест

Снимок экрана с симулятора, демонстрирующий, что он всегда запрашивает разрешение, кроме случаев, когда это было специально предоставлено:

снимок экрана симулятора

JSON отправляется при первоначальном подключении:


{
 "originalRequest": {
  "source": "google",
  "version": "2",
  "data": {
   "isInSandbox": true,
   "surface": {
    "capabilities": [
     {
      "name": "actions.capability.AUDIO_OUTPUT"
     },
     {
      "name": "actions.capability.SCREEN_OUTPUT"
     }
    ]
   },
   "inputs": [
    {
     "rawInputs": [
      {
       "query": "talk to my test app",
       "inputType": "KEYBOARD"
      }
     ],
     "intent": "actions.intent.MAIN"
    }
   ],
   "user": {
    "locale": "en-US",
    "userId": "APhe68HKWmHGe9cojGOMrX9WKQ0l"
   },
   "device": {},
   "conversation": {
    "conversationId": "1499807128489",
    "type": "NEW"
   }
  }
 },
 "id": "7e301f85-4178-4be6-8b7c-408bad3ef62b",
 "timestamp": "2017-07-11T21:05:28.504Z",
 "lang": "en",
 "result": {
  "source": "agent",
  "resolvedQuery": "GOOGLE_ASSISTANT_WELCOME",
  "speech": "",
  "action": "input.welcome",
  "actionIncomplete": false,
  "parameters": {},
  "contexts": [
   {
    "name": "google_assistant_welcome",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "actions_capability_screen_output",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "actions_capability_audio_output",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "google_assistant_input_type_keyboard",
    "parameters": {},
    "lifespan": 0
   }
  ],
  "metadata": {
   "intentId": "f31e371a-db9e-4e00-8002-546ec14d40a9",
   "webhookUsed": "true",
   "webhookForSlotFillingUsed": "false",
   "nluResponseTime": 2,
   "intentName": "Default Welcome Intent"
  },
  "fulfillment": {
   "speech": "I'm not sure, I'm a little confused.",
   "messages": [
    {
     "type": 0,
     "speech": "I'm not sure, I'm a little confused."
    }
   ]
  },
  "score": 1
 },
 "status": {
  "code": 200,
  "errorType": "success"
 },
 "sessionId": "1499807128489"
}

JSON, отправленный после того, как он просит разрешения, и я предоставил это. Как и ожидалось originalRequest.data.user имеет имя и originalRequest.data.device теперь имеет местоположение.


{
 "originalRequest": {
  "source": "google",
  "version": "2",
  "data": {
   "isInSandbox": true,
   "surface": {
    "capabilities": [
     {
      "name": "actions.capability.AUDIO_OUTPUT"
     },
     {
      "name": "actions.capability.SCREEN_OUTPUT"
     }
    ]
   },
   "inputs": [
    {
     "rawInputs": [
      {
       "query": "yes",
       "inputType": "KEYBOARD"
      }
     ],
     "arguments": [
      {
       "rawText": "yes",
       "textValue": "true",
       "name": "PERMISSION"
      }
     ],
     "intent": "actions.intent.PERMISSION"
    }
   ],
   "user": {
    "profile": {
     "displayName": "Allen Firstenberg",
     "givenName": "Allen",
     "familyName": "Firstenberg"
    },
    "locale": "en-US",
    "userId": "APhe68HKWmHGe9cojGOMrX9WKQ0l"
   },
   "device": {
    "location": {
     "coordinates": {
      "latitude": 37.4219806,
      "longitude": -122.0841979
     }
    }
   },
   "conversation": {
    "conversationId": "1499807128489",
    "type": "ACTIVE",
    "conversationToken": "[\"_actions_on_google_\"]"
   }
  }
 },
 "id": "7a75593e-55d0-4962-ad91-564d47e5df13",
 "timestamp": "2017-07-11T21:05:43.391Z",
 "lang": "en",
 "result": {
  "source": "agent",
  "resolvedQuery": "actions_intent_PERMISSION",
  "speech": "",
  "action": "",
  "actionIncomplete": false,
  "parameters": {},
  "contexts": [
   {
    "name": "actions_capability_screen_output",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "_actions_on_google_",
    "parameters": {},
    "lifespan": 99
   },
   {
    "name": "actions_intent_permission",
    "parameters": {
     "PERMISSION": "true"
    },
    "lifespan": 0
   },
   {
    "name": "actions_capability_audio_output",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "google_assistant_input_type_keyboard",
    "parameters": {},
    "lifespan": 0
   }
  ],
  "metadata": {
   "intentId": "5d154d71-63f1-43a9-9c18-70d78bfd700f",
   "webhookUsed": "true",
   "webhookForSlotFillingUsed": "false",
   "nluResponseTime": 1,
   "intentName": "Location result"
  },
  "fulfillment": {
   "speech": "you're allowed",
   "messages": [
    {
     "type": 0,
     "speech": "you're allowed"
    }
   ]
  },
  "score": 1
 },
 "status": {
  "code": 200,
  "errorType": "success"
 },
 "sessionId": "1499807128489"
}

JSON отправил после того, как я дал разрешение (выше), а затем выпустил фразу "простой тест". Обратите внимание, что в полях пользователя и устройства отсутствует информация, для которой было предоставлено разрешение, но это правильное намерение.


{
 "originalRequest": {
  "source": "google",
  "version": "2",
  "data": {
   "isInSandbox": true,
   "surface": {
    "capabilities": [
     {
      "name": "actions.capability.AUDIO_OUTPUT"
     },
     {
      "name": "actions.capability.SCREEN_OUTPUT"
     }
    ]
   },
   "inputs": [
    {
     "rawInputs": [
      {
       "query": "simple test",
       "inputType": "KEYBOARD"
      }
     ],
     "arguments": [
      {
       "rawText": "simple test",
       "textValue": "simple test",
       "name": "text"
      }
     ],
     "intent": "actions.intent.TEXT"
    }
   ],
   "user": {
    "locale": "en-US",
    "userId": "APhe68HKWmHGe9cojGOMrX9WKQ0l"
   },
   "device": {},
   "conversation": {
    "conversationId": "1499807128489",
    "type": "ACTIVE",
    "conversationToken": "[\"_actions_on_google_\"]"
   }
  }
 },
 "id": "f1804e02-bafc-4656-8726-0955bfb4f75d",
 "timestamp": "2017-07-11T21:05:55.001Z",
 "lang": "en",
 "result": {
  "source": "agent",
  "resolvedQuery": "simple test",
  "speech": "",
  "action": "",
  "actionIncomplete": false,
  "parameters": {},
  "contexts": [
   {
    "name": "actions_capability_screen_output",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "_actions_on_google_",
    "parameters": {},
    "lifespan": 98
   },
   {
    "name": "actions_capability_audio_output",
    "parameters": {},
    "lifespan": 0
   },
   {
    "name": "google_assistant_input_type_keyboard",
    "parameters": {},
    "lifespan": 0
   }
  ],
  "metadata": {
   "intentId": "48257e82-3615-4445-8ea2-be21980b7115",
   "webhookUsed": "true",
   "webhookForSlotFillingUsed": "false",
   "nluResponseTime": 4,
   "intentName": "simple test"
  },
  "fulfillment": {
   "speech": "",
   "messages": [
    {
     "type": 0,
     "speech": ""
    }
   ]
  },
  "score": 1
 },
 "status": {
  "code": 200,
  "errorType": "success"
 },
 "sessionId": "1499807128489"
}

Выполнение этого между двумя сессиями дает одинаковые результаты.

1 ответ

Решение

Это ожидаемое поведение. Прямо сейчас мы рекомендуем сохранить данные, разрешенные пользователем, с помощью идентификатора пользователя. Чтобы увидеть, как мы могли бы порекомендовать это, ознакомьтесь с образцом Name Psychic В этом примере мы используем Firebase Realtime DB для сохранения разрешенных данных для этого пользователя через намерения / разговоры.

Другие вопросы по тегам