@@ -693,7 +693,7 @@ def file_ext_from_mimetype(mimetype, default="pdf"):
693693 return default
694694
695695
696- def cache_message_inline_data (m ):
696+ def cache_message_inline_data (m , context = None ):
697697 """
698698 Replaces and caches any inline data URIs in the message content.
699699 """
@@ -714,7 +714,7 @@ def cache_message_inline_data(m):
714714 ext = image_ext_from_mimetype (header .split (":" )[1 ])
715715 filename = f"image.{ ext } " # Hash will handle uniqueness
716716
717- cache_url , _ = save_image_to_cache (base64_data , filename , {}, ignore_info = True )
717+ cache_url , _ = save_image_to_cache (base64_data , filename , {}, ignore_info = True , context = context )
718718 image_url ["url" ] = cache_url
719719 except Exception as e :
720720 _log (f"Error caching inline image: { e } " )
@@ -733,7 +733,7 @@ def cache_message_inline_data(m):
733733 filename = f"audio.{ fmt } "
734734
735735 try :
736- cache_url , _ = save_bytes_to_cache (base64_data , filename , {}, ignore_info = True )
736+ cache_url , _ = save_audio_to_cache (base64_data , filename , {}, ignore_info = True , context = context )
737737 input_audio ["data" ] = cache_url
738738 except Exception as e :
739739 _log (f"Error caching inline audio: { e } " )
@@ -751,7 +751,7 @@ def cache_message_inline_data(m):
751751 ext = file_ext_from_mimetype (mimetype )
752752 filename = f"{ filename } .{ ext } "
753753
754- cache_url , info = save_bytes_to_cache (base64_data , filename )
754+ cache_url , info = save_bytes_to_cache (base64_data , filename , context = context )
755755 file_info ["file_data" ] = cache_url
756756 file_info ["filename" ] = info ["name" ]
757757 except Exception as e :
@@ -767,7 +767,7 @@ def __init__(self, status, reason, body, headers=None):
767767 super ().__init__ (f"HTTP { status } { reason } " )
768768
769769
770- def save_bytes_to_cache (base64_data , filename , file_info = None , ignore_info = False ):
770+ def save_bytes_to_cache (base64_data , filename , file_info = None , ignore_info = False , context = None ):
771771 ext = filename .split ("." )[- 1 ]
772772 mimetype = get_file_mime_type (filename )
773773 content = base64 .b64decode (base64_data ) if isinstance (base64_data , str ) else base64_data
@@ -790,6 +790,7 @@ def save_bytes_to_cache(base64_data, filename, file_info=None, ignore_info=False
790790 return url , json_from_file (info_path )
791791
792792 os .makedirs (os .path .dirname (full_path ), exist_ok = True )
793+ user = context .get ("user" ) if context else None
793794
794795 with open (full_path , "wb" ) as f :
795796 f .write (content )
@@ -802,6 +803,8 @@ def save_bytes_to_cache(base64_data, filename, file_info=None, ignore_info=False
802803 }
803804 if file_info :
804805 info .update (file_info )
806+ if user :
807+ info ["user" ] = user
805808
806809 # Save metadata
807810 info_path = os .path .splitext (full_path )[0 ] + ".info.json"
@@ -810,20 +813,21 @@ def save_bytes_to_cache(base64_data, filename, file_info=None, ignore_info=False
810813
811814 _dbg (f"Saved cached bytes and info: { relative_path } " )
812815
813- g_app .on_cache_saved_filters ({"url" : url , "info" : info })
816+ user = context .get ("user" ) if context else None
817+ g_app .on_cache_saved_filters ({"url" : url , "info" : info , "user" : user })
814818
815819 return url , info
816820
817821
818- def save_audio_to_cache (base64_data , filename , audio_info , ignore_info = False ):
819- return save_bytes_to_cache (base64_data , filename , audio_info , ignore_info )
822+ def save_audio_to_cache (base64_data , filename , audio_info , ignore_info = False , context = None ):
823+ return save_bytes_to_cache (base64_data , filename , audio_info , ignore_info , context )
820824
821825
822- def save_video_to_cache (base64_data , filename , file_info , ignore_info = False ):
823- return save_bytes_to_cache (base64_data , filename , file_info , ignore_info )
826+ def save_video_to_cache (base64_data , filename , file_info , ignore_info = False , context = None ):
827+ return save_bytes_to_cache (base64_data , filename , file_info , ignore_info , context )
824828
825829
826- def save_image_to_cache (base64_data , filename , image_info , ignore_info = False ):
830+ def save_image_to_cache (base64_data , filename , image_info , ignore_info = False , context = None ):
827831 ext = filename .split ("." )[- 1 ]
828832 mimetype = get_file_mime_type (filename )
829833 content = base64 .b64decode (base64_data ) if isinstance (base64_data , str ) else base64_data
@@ -846,6 +850,7 @@ def save_image_to_cache(base64_data, filename, image_info, ignore_info=False):
846850 return url , json_from_file (info_path )
847851
848852 os .makedirs (os .path .dirname (full_path ), exist_ok = True )
853+ user = context .get ("user" ) if context else None
849854
850855 with open (full_path , "wb" ) as f :
851856 f .write (content )
@@ -857,6 +862,8 @@ def save_image_to_cache(base64_data, filename, image_info, ignore_info=False):
857862 "name" : filename ,
858863 }
859864 info .update (image_info )
865+ if user :
866+ info ["user" ] = user
860867
861868 # If image, get dimensions
862869 if HAS_PIL and mimetype .startswith ("image/" ):
@@ -879,7 +886,7 @@ def save_image_to_cache(base64_data, filename, image_info, ignore_info=False):
879886
880887 _dbg (f"Saved image and info: { relative_path } " )
881888
882- g_app .on_cache_saved_filters ({"url" : url , "info" : info })
889+ g_app .on_cache_saved_filters ({"url" : url , "info" : info , "user" : user })
883890
884891 return url , info
885892
@@ -1550,7 +1557,9 @@ def g_chat_request(template=None, text=None, model=None, system_prompt=None):
15501557 return chat
15511558
15521559
1553- def tool_result_part (result : dict , function_name : Optional [str ] = None , function_args : Optional [dict ] = None ):
1560+ def tool_result_part (
1561+ result : dict , function_name : Optional [str ] = None , function_args : Optional [dict ] = None , context = None
1562+ ):
15541563 args = function_args or {}
15551564 type = result .get ("type" )
15561565 prompt = args .get ("prompt" ) or args .get ("text" ) or args .get ("message" )
@@ -1571,7 +1580,7 @@ def tool_result_part(result: dict, function_name: Optional[str] = None, function
15711580 if not base64_data :
15721581 _dbg (f"Image data not found for { function_name } " )
15731582 return None , None
1574- url , _ = save_image_to_cache (base64_data , filename , image_info = image_info , ignore_info = True )
1583+ url , _ = save_image_to_cache (base64_data , filename , image_info = image_info , ignore_info = True , context = context )
15751584 resource = {
15761585 "type" : "image_url" ,
15771586 "image_url" : {
@@ -1593,7 +1602,7 @@ def tool_result_part(result: dict, function_name: Optional[str] = None, function
15931602 if not base64_data :
15941603 _dbg (f"Audio data not found for { function_name } " )
15951604 return None , None
1596- url , _ = save_audio_to_cache (base64_data , filename , audio_info = audio_info , ignore_info = True )
1605+ url , _ = save_audio_to_cache (base64_data , filename , audio_info = audio_info , ignore_info = True , context = context )
15971606 resource = {
15981607 "type" : "audio_url" ,
15991608 "audio_url" : {
@@ -1618,7 +1627,7 @@ def tool_result_part(result: dict, function_name: Optional[str] = None, function
16181627 if not base64_data :
16191628 _dbg (f"File data not found for { function_name } " )
16201629 return None , None
1621- url , info = save_bytes_to_cache (base64_data , filename , file_info = file_info )
1630+ url , info = save_bytes_to_cache (base64_data , filename , file_info = file_info , context = context )
16221631 resource = {
16231632 "type" : "file" ,
16241633 "file" : {
@@ -1640,20 +1649,20 @@ def tool_result_part(result: dict, function_name: Optional[str] = None, function
16401649 return None , None
16411650
16421651
1643- def g_tool_result (result , function_name : Optional [str ] = None , function_args : Optional [dict ] = None ):
1652+ def g_tool_result (result , function_name : Optional [str ] = None , function_args : Optional [dict ] = None , context = None ):
16441653 content = []
16451654 resources = []
16461655 args = function_args or {}
16471656 _dbg (f"{ function_name } tool result type: { type (result )} " )
16481657 if isinstance (result , dict ):
1649- text , res = tool_result_part (result , function_name , args )
1658+ text , res = tool_result_part (result , function_name , args , context )
16501659 if text :
16511660 content .append (text )
16521661 if res :
16531662 resources .append (res )
16541663 elif isinstance (result , list ):
16551664 for item in result :
1656- text , res = tool_result_part (item , function_name , args )
1665+ text , res = tool_result_part (item , function_name , args , context )
16571666 if text :
16581667 content .append (text )
16591668 if res :
@@ -1781,7 +1790,7 @@ def get_tool_property(function_name, prop_name):
17811790 return None
17821791
17831792
1784- async def g_exec_tool (function_name , function_args ):
1793+ async def g_exec_tool (function_name , function_args , context = None ):
17851794 _log (f"g_exec_tool: { function_name } " )
17861795 if function_name in g_app .tools :
17871796 try :
@@ -1792,9 +1801,9 @@ async def g_exec_tool(function_name, function_args):
17921801 is_async = inspect .iscoroutinefunction (func )
17931802 _dbg (f"Executing { 'async' if is_async else 'sync' } tool '{ function_name } ' with args: { function_args } " )
17941803 if is_async :
1795- return g_tool_result (await func (** function_args ), function_name , function_args )
1804+ return g_tool_result (await func (** function_args ), function_name , function_args , context )
17961805 else :
1797- return g_tool_result (func (** function_args ), function_name , function_args )
1806+ return g_tool_result (func (** function_args ), function_name , function_args , context )
17981807 except Exception as e :
17991808 return f"Error executing tool '{ function_name } ':\n { to_error_message (e )} " , None
18001809 return f"Error: Tool '{ function_name } ' not found" , None
@@ -3222,14 +3231,23 @@ def to_file_info(
32223231 return to_file_info (chat , info = info , response = response )
32233232
32243233 def save_image_to_cache (
3225- self , base64_data : Union [str , bytes ], filename : str , image_info : Dict [str , Any ], ignore_info : bool = False
3234+ self ,
3235+ base64_data : Union [str , bytes ],
3236+ filename : str ,
3237+ image_info : Dict [str , Any ],
3238+ ignore_info : bool = False ,
3239+ context : Optional [Dict [str , Any ]] = None ,
32263240 ) -> Tuple [str , Optional [Dict [str , Any ]]]:
3227- return save_image_to_cache (base64_data , filename , image_info , ignore_info = ignore_info )
3241+ return save_image_to_cache (base64_data , filename , image_info , ignore_info = ignore_info , context = context )
32283242
32293243 def save_bytes_to_cache (
3230- self , bytes_data : Union [str , bytes ], filename : str , file_info : Optional [Dict [str , Any ]]
3244+ self ,
3245+ bytes_data : Union [str , bytes ],
3246+ filename : str ,
3247+ file_info : Optional [Dict [str , Any ]],
3248+ context : Optional [Dict [str , Any ]] = None ,
32313249 ) -> Tuple [str , Optional [Dict [str , Any ]]]:
3232- return save_bytes_to_cache (bytes_data , filename , file_info )
3250+ return save_bytes_to_cache (bytes_data , filename , file_info , context = context )
32333251
32343252 def text_from_file (self , path : str ) -> str :
32353253 return text_from_file (path )
@@ -3478,8 +3496,8 @@ def context_to_username(self, context: Optional[Dict[str, Any]]) -> Optional[str
34783496 def should_cancel_thread (self , context : Dict [str , Any ]) -> bool :
34793497 return should_cancel_thread (context )
34803498
3481- def cache_message_inline_data (self , message : Dict [str , Any ]):
3482- return cache_message_inline_data (message )
3499+ def cache_message_inline_data (self , message : Dict [str , Any ], context : Optional [ Dict [ str , Any ]] = None ):
3500+ return cache_message_inline_data (message , context = context )
34833501
34843502 async def exec_tool (self , name : str , args : Dict [str , Any ]) -> Tuple [Optional [str ], List [Dict [str , Any ]]]:
34853503 return await g_exec_tool (name , args )
@@ -4303,6 +4321,7 @@ async def upload_handler(request):
43034321 if not is_authenticated :
43044322 return web .json_response (g_app .error_auth_required , status = 401 )
43054323
4324+ user = g_app .get_username (request )
43064325 reader = await request .multipart ()
43074326
43084327 # Read first file field
@@ -4357,6 +4376,8 @@ async def upload_handler(request):
43574376 "type" : mimetype ,
43584377 "name" : filename ,
43594378 }
4379+ if user :
4380+ response_data ["user" ] = user
43604381
43614382 # If image, get dimensions
43624383 if HAS_PIL and mimetype .startswith ("image/" ):
@@ -4372,7 +4393,7 @@ async def upload_handler(request):
43724393 with open (info_path , "w" ) as f :
43734394 json .dump (response_data , f )
43744395
4375- g_app .on_cache_saved_filters ({"url" : url , "info" : response_data })
4396+ g_app .on_cache_saved_filters ({"url" : url , "info" : response_data , "user" : user })
43764397
43774398 return web .json_response (response_data )
43784399
0 commit comments