@@ -405,38 +405,41 @@ def get_awareness(self, on_reset: Callable[[pycrdt.Awareness], Any] | None = Non
405405 self ._on_reset_callbacks ['awareness' ].append (on_reset )
406406 return self ._awareness
407407
408- def get_cell_execution_states (self ) -> dict :
409- """
410- Returns the persistent cell execution states for this room.
411- These states survive client disconnections but are not saved to disk.
412- """
413- if not hasattr (self , '_cell_execution_states' ):
414- self ._cell_execution_states : dict [str , str ] = {}
415- return self ._cell_execution_states
416-
417408 def set_cell_execution_state (self , cell_id : str , execution_state : str ) -> None :
418409 """
419- Sets the execution state for a specific cell.
420- This state persists across client disconnections.
410+ Sets the execution state for a specific cell in the awareness system.
411+ This provides real-time updates to all connected clients and persists
412+ while the server is running (survives client reconnections).
421413 """
422- if not hasattr (self , '_cell_execution_states' ):
423- self ._cell_execution_states = {}
424- self ._cell_execution_states [cell_id ] = execution_state
414+ awareness = self .get_awareness ()
415+ if awareness is None :
416+ return
417+
418+ local_state = awareness .get_local_state ()
419+ if local_state is not None :
420+ cell_states = local_state .get ("cell_execution_states" , {})
421+ else :
422+ cell_states = {}
423+
424+ cell_states [cell_id ] = execution_state
425+ awareness .set_local_state_field ("cell_execution_states" , cell_states )
425426
426427 def set_cell_awareness_state (self , cell_id : str , execution_state : str ) -> None :
427428 """
428- Sets the execution state for a specific cell in the awareness system.
429+ Alias for set_cell_execution_state for backward compatibility.
430+ """
431+ self .set_cell_execution_state (cell_id , execution_state )
432+
433+ def set_kernel_execution_state (self , execution_state : str ) -> None :
434+ """
435+ Sets the kernel execution state in awareness.
429436 This provides real-time updates to all connected clients.
430437 """
431438 awareness = self .get_awareness ()
432439 if awareness is not None :
433- local_state = awareness .get_local_state ()
434- if local_state is not None :
435- cell_states = local_state .get ("cell_execution_states" , {})
436- else :
437- cell_states = {}
438- cell_states [cell_id ] = execution_state
439- awareness .set_local_state_field ("cell_execution_states" , cell_states )
440+ awareness .set_local_state_field (
441+ "kernel" , {"execution_state" : execution_state }
442+ )
440443
441444 def add_message (self , client_id : str , message : bytes ) -> None :
442445 """
@@ -540,6 +543,7 @@ def handle_sync_step1(self, client_id: str, message: bytes) -> None:
540543 - Computing a SyncStep2 reply,
541544 - Sending the reply to the client over WS, and
542545 - Sending a new SyncStep1 message immediately after.
546+ - Sending awareness state to the new client.
543547 """
544548 # Mark client as desynced
545549 new_client = self .clients .get (client_id )
@@ -586,6 +590,22 @@ def handle_sync_step1(self, client_id: str, message: bytes) -> None:
586590 )
587591 self .log .exception (e )
588592
593+ # Send current awareness state to the new client
594+ try :
595+ # Get all awareness client IDs and broadcast the current state
596+ all_client_ids = list (self ._awareness ._states .keys ())
597+ if all_client_ids :
598+ awareness_update = self ._awareness .encode_awareness_update (all_client_ids )
599+ awareness_message = pycrdt .create_awareness_message (awareness_update )
600+ assert isinstance (new_client .websocket , WebSocketHandler )
601+ new_client .websocket .write_message (awareness_message , binary = True )
602+ except Exception as e :
603+ self .log .error (
604+ f"An exception occurred when sending awareness to "
605+ f"newly-synced client '{ new_client .id } ':"
606+ )
607+ self .log .exception (e )
608+
589609
590610 def handle_sync_step2 (self , client_id : str , message : bytes ) -> None :
591611 """
@@ -791,8 +811,8 @@ def _on_awareness_update(self, type: str, changes: tuple[dict[str, Any], Any]) -
791811 Arguments:
792812 type: The change type.
793813 changes: The awareness changes.
794- """
795-
814+ """
815+
796816 self .log .debug (f"awareness update, type={ type } , changes={ changes } , changes[1]={ changes [1 ]} , meta={ self ._awareness .meta } , ydoc.clientid={ self ._ydoc .client_id } , roomId={ self .room_id } " )
797817 updated_clients = [v for value in changes [0 ].values () for v in value ]
798818 self .log .debug (f"awareness update, updated_clients={ updated_clients } " )
0 commit comments