diff --git a/.github/workflows/push_skill_json.yml b/.github/workflows/push_skill_json.yml new file mode 100644 index 0000000..c2772a2 --- /dev/null +++ b/.github/workflows/push_skill_json.yml @@ -0,0 +1,31 @@ +# Update skill.json at neon_skills repository +name: Update neon_skills +on: + workflow_dispatch: + push: + branches: + - dev + - master + +jobs: + push_skill_json: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v2 + - name: Update skill.json in neon_skills + run: | + git clone https://github.com/neongeckocom/neon_skills -b ${{github.ref_name}} + cp skill.json neon_skills/skill_metadata/${{github.event.repository.name}}.json + - name: Push neon_skills changes + uses: cpina/github-action-push-to-another-repository@main + with: + source-directory: neon_skills/ + destination-github-username: neongeckocom + destination-repository-name: neon_skills + user-name: github-actions[bot] + user-email: developers@neon.ai + target-branch: ${{github.ref_name}} + commit-message: Update skill.json for ${{github.event.repository.name}} + env: + API_TOKEN_GITHUB: ${{secrets.SKILL_JSON_TOKEN}} \ No newline at end of file diff --git a/__init__.py b/__init__.py index 8c7b52a..2055626 100644 --- a/__init__.py +++ b/__init__.py @@ -53,16 +53,23 @@ def __init__(self): super(DemoSkill, self).__init__(name="DemoSkill") self._active_demos = dict() self._audio_output_done = Event() + self._prompt_handled = Event() + self._last_response = None self._data_path = get_xdg_data_save_path() @property def demo_tts_plugin(self) -> str: """ - Get the TTS engine spec to use for the demo user + Get the TTS engine spec to use for the demo user. + TTS Engine is resolved in the order of: + 1) demo_tts_engine in settings + 2) audiofiles TTS engine if setting is missing/unset + 3) configured fallback module if setting is explicitly empty """ - return self.settings.get("demo_tts_engine") or \ - self.config_core["tts"].get("fallback_module") or \ - "ovos-tts-plugin-mimic" + # TODO: Add a check for plugin availability here to validate config + return self.settings.get("demo_tts_engine", + "neon-tts-plugin-audiofiles") or \ + self.config_core["tts"].get("fallback_module") @property def speak_timeout(self): @@ -70,7 +77,7 @@ def speak_timeout(self): @property def intent_timeout(self): - return self.settings.get("intent_timeout") or 10 + return self.settings.get("intent_timeout") or self._speak_timeout @property def demo_filename(self): @@ -86,13 +93,26 @@ def initialize(self): self.add_event("recognizer_loop:audio_output_start", self._audio_started) self.add_event("recognizer_loop:audio_output_end", self._audio_stopped) + self.add_event("mycroft.mic.listen", self._mic_listen) + self.add_event("mycroft.skill.handler.complete", self._handler_complete) def _audio_started(self, _): + # TODO: Handle audio per-user self._audio_output_done.clear() def _audio_stopped(self, _): + # TODO: Handle audio per-user self._audio_output_done.set() + def _mic_listen(self, _): + # TODO: Handle this per-user + self._prompt_handled.set() + + def _handler_complete(self, message): + # TODO: Handle this per-user + self._last_response = message + self._prompt_handled.set() + def _show_demo_prompt(self, message): """ Handles first run demo prompt @@ -160,14 +180,17 @@ def handle_show_demo(self, message): if self._active_demos[user].is_set(): # Check to stop before speaking the prompt break - self._speak_prompt(prompt, prompter, tts) - if self._active_demos[user].is_set(): - # Check to stop before executing the prompt - break - LOG.info(message.context['user_profiles'][0]['units']['measure']) - message.data = {"lang": lang, - "utterances": [prompt.lower()]} - self._send_prompt(message) + try: + self._speak_prompt(prompt, prompter, tts) + if self._active_demos[user].is_set(): + # Check to stop before executing the prompt + break + LOG.info(message.context['user_profiles'][0]['units']['measure']) + message.data = {"lang": lang, + "utterances": [prompt.lower()]} + self._send_prompt(message) + except Exception as e: + LOG.exception(e) self.speak_dialog("finished_demo", message=original_message) self._active_demos.pop(user) @@ -200,14 +223,15 @@ def _send_prompt(self, message: Message): :param message: Message to emit to skills """ self._audio_output_done.clear() # Clear to wait for this response - resp = self.bus.wait_for_response(message, - "mycroft.skill.handler.complete", - self.intent_timeout) - if not resp: + self._prompt_handled.clear() + self.bus.emit(message) + self._prompt_handled.wait(self.intent_timeout) + if not self._prompt_handled.is_set(): LOG.error(f"Handler not completed for: " f"{message.data.get('utterances')}") else: - message.context['user_profiles'] = resp.context['user_profiles'] + message.context['user_profiles'] = \ + self._last_response.context['user_profiles'] if not self._audio_output_done.wait(self.speak_timeout): LOG.error(f"Timed out waiting") else: @@ -240,18 +264,21 @@ def _get_demo_tts(self, lang: str = None) -> Optional[TTS]: Create a TTS plugin instance to """ from ovos_plugin_manager.tts import OVOSTTSFactory - engine = self.demo_tts_plugin - lang = lang or self.lang - config = {"module": engine, - "lang": lang} + + # Get TTS config with lang and module overrides from skill + config = dict(self.config_core.get('tts')) + config['module'] = self.demo_tts_plugin + config['lang'] = lang or self.lang + try: + LOG.debug(f'Creating TTS with config={config}') return OVOSTTSFactory.create(config) except Exception as e: LOG.error(f"Failed to load TTS Plugin: {self.demo_tts_plugin}") LOG.error(e) try: - LOG.info("Trying with configured fallback_module") config['module'] = self.config_core["tts"].get("fallback_module") + LOG.info(f"Trying with configured fallback_module {config['module']}") return OVOSTTSFactory.create(config) except Exception as e: LOG.error(f"Failed to load TTS Plugin: {self.demo_tts_plugin}") @@ -266,6 +293,7 @@ def stop(self): if user and user in self._active_demos: LOG.info(f"{user} requested stop") self._active_demos[user].set() + self._prompt_handled.set() def create_skill(): diff --git a/locale/en-us/demo.txt b/locale/en-us/demo.txt index 6317db2..fee92cc 100644 --- a/locale/en-us/demo.txt +++ b/locale/en-us/demo.txt @@ -1,9 +1,7 @@ -what is your name -how are you -what time is it -what is the temperature -change my units to metric -what is the temperature -what is the capital of Ukraine -how much caffeine is in Coke -how do you spell caffeine \ No newline at end of file +what is your name? +how are you? +what time is it? +what is the temperature? +what is the capital of Ukraine? +how much caffeine is in Coke? +how do you spell caffeine? \ No newline at end of file diff --git a/locale/en-us/mall_demo.txt b/locale/en-us/mall_demo.txt new file mode 100644 index 0000000..93c043c --- /dev/null +++ b/locale/en-us/mall_demo.txt @@ -0,0 +1,10 @@ +where is apple store +yes +starbucks +yes +hours +yes +show me starbucks +yes +location +yes diff --git a/requirements.txt b/requirements.txt index 765f408..3a2ea51 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ -neon_utils>=0.5.7,<2.0.0 +neon_utils~=1.0 +neon_tts_plugin_audiofiles~=0.0.2 +ovos-plugin-manager~=0.0.21 \ No newline at end of file diff --git a/skill.json b/skill.json index 8358b47..c864bef 100644 --- a/skill.json +++ b/skill.json @@ -12,7 +12,9 @@ "systemDeps": false, "requirements": { "python": [ - "neon_utils>=0.5.7,<2.0.0" + "neon_tts_plugin_audiofiles~=0.0.2", + "neon_utils~=1.0", + "ovos-plugin-manager~=0.0.21" ], "system": {}, "skill": [] diff --git a/version.py b/version.py index 4488dcb..96062fc 100644 --- a/version.py +++ b/version.py @@ -26,4 +26,4 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -__version__ = "0.1.0" +__version__ = "0.2.0"