+
    9Uj                    6   R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t]P                  P                  RR4      tR R ltR R ltR	 R
 ltRR R lltR R R lltR R lt]! R4      t]! R4      tR R ltR R ltR R ltR R ltR R ltR R ltR# )!u	  Supabase Storage — the WRITABLE shared file store for jarvis-tools.

A service account can't write to a personal Google Drive (no quota), so this is
the write layer: Jarvis/any AI on any device can save, read, list, and delete
files here, and they sync everywhere. Works from the cloud connector (plain
HTTPS, no OAuth). Files live in the 'jarvis-files' bucket of Ahmed's Supabase.

Env: SUPABASE_URL, SUPABASE_SECRET (the service_role key).
(Reading Ahmed's Google Drive uploads still goes through the drive_* tools.)
)annotationsNSTORAGE_BUCKETzjarvis-filesc                   V ^8  d   QhRR/#    returnstr )formats   "
storage.py__annotate__r      s     : :s :    c                 `    \         P                  P                  R R4      P                  R4      # )SUPABASE_URL /)osenvirongetrstripr	   r   r   _baser      s"    ::>>."-44S99r   c                   V ^8  d   QhRR/# r   r	   )r
   s   "r   r   r      s     1 1c 1r   c                 B    \         P                  P                  R R4      # )SUPABASE_SECRETr   )r   r   r   r	   r   r   _keyr      s    ::>>+R00r   c                   V ^8  d   QhRR/# )r   r   boolr	   )r
   s   "r   r   r      s     $ $D $r   c                 L    \        \        4       ;'       d    \        4       4      # N)r   r   r   r	   r   r   
configuredr      s    ""DF##r   c                    V ^8  d   QhRRRR/# )r   extradict | Noner   dictr	   )r
   s   "r   r   r   #   s      K 4 r   c                j    R R\        4        2R\        4       /pV '       d   VP                  V 4       V# )AuthorizationzBearer apikey)r   update)r!   hs   & r   _headersr)   #   s.    	GDF8,h?A	Hr   c          
     ,    V ^8  d   QhRRRRRRRRRR	/# )
r   methodr   pathbodyzbytes | Noneheadersr"   r   bytesr	   )r
   s   "r   r   r   *   s8     J J J3 Jl JJ(-Jr   c           
     F   \         P                  P                  \        4        R V 2VV R7      p\	        V4      P                  4        F  w  rVVP                  WV4       K  	   \         P                  P                  V^R7      ;_uu_ 4       pVP                  4       uuRRR4       #   + '       g   i     R# ; i  \         P                  P                   dF   p\        RTP                   RTP                  4       R,          P                  RR4       24      hRp?ii ; i)	z/storage/v1)datar+   )timeoutNzHTTP z: :N   Nutf-8ignore)urllibrequestRequestr   r)   items
add_headerurlopenreaderror	HTTPErrorRuntimeErrorcodedecode)	r+   r,   r-   r.   reqkvres	   &&&&     r   _dorG   *   s    
..
 
 EG9Kv!>T'- ! /C!'')q *J^^##C#44668 5444<<!! JU166("ffhtn33GXFGI J 	JJs7   $)B< B(
B< (B9	3B< 9B< <D A DD c                   V ^8  d   QhRR/# )r   r   Noner	   )r
   s   "r   r   r   8   s       r   c                 J    \        R R\        P                  ! R\        R\        RR/4      P	                  4       RR/4       R
#   \
         dT   p R\        T 4      P                  4       9  d+   R	\        T 4      P                  4       9  d    R
p ? R
#  R
p ? R
#  R
p ? R
# R
p ? ii ; i)POSTz/bucketidnamepublicFContent-Typeapplication/jsonexist	duplicateN)rG   jsondumpsBUCKETencode	Exceptionr   lower)rF   s    r   _ensure_bucketrY   8   s    FIJJfffhFGNNP/0	2  #a&,,.([A-N .O(s   A A B"<BB"zCabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-() 0123456789abcdefc                    V ^8  d   QhRRRR/# r   rM   r   r   r	   )r
   s   "r   r   r   J   s     2 23 23 2r   c                    \        V 4      P                  4       P                  R 4      p RP                  R V P	                  R4       4       4      # )r   r   c              3  l   "   T F*  p\        V4      \        9   d   \        V4      MR VR 2x  K,  	  R# 5i)_02xN)chr_KEEP).0bs   & r   	<genexpr>_enc_key.<locals>.<genexpr>L   s2      20q !Vu_3q6AaW+=0s   24r4   )r   striplstripjoinrV   )rM   s   &r   _enc_keyrj   J   sD    t9??##C(D77 2 KK02 2 2r   c                    V ^8  d   QhRRRR/# )r   keyr   r   r	   )r
   s   "r   r   r   P   s     
( 
(3 
(3 
(r   c                   \        4       p^ \        V 4      r2W#8  d   W,          R8X  du   V^,           V8:  dg   W^,           ,          \        9   dO   W^,           ,          \        9   d7   VP                  \	        W^,           V^,            ^4      4       V^,          pK  VP                  \        W,          4      ^,          4       V^,          pK  VP                  RR4      # )    r_   r4   replace)	bytearraylen_HEXappendintordrA   )rl   rd   ins   &   r   	_dec_namerx   P   s    Ac#hq
%6S=QUaZC!H,<qSTAQHHSqS1r*+FAHHS[4'(FA88GY''r   c               $    V ^8  d   QhRRRRRR/# )r   rM   r   contentr   r	   )r
   s   "r   r   r   ]   s!     7 7 7c 7c 7r   c                "   \        V 4      P                  4       P                  R 4      p V '       g   R# \        4        \	        V\         4      '       d   VP                  R4      MTp\        P                  ! V 4      ^ ,          ;'       g    Rp \        RR\         R \        P                  P                  \        V 4      R R7       2VRVRR	/4       R
V  R\        V4       R2#   \         d    pR\        T4      R,           2u Rp?# Rp?ii ; i)r   z'storage_write failed: need a file name.r4   z
text/plainrK   /object/saferO   zx-upserttruezSaved z to shared storage (z bytes).zstorage_write failed: N   NN)r   rg   rh   rY   
isinstancerV   	mimetypes
guess_typerG   rU   r6   parsequoterj   rq   rW   )rM   rz   r-   mimerF   s   &&   r   writer   ]   s    t9??##C(D8&0#&>&>7>>'"GD%a(88LD7Fhvha(:(:8D>PS(:(T'UVX\T:v6	8v1#d)HEE 7'At~667s   AC$ $D/D	D	Dc                    V ^8  d   QhRRRR/# r\   r	   )r
   s   "r   r   r   l   s     6 6s 6s 6r   c                   \        V 4      P                  4       P                  R 4      p  \        RR\         R \
        P                  P                  \        V 4      R R7       24      pVP                  RR4      pV  RVR,           2\        V4      R8  d	   R	,           # R
,           #   \         d    pR\        T4      R,           2u Rp?# Rp?ii ; i)r   GETr|   r}   r4   r5   z:
:NiX  NiX  u    …[truncated]r   zstorage_read failed: r   N)r   rg   rh   rG   rU   r6   r   r   rj   rA   rq   rW   )rM   r1   txtrF   s   &   r   r<   r<   l   s    t9??##C(D65HVHAfll.@.@$VY.@.Z-[\]kk'8,s3u:,'C4+<XXUWXX 6&s1vd|n556s$   A4B' B' 'C2CCCc                   V ^8  d   QhRR/# r   r	   )r
   s   "r   r   r   v   s     6 6C 6r   c                 H    \        R R\         2\        P                  ! RRR^dRRRRR	//4      P	                  4       R
R/4      p \        P
                  ! V 4      pV'       g   R# V Uu. uF]  q"P                  R4      '       g   K  R\        VR,          4       RVP                  R4      ;'       g    / P                  RR4       R2NK_  	  pp\        V4       R2RP                  V4      ,           # u upi   \         d    pR\        T4      R,           2u Rp?# Rp?ii ; i)rK   z/object/list/prefixr   limitsortBycolumnrM   orderascrO   rP   zShared storage is empty.z- z (metadatasize?z bytes)z file(s) in shared storage:

zstorage_list failed: r   N)rG   rU   rS   rT   rV   loadsr   rx   rq   ri   rW   r   )r1   r9   rv   linesrF   s        r   
list_filesr   v   s%   66]6(3::xWc'(FGU)KM NNTfh"$679 

4 -  2Q55=I2i&	*+ ,eeJ'--22263?@I 	 2 e*:;dii>NNN2  6&s1vd|n556sB   A!C7 %C7 )C2+C22C2%C7 2C7 7D!DD!D!c                    V ^8  d   QhRRRR/# r\   r	   )r
   s   "r   r   r      s     8 8 8 8r   c                6   \        V 4      P                  4       P                  R 4      p  \        RR\         R \
        P                  P                  \        V 4      R R7       24       RV  R2#   \         d    pR\        T4      R,           2u Rp?# Rp?ii ; i)	r   DELETEr|   r}   zDeleted z from shared storage.zstorage_delete failed: r   N)
r   rg   rh   rG   rU   r6   r   r   rj   rW   )rM   rF   s   & r   deleter      s    t9??##C(D8H&,,*<*<Xd^RU*<*V)WXY$455 8(Q778s   AA. .B9BBBr   )NN)__doc__
__future__r   rS   r   r   urllib.errorr6   urllib.parseurllib.requestr   r   rU   r   r   r   r)   rG   rY   	frozensetrb   rr   rj   rx   r   r<   r   r   r	   r   r   <module>r      s   	 #   	   	(.	9:1$J 	I	K#$2
(766"8r   