Skip to content

Commit

Permalink
📝 Add docstrings to stop (#644)
Browse files Browse the repository at this point in the history
Docstrings generation was requested by @JarbasAl.

* #643 (comment)

The following files were modified:

* `ovos_core/intent_services/__init__.py`
* `ovos_core/intent_services/converse_service.py`
* `ovos_core/intent_services/stop_service.py`

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
  • Loading branch information
coderabbitai[bot] authored Jan 9, 2025
1 parent 4fa2355 commit e2a1b08
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 46 deletions.
47 changes: 42 additions & 5 deletions ovos_core/intent_services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,31 @@ def _handle_deactivate(self, message):
self._deactivations[sess.session_id].append(skill_id)

def _emit_match_message(self, match: Union[IntentHandlerMatch, PipelineMatch], message: Message):
"""Update the message data with the matched utterance information and
activate the corresponding skill if available.
"""
Emit a reply message for a matched intent, updating session and skill activation.
This method processes matched intents from either a pipeline matcher or an intent handler,
creating a reply message with matched intent details and managing skill activation.
Args:
match (IntentHandlerMatch): The matched utterance object.
message (Message): The messagebus data.
match (Union[IntentHandlerMatch, PipelineMatch]): The matched intent object containing
utterance and matching information.
message (Message): The original messagebus message that triggered the intent match.
Details:
- Handles two types of matches: PipelineMatch and IntentHandlerMatch
- Creates a reply message with matched intent data
- Activates the corresponding skill if not previously deactivated
- Updates session information
- Emits the reply message on the messagebus
Side Effects:
- Modifies session state
- Emits a messagebus event
- Can trigger skill activation events
Returns:
None
"""
reply = None
sess = match.updated_session or SessionManager.get(message)
Expand Down Expand Up @@ -313,6 +332,24 @@ def _emit_match_message(self, match: Union[IntentHandlerMatch, PipelineMatch], m
self.bus.emit(reply)

def send_cancel_event(self, message):
"""
Emit events and play a sound when an utterance is canceled.
Logs the cancellation with the specific cancel word, plays a predefined cancel sound,
and emits multiple events to signal the utterance cancellation.
Parameters:
message (Message): The original message that triggered the cancellation.
Events Emitted:
- 'mycroft.audio.play_sound': Plays a cancel sound from configuration
- 'ovos.utterance.cancelled': Signals that the utterance was canceled
- 'ovos.utterance.handled': Indicates the utterance processing is complete
Notes:
- Uses the default cancel sound path 'snd/cancel.mp3' if not specified in configuration
- Ensures events are sent as replies to the original message
"""
LOG.info("utterance canceled, cancel_word:" + message.context.get("cancel_word"))
# play dedicated cancel sound
sound = Configuration().get('sounds', {}).get('cancel', "snd/cancel.mp3")
Expand Down
28 changes: 21 additions & 7 deletions ovos_core/intent_services/converse_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,29 @@ def converse(self, utterances: List[str], skill_id: str, lang: str, message: Mes
return False

def converse_with_skills(self, utterances: List[str], lang: str, message: Message) -> Optional[PipelineMatch]:
"""Give active skills a chance at the utterance
"""
Attempt to converse with active skills for a given set of utterances.
Iterates through active skills to find one that can handle the utterance. Filters skills based on timeout and blacklist status.
Args:
utterances (list): list of utterances
lang (string): 4 letter ISO language code
message (Message): message to use to generate reply
utterances (List[str]): List of utterance strings to process
lang (str): 4-letter ISO language code for the utterances
message (Message): Message context for generating a reply
Returns:
IntentMatch if handled otherwise None.
PipelineMatch: Match details if a skill successfully handles the utterance, otherwise None
- handled (bool): Whether the utterance was fully handled
- match_data (dict): Additional match metadata
- skill_id (str): ID of the skill that handled the utterance
- updated_session (Session): Current session state after skill interaction
- utterance (str): The original utterance processed
Notes:
- Standardizes language tag
- Filters out blacklisted skills
- Checks for skill conversation timeouts
- Attempts conversation with each eligible skill
"""
lang = standardize_lang_tag(lang)
session = SessionManager.get(message)
Expand Down
147 changes: 113 additions & 34 deletions ovos_core/intent_services/stop_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,25 @@ def get_active_skills(message: Optional[Message] = None) -> List[str]:
return [skill[0] for skill in session.active_skills]

def _collect_stop_skills(self, message: Message) -> List[str]:
"""use the messagebus api to determine which skills can stop
This includes all skills and external applications"""
"""
Collect skills that can be stopped based on a ping-pong mechanism.
This method determines which active skills can handle a stop request by sending
a stop ping to each active skill and waiting for their acknowledgment.
Parameters:
message (Message): The original message triggering the stop request.
Returns:
List[str]: A list of skill IDs that can be stopped. If no skills explicitly
indicate they can stop, returns all active skills.
Notes:
- Excludes skills that are blacklisted in the current session
- Uses a non-blocking event mechanism to collect skill responses
- Waits up to 0.5 seconds for skills to respond
- Falls back to all active skills if no explicit stop confirmation is received
"""
sess = SessionManager.get(message)

want_stop = []
Expand All @@ -66,6 +83,23 @@ def _collect_stop_skills(self, message: Message) -> List[str]:
event = Event()

def handle_ack(msg):
"""
Handle acknowledgment from skills during the stop process.
This method is a nested function used in skill stopping negotiation. It validates and tracks skill responses to a stop request.
Parameters:
msg (Message): Message containing skill acknowledgment details.
Side Effects:
- Modifies the `want_stop` list with skills that can handle stopping
- Updates the `skill_ids` list to track which skills have responded
- Sets the threading event when all active skills have responded
Notes:
- Checks if a skill can handle stopping based on multiple conditions
- Ensures all active skills provide a response before proceeding
"""
nonlocal event, skill_ids
skill_id = msg.data["skill_id"]

Expand Down Expand Up @@ -96,15 +130,28 @@ def handle_ack(msg):
return want_stop or active_skills

def stop_skill(self, skill_id: str, message: Message) -> bool:
"""Tell a skill to stop anything it's doing,
taking into account the message Session
"""
Stop a skill's ongoing activities and manage its session state.
Sends a stop command to a specific skill and handles its response, ensuring
that any active interactions or processes are terminated. The method checks
for errors, verifies the skill's stopped status, and emits additional signals
to forcibly abort ongoing actions like conversations, questions, or speech.
Args:
skill_id: skill to query.
message (Message): message containing interaction info.
skill_id (str): Unique identifier of the skill to be stopped.
message (Message): The original message context containing interaction details.
Returns:
handled (bool): True if handled otherwise False.
bool: True if the skill was successfully stopped, False otherwise.
Raises:
Logs error if skill stop request encounters an issue.
Notes:
- Emits multiple bus messages to ensure complete skill termination
- Checks and handles different skill interaction states
- Supports force-stopping of conversations, questions, and speech
"""
stop_msg = message.reply(f"{skill_id}.stop")
result = self.bus.wait_for_response(stop_msg, f"{skill_id}.stop.response")
Expand Down Expand Up @@ -133,15 +180,28 @@ def stop_skill(self, skill_id: str, message: Message) -> bool:
return stopped

def match_stop_high(self, utterances: List[str], lang: str, message: Message) -> Optional[PipelineMatch]:
"""If utterance is an exact match for "stop" , run before intent stage
Args:
utterances (list): list of utterances
lang (string): 4 letter ISO language code
message (Message): message to use to generate reply
"""
Handles high-confidence stop requests by matching exact stop vocabulary and managing skill stopping.
Attempts to stop skills when an exact "stop" or "global_stop" command is detected. Performs the following actions:
- Identifies the closest language match for vocabulary
- Checks for global stop command when no active skills exist
- Emits a global stop message if applicable
- Attempts to stop individual skills if a stop command is detected
- Disables response mode for stopped skills
Parameters:
utterances (List[str]): List of user utterances to match against stop vocabulary
lang (str): Four-letter ISO language code for language-specific matching
message (Message): Message context for generating appropriate responses
Returns:
PipelineMatch if handled otherwise None.
Optional[PipelineMatch]: Match result indicating whether stop was handled, with optional skill and session information
- Returns None if no stop action could be performed
- Returns PipelineMatch with handled=True for successful global or skill-specific stop
Raises:
No explicit exceptions raised, but may log debug/info messages during processing
"""
lang = self._get_closest_lang(lang)
if lang is None: # no vocs registered for this lang
Expand Down Expand Up @@ -182,16 +242,26 @@ def match_stop_high(self, utterances: List[str], lang: str, message: Message) ->
return None

def match_stop_medium(self, utterances: List[str], lang: str, message: Message) -> Optional[PipelineMatch]:
""" if "stop" intent is in the utterance,
but it contains additional words not in .intent files
Args:
utterances (list): list of utterances
lang (string): 4 letter ISO language code
message (Message): message to use to generate reply
"""
Handle stop intent with additional context beyond simple stop commands.
This method processes utterances that contain "stop" or global stop vocabulary but may include
additional words not explicitly defined in intent files. It performs a medium-confidence
intent matching for stop requests.
Parameters:
utterances (List[str]): List of input utterances to analyze
lang (str): Four-letter ISO language code for localization
message (Message): Message context for generating appropriate responses
Returns:
PipelineMatch if handled otherwise None.
Optional[PipelineMatch]: A pipeline match if the stop intent is successfully processed,
otherwise None if no stop intent is detected
Notes:
- Attempts to match stop vocabulary with fuzzy matching
- Falls back to low-confidence matching if medium-confidence match is inconclusive
- Handles global stop scenarios when no active skills are present
"""
lang = self._get_closest_lang(lang)
if lang is None: # no vocs registered for this lang
Expand Down Expand Up @@ -222,15 +292,24 @@ def _get_closest_lang(self, lang: str) -> Optional[str]:
return None

def match_stop_low(self, utterances: List[str], lang: str, message: Message) -> Optional[PipelineMatch]:
""" before fallback_low , fuzzy match stop intent
Args:
utterances (list): list of utterances
lang (string): 4 letter ISO language code
message (Message): message to use to generate reply
"""
Perform a low-confidence fuzzy match for stop intent before fallback processing.
This method attempts to match stop-related vocabulary with low confidence and handle stopping of active skills.
Parameters:
utterances (List[str]): List of input utterances to match against stop vocabulary
lang (str): Four-letter ISO language code for vocabulary matching
message (Message): Message context used for generating replies and managing session
Returns:
PipelineMatch if handled otherwise None.
Optional[PipelineMatch]: A pipeline match object if a stop action is handled, otherwise None
Notes:
- Increases confidence if active skills are present
- Attempts to stop individual skills before emitting a global stop signal
- Handles language-specific vocabulary matching
- Configurable minimum confidence threshold for stop intent
"""
lang = self._get_closest_lang(lang)
if lang is None: # no vocs registered for this lang
Expand Down

0 comments on commit e2a1b08

Please sign in to comment.