22
33from pycrdt import Map
44
5- from traitlets import Unicode , Bool
5+ from traitlets import Unicode , Bool , Dict
66from traitlets .config import LoggingConfigurable
77from jupyter_server_documents .kernels .message_cache import KernelMessageCache
88
99class OutputProcessor (LoggingConfigurable ):
1010
1111 _file_id = Unicode (default_value = None , allow_none = True )
12+ _clear_output_cells = Dict (default_value = {})
1213
1314 use_outputs_service = Bool (
1415 default_value = True ,
@@ -46,6 +47,17 @@ def yroom_manager(self):
4647 """A shortcut for the jupyter server ydoc manager."""
4748 return self .settings ["yroom_manager" ]
4849
50+
51+ async def get_notebook_ydoc (self , file_id ):
52+ room_id = f"json:notebook:{ file_id } "
53+ room = self .yroom_manager .get_room (room_id )
54+ if room is None :
55+ self .log .error (f"YRoom not found: { room_id } " )
56+ return
57+ notebook = await room .get_jupyter_ydoc ()
58+
59+ return notebook
60+
4961 async def clear_cell_outputs (self , cell_id , room_id ):
5062 """Clears the outputs of a cell in ydoc"""
5163 room = self .yroom_manager .get_room (room_id )
@@ -62,11 +74,19 @@ async def clear_cell_outputs(self, cell_id, room_id):
6274
6375 def clear (self , cell_id ):
6476 """Clear all outputs for a given cell Id."""
77+
78+ task = None
79+
6580 if self ._file_id is not None :
6681 if self .use_outputs_service :
6782 room_id = f"json:notebook:{ self ._file_id } "
68- asyncio .create_task (self .clear_cell_outputs (cell_id , room_id ))
83+ task = asyncio .create_task (self .clear_cell_outputs (cell_id , room_id ))
6984 self .outputs_manager .clear (file_id = self ._file_id , cell_id = cell_id )
85+
86+ # Remove any pending delayed clear for this cell
87+ self ._clear_output_cells .pop (cell_id , None )
88+
89+ return task
7090
7191 # Outgoing messages
7292 def process_output (self , msg_type : str , cell_id : str , content : dict ):
@@ -87,6 +107,23 @@ def process_output(self, msg_type: str, cell_id: str, content: dict):
87107
88108 async def output_task (self , msg_type , cell_id , content ):
89109 """A coroutine to handle output messages."""
110+
111+ if msg_type == "clear_output" :
112+ if not content .get ("wait" , False ):
113+ # Clear immediately
114+ self .clear (cell_id )
115+ else :
116+ # Mark for delayed clear, overriding any previous pending clear
117+ self ._clear_output_cells [cell_id ] = True
118+
119+ return
120+
121+ # Check for delayed clear before processing output
122+ if cell_id in self ._clear_output_cells and msg_type != "clear_output" :
123+ clear_task = self .clear (cell_id )
124+ if clear_task is not None :
125+ await clear_task
126+
90127 try :
91128 # TODO: The session manager may have multiple notebooks connected to the kernel
92129 # but currently get_session only returns the first. We need to fix this and
0 commit comments