3535 register_window ,
3636 gather_envs ,
3737 broadcast_envs ,
38- serialize_env ,
3938 escape_eid ,
4039 compare_envs ,
4140 load_env ,
@@ -118,6 +117,39 @@ def update_packet(p, args, max_text_lines, max_old_content, max_image_history):
118117 patch = jsonpatch .make_patch (old_p , p )
119118 return p , patch .patch
120119
120+ @staticmethod
121+ def update_embeddings_packet (p , args , max_old_content ):
122+ update_type = args ["data" ]["update_type" ]
123+ content_id = get_rand_id ()
124+ if update_type == "EntitySelected" :
125+ selected = args ["data" ]["selected" ]
126+ p ["content" ]["selected" ] = selected
127+ p ["contentID" ] = content_id
128+ # `selected` may not exist yet on the first selection, so use "add"
129+ # (which also overwrites when the key is already present).
130+ return [
131+ {"op" : "add" , "path" : "/content/selected" , "value" : selected },
132+ {"op" : "replace" , "path" : "/contentID" , "value" : content_id },
133+ ]
134+ if update_type == "RegionSelected" :
135+ old_data = p ["content" ]["data" ]
136+ new_data = args ["data" ]["points" ]
137+ p ["old_content" ].append (old_data )
138+ # Cap retained history to prevent unbounded in-memory growth (#1320).
139+ if len (p ["old_content" ]) > max_old_content :
140+ p ["old_content" ] = p ["old_content" ][- max_old_content :]
141+ p ["content" ]["data" ] = new_data
142+ p ["content" ]["has_previous" ] = True
143+ p ["content" ]["selected" ] = None
144+ p ["contentID" ] = content_id
145+ return [
146+ {"op" : "replace" , "path" : "/content/data" , "value" : new_data },
147+ {"op" : "add" , "path" : "/content/has_previous" , "value" : True },
148+ {"op" : "add" , "path" : "/content/selected" , "value" : None },
149+ {"op" : "replace" , "path" : "/contentID" , "value" : content_id },
150+ ]
151+ return []
152+
121153 @staticmethod
122154 def update (p , args , max_text_lines , max_old_content , max_image_history ):
123155 # Update text in window, separated by a line break
@@ -127,20 +159,6 @@ def update(p, args, max_text_lines, max_old_content, max_image_history):
127159 if len (lines ) > max_text_lines :
128160 p ["content" ] = "<br>" .join (lines [- max_text_lines :])
129161 return p
130- if p ["type" ] == "embeddings" :
131- # TODO embeddings updates should be handled outside of the regular
132- # update flow, as update packets are easy to create manually and
133- # expensive to calculate otherwise
134- if args ["data" ]["update_type" ] == "EntitySelected" :
135- p ["content" ]["selected" ] = args ["data" ]["selected" ]
136- elif args ["data" ]["update_type" ] == "RegionSelected" :
137- p ["content" ]["selected" ] = None
138- p ["old_content" ].append (p ["content" ]["data" ])
139- if len (p ["old_content" ]) > max_old_content :
140- p ["old_content" ] = p ["old_content" ][- max_old_content :]
141- p ["content" ]["has_previous" ] = True
142- p ["content" ]["data" ] = args ["data" ]["points" ]
143- return p
144162 if p ["type" ] == "image_history" :
145163 utype = args ["data" ][0 ]["type" ]
146164 if utype == "image_history" :
@@ -325,6 +343,17 @@ def update(p, args, max_text_lines, max_old_content, max_image_history):
325343
326344 return p
327345
346+ @staticmethod
347+ def broadcast_window_update (handler , args , eid , p , diff_packet ):
348+ broadcast_packet = {
349+ "command" : "window_update" ,
350+ "win" : args ["win" ],
351+ "eid" : eid ,
352+ "content" : diff_packet ,
353+ "version" : p .get ("version" , 1 ),
354+ }
355+ broadcast (handler , json .dumps (broadcast_packet , cls = NanSafeEncoder ), eid )
356+
328357 @staticmethod
329358 def wrap_func (handler , args ):
330359 if "win" not in args :
@@ -374,6 +403,14 @@ def wrap_func(handler, args):
374403 )
375404 return
376405
406+ if p ["type" ] == "embeddings" :
407+ diff_packet = UpdateHandler .update_embeddings_packet (
408+ p , args , handler .max_old_content
409+ )
410+ UpdateHandler .broadcast_window_update (handler , args , eid , p , diff_packet )
411+ handler .write (p ["id" ])
412+ return
413+
377414 p , diff_packet = UpdateHandler .update_packet (
378415 p ,
379416 args ,
@@ -387,14 +424,7 @@ def wrap_func(handler, args):
387424 broadcast_msg ["eid" ] = eid
388425 broadcast (handler , json .dumps (broadcast_msg , cls = NanSafeEncoder ), eid )
389426 else :
390- broadcast_packet = {
391- "command" : "window_update" ,
392- "win" : args ["win" ],
393- "eid" : eid ,
394- "content" : diff_packet ,
395- "version" : p .get ("version" , 1 ),
396- }
397- broadcast (handler , json .dumps (broadcast_packet , cls = NanSafeEncoder ), eid )
427+ UpdateHandler .broadcast_window_update (handler , args , eid , p , diff_packet )
398428 handler .write (p ["id" ])
399429
400430 @check_auth
@@ -502,7 +532,7 @@ def wrap_func(handler, args):
502532 assert prev_eid in handler .state , "env to be forked doesn't exist"
503533
504534 handler .state [eid ] = copy .deepcopy (handler .state [prev_eid ])
505- serialize_env ( handler .state , [ eid ], env_path = handler .env_path )
535+ handler .storage . save_env ( eid , handler .state [ eid ] )
506536 broadcast_envs (handler )
507537
508538 handler .write (eid )
@@ -608,7 +638,7 @@ def wrap_func(handler, args):
608638 envs = args ["data" ]
609639 envs = [escape_eid (eid ) for eid in envs ]
610640 # this drops invalid env ids
611- ret = serialize_env (handler .state , envs , env_path = handler . env_path )
641+ ret = handler . storage . save_envs (handler .state , envs )
612642 handler .write (json .dumps (ret ))
613643
614644 @check_auth
@@ -790,8 +820,7 @@ def post(self):
790820
791821 self .state [new_eid ] = {"jsons" : data ["jsons" ], "reload" : data ["reload" ]}
792822
793- if self .env_path is not None :
794- serialize_env (self .state , [new_eid ], env_path = self .env_path )
823+ self .storage .save_env (new_eid , self .state [new_eid ])
795824
796825 broadcast_envs (self )
797826
0 commit comments