@@ -1070,9 +1070,15 @@ def _register_system_event_handlers(self):
10701070 """
10711071 Register default messagebus event handlers
10721072 """
1073+ # Stop topics: subscribe to BOTH the legacy and the OVOS-STOP-1 spec
1074+ # namespaces. Only one namespace is ever emitted (chosen by the
1075+ # 'legacy_namespace' config), so a subscriber never sees duplicates.
10731076 self .add_event ('mycroft.stop' , self ._handle_session_stop , speak_errors = False )
1077+ self .add_event ('ovos.stop' , self ._handle_session_stop , speak_errors = False ) # STOP-1 §5.3
10741078 self .add_event (f"{ self .skill_id } .stop" , self ._handle_session_stop , speak_errors = False )
1079+ self .add_event (f"{ self .skill_id } :stop" , self ._handle_session_stop , speak_errors = False ) # STOP-1 §4.3
10751080 self .add_event (f"{ self .skill_id } .stop.ping" , self ._handle_stop_ack , speak_errors = False )
1081+ self .add_event ("ovos.stop.ping" , self ._handle_stop_ack , speak_errors = False ) # STOP-1 §4.2
10761082 self .add_event (f"{ self .skill_id } .converse.get_response" , self .__handle_get_response , speak_errors = False )
10771083
10781084 self .add_event ('mycroft.skill.enable_intent' , self .handle_enable_intent , speak_errors = False )
@@ -1142,15 +1148,28 @@ def handle_settings_change(self, message: Message):
11421148 f"remote changes not handled!: { e } " )
11431149 self ._start_filewatcher ()
11441150
1151+ @staticmethod
1152+ def _legacy_namespace () -> bool :
1153+ """Whether to emit the legacy ``mycroft.*`` bus topics (default) or the
1154+ OVOS spec ``ovos.*`` topics, during the bus-namespace transition.
1155+
1156+ Deployment-wide, controlled by the ``legacy_namespace`` config key
1157+ (default ``True``). Emitters pick exactly one namespace so subscribers —
1158+ which listen on both — never receive duplicate messages.
1159+ """
1160+ return Configuration ().get ("legacy_namespace" , True )
1161+
11451162 def _handle_stop_ack (self , message : Message ):
11461163 """
1147- Inform skills service if we want to handle stop. Individual skills
1148- must implement the method self.can_stop to enable or
1149- disable stop support.
1150- @param message: `{self.skill_id}.stop.ping` Message
1164+ Answer a stoppability ping. Individual skills must implement the method
1165+ self.can_stop to enable or disable stop support. Replies on the legacy
1166+ ``skill.stop.pong`` or the spec ``ovos.stop.pong`` (OVOS-STOP-1 §4.2)
1167+ depending on the active namespace.
1168+ @param message: a ``{self.skill_id}.stop.ping`` or ``ovos.stop.ping`` Message
11511169 """
1170+ topic = "skill.stop.pong" if self ._legacy_namespace () else "ovos.stop.pong"
11521171 self .bus .emit (message .reply (
1153- "skill.stop.pong" ,
1172+ topic ,
11541173 data = {"skill_id" : self .skill_id ,
11551174 "can_handle" : self .can_stop (message )},
11561175 context = {"skill_id" : self .skill_id }))
@@ -1423,6 +1442,16 @@ def handle_remove_cross_context(self, message: Message):
14231442 context = message .data .get ('context' )
14241443 self .remove_context (context )
14251444
1445+ def _intent_handler_data (self , message : Optional [Message ],
1446+ skill_data : dict ) -> dict :
1447+ """Build the OVOS-PIPELINE-1 §8.2 handler-lifecycle payload
1448+ (``skill_id`` + ``intent_name``) on top of the legacy ``skill_data``."""
1449+ data = dict (skill_data )
1450+ data ["skill_id" ] = self .skill_id
1451+ if message is not None and ":" in message .msg_type :
1452+ data ["intent_name" ] = message .msg_type .split (":" , 1 )[- 1 ]
1453+ return data
1454+
14261455 def _on_event_start (self , message : Message , handler_info : str ,
14271456 skill_data : dict , activation : Optional [bool ] = None ):
14281457 """
@@ -1434,9 +1463,15 @@ def _on_event_start(self, message: Message, handler_info: str,
14341463 """
14351464 if handler_info :
14361465 # Indicate that the skill handler is starting if requested
1437- msg_type = handler_info + '.start'
14381466 message .context ["skill_id" ] = self .skill_id
1439- self .bus .emit (message .forward (msg_type , skill_data ))
1467+ # OVOS-PIPELINE-1 §8 handler-lifecycle trio: legacy mycroft.skill.handler.*
1468+ # or spec ovos.intent.handler.* depending on the active namespace.
1469+ if handler_info == "mycroft.skill.handler" and not self ._legacy_namespace ():
1470+ self .bus .emit (message .forward (
1471+ "ovos.intent.handler.start" ,
1472+ self ._intent_handler_data (message , skill_data )))
1473+ else :
1474+ self .bus .emit (message .forward (handler_info + '.start' , skill_data ))
14401475
14411476 def _on_event_end (self , message : Message , handler_info : str ,
14421477 skill_data : dict , is_intent : bool = False ):
@@ -1445,9 +1480,14 @@ def _on_event_end(self, message: Message, handler_info: str,
14451480 completed.
14461481 """
14471482 if handler_info :
1448- msg_type = handler_info + '.complete'
14491483 message .context ["skill_id" ] = self .skill_id
1450- self .bus .emit (message .forward (msg_type , skill_data ))
1484+ # OVOS-PIPELINE-1 §8: legacy or spec namespace.
1485+ if handler_info == "mycroft.skill.handler" and not self ._legacy_namespace ():
1486+ self .bus .emit (message .forward (
1487+ "ovos.intent.handler.complete" ,
1488+ self ._intent_handler_data (message , skill_data )))
1489+ else :
1490+ self .bus .emit (message .forward (handler_info + '.complete' , skill_data ))
14511491 if is_intent :
14521492 self .bus .emit (message .forward ("ovos.utterance.handled" , skill_data ))
14531493
@@ -1473,10 +1513,15 @@ def _on_event_error(self, error: str, message: Message, handler_info: str,
14731513 skill_data ['exception' ] = repr (error )
14741514 if handler_info :
14751515 # Indicate that the skill handler errored
1476- msg_type = handler_info + '.error'
14771516 message = message or Message ("" )
14781517 message .context ["skill_id" ] = self .skill_id
1479- self .bus .emit (message .forward (msg_type , skill_data ))
1518+ # OVOS-PIPELINE-1 §8: legacy or spec namespace.
1519+ if handler_info == "mycroft.skill.handler" and not self ._legacy_namespace ():
1520+ self .bus .emit (message .forward (
1521+ "ovos.intent.handler.error" ,
1522+ self ._intent_handler_data (message , skill_data )))
1523+ else :
1524+ self .bus .emit (message .forward (handler_info + '.error' , skill_data ))
14801525
14811526 def _register_adapt_intent (self ,
14821527 intent_parser : Union [IntentBuilder , Intent , str ],
@@ -1541,8 +1586,11 @@ def speak(self, utterance: str, expect_response: bool = False,
15411586
15421587 # grab message that triggered speech so we can keep context
15431588 message = dig_for_message ()
1544- m = message .forward ("speak" , data ) if message \
1545- else Message ("speak" , data )
1589+ # OVOS-PIPELINE-1 §9.6 natural-language response exit point: the legacy
1590+ # 'speak' topic or the spec 'ovos.utterance.speak', per active namespace.
1591+ topic = "speak" if self ._legacy_namespace () else "ovos.utterance.speak"
1592+ m = message .forward (topic , data ) if message \
1593+ else Message (topic , data )
15461594 m .context ["skill_id" ] = self .skill_id
15471595
15481596 # update any auto-translation metadata in message.context
0 commit comments