From a2d4716e53e75037e99fe5d55dc664b74e68c9e3 Mon Sep 17 00:00:00 2001 From: "Fred N. Garvin, Esq." <184324400+FNGarvin@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:36:32 -0600 Subject: [PATCH] feat: Atomic downloads, periodic logging, and smart path selection --- __init__.py | 35 +++++++++++++++++++++++++++++------ icon.png | Bin 0 -> 25120 bytes pyproject.toml | 3 ++- web/serverDownload.js | 2 +- 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 icon.png diff --git a/__init__.py b/__init__.py index f0d6552..a9d3e71 100644 --- a/__init__.py +++ b/__init__.py @@ -69,7 +69,9 @@ async def start_download(request): ) # Get the first folder path for this model type - output_dir = folder_paths.folder_names_and_paths[save_path][0][0] + # Get all eligible folder paths and find the first writable one + available_paths = folder_paths.folder_names_and_paths[save_path][0] + output_dir = next((p for p in available_paths if os.access(p, os.W_OK)), available_paths[0]) output_path = os.path.join(output_dir, safe_filename) # Final security check: ensure the resolved path is within the intended directory @@ -258,8 +260,11 @@ async def download_file(url, output_path, download_id): logging.info(f"File size for {download_id}: {total_size} bytes, supports range: {supports_range}") + # Atomic Download: Use a temporary file ending in .part + part_path = output_path + ".part" + # Create file with full size - with open(output_path, 'wb') as f: + with open(part_path, 'wb') as f: f.seek(total_size - 1) f.write(b'\0') @@ -279,7 +284,7 @@ async def download_file(url, output_path, download_id): end = start + chunk_size - 1 if i < NUM_CONNECTIONS - 1 else total_size - 1 tasks.append(download_chunk_with_progress( - session, url, start, end, output_path, i, download_id, total_size + session, url, start, end, part_path, i, download_id, total_size )) # Download all chunks in parallel @@ -293,13 +298,17 @@ async def download_file(url, output_path, download_id): else: # Fallback to single connection download logging.info(f"Using single connection for {download_id}") - await download_single_connection(session, url, output_path, download_id, total_size) + await download_single_connection(session, url, part_path, download_id, total_size) # Check if cancelled if download_control[download_id]["cancelled"]: - os.remove(output_path) + if os.path.exists(part_path): + os.remove(part_path) return + # Atomic Move: Rename .part to actual filename on success + os.rename(part_path, output_path) + # Mark as complete active_downloads[download_id]["status"] = "completed" active_downloads[download_id]["progress"] = 100 @@ -337,6 +346,7 @@ async def download_chunk_with_progress(session, url, start, end, output_path, ch chunk_size = end - start + 1 downloaded = 0 last_report_time = 0 + last_log_time = 0 try: async with session.get(url, headers=headers) as response: @@ -367,6 +377,12 @@ async def download_chunk_with_progress(session, url, start, end, output_path, ch # Send progress updates every 100ms to avoid spam (only from chunk 0) import time current_time = time.time() + + if chunk_index == 0 and (current_time - last_log_time) >= 60.0: + progress = (total_downloaded / total_size) * 100 + print(f"[AutoModelDownloader] {download_id}: {progress:.1f}%", flush=True) + last_log_time = current_time + if chunk_index == 0 and (current_time - last_report_time) >= 0.1: progress = (total_downloaded / total_size) * 100 active_downloads[download_id]["progress"] = progress @@ -389,6 +405,8 @@ async def download_chunk_with_progress(session, url, start, end, output_path, ch async def download_single_connection(session, url, output_path, download_id, total_size): """Fallback single connection download""" downloaded_size = 0 + last_log_time = 0 + import time async with session.get(url) as response: if response.status != 200: @@ -412,6 +430,11 @@ async def download_single_connection(session, url, output_path, download_id, tot active_downloads[download_id]["progress"] = progress active_downloads[download_id]["downloaded"] = downloaded_size + current_time = time.time() + if (current_time - last_log_time) >= 60.0: + print(f"[AutoModelDownloader] {download_id}: {progress:.1f}%", flush=True) + last_log_time = current_time + await PromptServer.instance.send("server_download_progress", { "download_id": download_id, "progress": progress, @@ -565,4 +588,4 @@ NODE_CLASS_MAPPINGS = {} NODE_DISPLAY_NAME_MAPPINGS = {} __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"] -print("[AutoModelDownloader] Linked and Loaded!", flush=True) +print("[AutoModelDownloader] Linked and Loaded!", flush=True) diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5a38c680932eeb4cecf84685abb2cd37921b8598 GIT binary patch literal 25120 zcmW(+1zeMF7c~G!kC6&UjT9s$rA7^qk`$zsknRTQmhSHEt|1{P9nvKrU6P~5zW4wA z*gLl0#(1Cm-h0lu=RONpRhGlYd4coj(Ib3$xb%DAxBGtw2n)Cu`our==#lY`ytJf- z`{TnN?9OdBeVSY34$^PTDS5#>J`I{68U!Y84#J3i6Z9zHCw;E;p`xW%6=@S`;YB%o zMyt+q(nKxqP!*e&{z<-s#FKhxY;5$Q7gNFl@+fl$-L)gcoPepScv6MDEJvcoc2@6J z&qNjItM;&nv51MW`d94qQ9;_s=bVb(}(v#;+Z%K+)jc9fD|COkN|0z z^l}NX7=;>@n7CY0pFB9J%*4c?6iIu}qr6M{Fr2#52p%%&%OYJU$wp2!G(P@yx`#~6 zV;Ry2*a+^7x>_{!J)>oSjs`rb{Jl>N&s1bx$V+_D7oH5rES)o9Ug^VHJ1?UBi zPd;Ng&0e6|1hi{vcSr|fN+e$>1B1b=PE`z4p=woy`Av|?czAj;{Dp}m5TCHHusTpM zTe*f|`HAM*!Clkbt1; zY@aLMoF?NwEVM|N2OYei$%6VR42Os?Og12lHY^d-Qc{C7f~`D7Orh+eJpWQHeBUbx z{-#KSXsZ?q3eJy(rIGie^_p#0_I*x#a-KfB5-~$@e-qlKKrg{d=}Re~lHMIq`uMPu zeDJx6B&kf1bPd~knFzMTI@q~Qgrg2?p#m$BCL^h)nhfcTdi3?G_i3b|^Qk$f>)$xJ z+{W2^J35v`na@46FcV4kFd3pCup|p1(Yc8MJ4-ppgdK!U9{`5~FO{+dYp@oU!qhZL zP%H!aVIGsZlk}%%YTP;N40S$(boDb9Z< zEOS|OvL~mZLaM28Q(fJ0EZlu3(rwBoQ189K!>gDqxbc(Wuy$rB=@kbHNyPpzLe%SM zttAF_L&NhT`lHtm0hC|SatS*d*7lE1=_nZ!1L(F4d&C`-9uyD@hou+FTj^Tq&RMQV z=rUV2GKCk)!(b-t;ZL6twz{1&=?mB&)(uh;gle#`6_)0EvK5`k)3ZWw>T=7yFA8W} zj^51aG?+!tx+HVxnJv_RHtUeGJ+5wX{`FpyjMPWG-tNSp!1ogu1xw_6vL699dd)g* zo=vmqeeKofrGr^VH2OCL!E9J${rRyvu{tE-cRzICP&y!MrW(oQ6J`rt;+ZUU4+;+& zXQOW8>JLHLz z&KmMUhJ~(>-J**3MKq8arh9h=R--Mi*2->q_-Xq)DI)8_>fj@hspJ7L=^$xoX^8x^ zE^wxAER}TChl&hQ^)>f1%pXy~<5nGRLSMU5y~q6;Fr=uWjWo9Y9IqfQzO~FZTNa=% z22TW%TMhF(%Q!U3l29~ zB>i@9SRFoUm)_nU-vtgKO3Lw^g@$^B_)9{y9|3dFvB|Ty%bTzoc zRH0=@P=7B2cD-{us;W@nGjn*=KgzHjKa^}Cj0TYAPFEiRRnoq?a z^8Jj_2o%3v$D9Qpb5&YK#t}6_aBd8Ee`aaB$WZZN0{5}v;m9)=c5e#7* z%7;YeNBs!k`wtvJ5P3Klg0x*dY%xGNVNsqqV0bP^5XhNS>AXz0Bj50)7IxU&N{N6o zM9)sPTTriEFOA=37`|OA)9W_NKVUa(9yv?0irU_e!o+stXqyzJJidx>@*T3^+gatH zjFNQ%Y09F0TJQlStC0j^xNVz?Q4rVuq5)j=()Zg*cSlPdbJQ)X+vxDNHlZB!i1|HX zqzv6LagbzquJi=M%UJ2~AQ&&1E*L@-%1E+$P1*g$>_AJswJ%>&C!`4OO-^@AegR7r ztzENmTi&P^v2)t}Bc^Y9x!A<-y~$gQxDHjONbWJ}9U>h*8f_fs^eImm^9czuLiY1( zH`jO`{~^_)t{ZC3%80f>xFs;mRq<;1*xA}DL*(%~p3lf>%11W7_kqjH&?zv!2Z^+t z*iW}qJKf7O-{!obz1%%1?U8c~ujSJLp zMIY$|KWFcIM6{;4%$Z8;7J4-AxwZ8$Lp;Vsb`IIe7Tc65QQ2cM70hh(+)`+vPIox( zGdwH|&3c`;9+~1d*<7-`(K?J6Us44lq;8>l zzj9IwdBqh>$HX21USoBbw_Sd974n?@M>c{AG@Y7y*m<#B^s>t~wXvX@1i0nqe#3>g#a(ZwdSWcJhUp(btptu@rexcf}^oy@rJ!?~yqj1(3D8SR9H z^VH-^=V7P;fNm8Z8_Q%l1xpVb_c?CZ=C^BpVO5JkOePa{LO zXfhg<u-Rf=LA3K- z)}aM4`p3@*?_+=ARqD5lRrnp@_oL!dv$8JN(AP0Xt92{;X$;O)ZR;UcA02-g7DSP{ z9FYHt5C~{9WJa*VGBL+t( zT)E!}SzeZF$`UJjd+sGryR9nXw=2UYVq^)Lq+T0d%8b)I)RMow!yEvjW@93FVf2jf z5Lt)plA9YkK|E+%BitJ5lrs2*Zg+__f;SEfZ_07~{yghKcHhTkArBq*b`Zto0{q-m zo+CmrE!H=VYZV!Gtv#IR-U=VitHV{BFP@8QtjBZZEE;MoBtxCjMRBq)t43vAW_{+W zgjsojXFuL1ab}d)|CajE=^pk{fca`enrcb#U*^06lfVdft%alIPRW?wF)Q=CFI8!2 z*{=QRZ(P%_wl2rrmW6fz)qAwm;;}-5YVV#ulbkj*++vLpSsN6;HYPF`J;f$aq!uTs^4O`Q5c4 z!|5fZ2@V1p1ZXrLK+eonmR0hAkoZsN0DNsFc6RJG-@R^I0VWIsBbQ=C`rB*C`W_?i z?Ww5h4@}>^h-8d$4;t+L^XzvX>f28PD=qdW&lxs1>h!a!Y2W_#&@5y2yu900Kg2Ev ze^tleHx4}|AFDJgPIPh2$9o~G7~#cn^ggFZt6xqG;!gjY=-wx!_57bhX0c!CGY6IF zV!ew^a%msLHU)fd-efTiN31K41DK z=Gs*dBQ`LfE$VeR-#j{1G#utP!7%PwN!W$-aXp-0SBvqfET7Un*C!1npmw}1c)7j`KhP&CySngSR?JQ%>&%N+x!n)?YFi2p?Je~>Si<}ABK#kF)tIYbz2XPL)Uj~30b+Iuz>^iwMt(dJmUEb-|vBHm|eW$GAb#}Ak zb##CZ+*A=;;6yD~EW3}kc%P|=1J!U>UJxTXMkH6=Ck6^j~mF3u3OopC#AB80Lf@`ibAED5-03b91kIaC*lv%vCq! z!aq#tU-zbT`P2RvB{+SR<^Kb9AY66OXq)SjHH+V9`)8=4<}5k}l{Q1+DG{Voiz!tJ z!R~D~uf0=q*drCvH(c2K3xtTi9BCFYfixkU`N-P}@syjWY? z+8Dnt+V|={vqFCm*zNC>4zS<1jQQ`Fn7aQVC-%1?=ejj0NXgCa-<;p6gZbNS?lJe@ z1<^nwVE>z2?yiHX&9#bgIK^Y=X8a#Y#iu-!WvG))ljTA~%|~rljf^y+ywqfZToQa9 zL8g#cnhya$Pf54LCCfQ$_Dz*bb@!PgHIpbUjD0>VDV2wl>`*96N&Ks!RWr3q;|^k1 zMp^W7y&nLD<_@<_*@M}tg#LLWE-o^Ro+beU^OGJ_vN*!B<=t+x>un-gamc9A#K>nD zfpTdegHzL*O^d+^q2GD5*wsVia>u%D!DMDy(QxNp%xcwva0E`-d-_s@hT6>C_l{M% zm+ZF-LVCw5hjwD;&ttsqiP`m=HQuukMY^6WZcX$^%~E*;J@Z<4Ww7r1Su#yqgH+~H zBMDO`O?x}3jxBPilOFGuUICn^%0fa^#7ajO?K~x1Ft`%+N+-#tw-S=F1qU-E%H-$zCugd&%Gh7TJ%Hl63MiEvE}RL8`S;SYcH?F7=Z zoK_ohsu-u*3=f1YPm!$1viG8zMV{rVML3_;@=DnvcxvEM6j8VF(l16kaY%_6+3o7X|nP=t$Nrr&kRZpbYZl=@N zDTDYeLosu4mdAG5G2-C0z>0H1sOX_FBwYq+z3|sah7Pl|n>+OulH;TVFKn zgQ_q*EjRS8>d%L<>(qY=XH-nSex_MQX@hfZU48Wn-d%J(E~ z{k`TT+sh&C2dBXt`_9Y3msW${sH?lSzr?&fe;2v2ESGaMu%0C5xA2)sAgS8aY@R}y zBD(nES=s?oej7?x2&NAT>+b}g1D%#2JER(M<~W#h&o%COs`$}oq3F2lKzS$tkU%qr z=q*F{sp%YB!8fefb){g$RT1aSUpcY;Vmp2FrDTp{ zj+aSm(or_qi+>uORGJUZ@{A8g@cQg~E%=JWRn6{vJQ;$5g1~X$xKwh$MF4S=5y?xl z8`kw2nfysqS2?dFN6dSOUrWWqO$6WUb=jd9IK6L%i-KEKSkEI`5PL|UtIZtyyHSCq zE~k>N4z~_eafZ*X{>hntOZSq_rH0{!jLK!v?GzI5=nAHg8cF4_=N0)Qugb4`cf>0+ zliuIvmusk%=0~ud15VWoz&)&5Xg1AQyDKsT9}X&|l396|EX*w5o>N_hI#hk0N}o+H z+hgtfl?NSwAS?E}c0^AuFNa?z)H?rylw>-VTU8^5N~4!WeIk{}k7mcOibE$uqzWbr zA0*PMPzszTYEU>}m6#ZWdBlM+h_Hcnv+iMjQ*@i#T;#Mr0Y5Z>-?mi`Vl`LOaYd#?yIJ>7?av-dq9vFH>S%J_nyd^@FUWm@5>?@LLvS_@` zWoJQpElzWCl{)6UC)ETrKP()=SQrO?VR_5eeHU3%@7K3dZ2ySalnv3hjAM%us6#6W?O67UBiqHJ- zueO3*K}rL zQ4b<(N3$7rjmN2`{W^3cCX&YalosKD9SWnsV~V1lcl+LN^j=e~^t}vVRtd4^vxA26 zVHQ3~2nE2dQqwF~(0u-ikZh{(4SCll;fm9qHc9fj^Sf|6fetoXl!umYk_dw5^V~=j z;B`2DQGg&b*g}HcYiDdDQC z!AFrYypC&~7g_UHwwgWB}GywWd*ROJGSUcWA-)SM`bslGpFUqghA~hpT2>t!RJtz-->t8wI^?*A10e&ufWVCQEt z_|3-kc>Wk@A!JoSHMik3O*ZFd-4Dg$xvl3{OI2bf(Q-L1&2l+D&2_2dNUy1e?4xtP z8*Rj8v|VZ{1swNBUfTyRbL3r_p+}eDoj}bbM8ME18c;8~ZI1Xds-Gp-VhZ2<7lSZN z8q`mjRpdAEdZ%+UQ}O$V9H4{N(!50gnDt&0N3&?+Rgp$g{cd{2Yqurs*WBNE2+2Z^ z-bU*A`8U!0-R4y3Fu!pGDE+Vfd#h0$(e1C3ddHLKdF7Rw%B0b!rr{oO6R-xBZN}HA zeeDY$&b%h~Q^nVb3ue^>6p`S7)D&6>F1?A`1hPw@>l7cbH8vgtA4Y13PS-{sJ60G(7+tU3MCt^s?_fCAV z>vIL;aPr;WT<4fd*Z!J9q@*T**fsHNK88~kfNc%Hwaj{r_&-}>&0=n2HDIn$xAolG zo7-xQN_(yC_rqsiEPZpq%->i_SzU(cv#kBYr;9r&y9QoChn5I^Tn>O}LVebroA2vR z2P-se{L~!t-6-%rjpqb>E@U`uIEh++fYFb12J5xq@zdz^eH zcwf7Jv*n7F);u|@@tchF{R;z>R8Psn28!V2yzSnnlQT~5*$|Nv`$KtVNC2Z^ipMbJ z+OA>uaZ_<|Nh6u5CYeT>cJp;(UJjd^k z&uyEKd?xbg_+^dn@f)ogA=nE`?ou{WpUK;)61heMFirYzaH62O(B@QP#o0E`S1kJ5 zBBX=!(>R09)xjv~oz|{-2on<%9y60*xd2jxQqVV9iMV~PW(L6(28E(!C zpA&f%4>nd2=9V_g1^jlDx|!CyayE`pWBGoaD9qsUDG1RH`uq8c?|F3f^?r)}?UthT zs&@@T%ttv81gp<~Vc|nxc%I7r51CbT^O{p{S;vz1}7~w6tUgGp!)qAK}tG`_JDsu#4d$%z6kn_@MRtV@H$oEWCfls)o+Esjii@4Cd zW&1x@Xn(wIXuH&7-PTohpxUDhJJU01U+i*m`s z{Mv<_C~TEVr%(4XEXJ3Fz!F*6x>@UMDljuE3V$(8oJ!QS$nU^M%Kv2@Y(s_ zSIIezq=YfSmG~mX!Ooq1`dLBEeTsqOx;QU41)PC{ zkFDq+T~aenNA+`M#CsrD%79^8l1NSWfK(8*iqV0`?@-~EmBx|7zZ24P&y|(GRE5hN zZ4Un>oZ~tJbCZQ)V&ezTRA_k&d8oMUCn!5?mcP<(+I)qTlj*$EJbK*j+pyy0_8~UR zgPYUDV3|1{p41C}ZUKF`&qsPK1dHcU^7*XkHJg+rReS?*Mf|p=d(R1g{K;keEz)$j z$(JvS&(`h+fqu&NctWyh?nSv905bymZqdYmu(cPobiIl_(&PW&HB$Hfb8KmD>4bKv z0bh~EM)wNS>bBmC(eZxBKOH}I#vc~XSSdON_AV6Ap$^`w; zC3aOp^KoQ#JT@m1MhRtB(mUxV);dM~%HYLhGD-FAmhI1{~RKc&I_`xY5Dn@%=xt zXICQ-`uxXEmJ2<2!7{xCES{4etckkX=U~kZE(3!CJOKBv9=D4PxkNbtF z(_C>mJ-^9#L&JOD|7GcT(dJh?BVaU?t2pf)38Zx#eVtYoTKzk&+lP%V25h3+2}J_KHd&lPvrWiQpn~@hxW+TGk)Z@6hdkM-p)MH7E=U7_wUezB}40 zZR-TdoGH=}eJiGCPXl`-AjrsP;oXW+KjsSnQ8VtneKSkbVbEZ)V;_l{8&6;9oEwQ} zgy=?kT^&0fjNub3nD=RBytTYbn?>u`ZOLi1p(x!L1|X5;7jJlGA)#N!xQK7}eGc~R zJbM$e{}yK;wh}|LjzbP=P7!YR{$92nN+p(I7U5cxj947H7WtZdaT5@ZIBBWaSRBn{ zPVvfWKoaxGa5WLnKJl& zXEhDGdp*XxzsJc@?=9gE>4ew0mxBLupv4h;bJp|jDbSF}8qaFBlAEkw$2t=+{kv*dliXBa%4$}*`gEQ_<@B;@PEatt$!dl_Evw-&WF;OR z#`R(^0zo66WK6j`32}PEGlLI(hOIt5?Yre7ew2~oGxLebIiHk>W0I|%ERZa)|F<+= zN9u0A)g*+mJe6`135|;d6R{g=T^+KEdaC(62dG7R?=D_C$9-WOUAY4|TJ6=mTAF}O zxqn4z>v}{wH{ak@1I%}CcfG_91IWb&!%MP1StG0UuZ~u%R5eWu@^QB4t_~MAsmZ%$ zLZaO)tI{$vf4gM$ZO{Pi#@qF9mD=@V{QsI)Q+4&}?EAmWUi;J8U-qVo2yg@56FA=; zzC3jPb1cQg%pBdMitUqGe`aBo!tR9pi}kW&x~to3BD?EOI;v@ZrgSb`W3NJ+qOrJ! zXHq!u*J``z?9HENtH)1IJTip&%v1eCG{EwFlTBvxb=LK1FJ+nIE%Fr`$v6sS=JHR3 zxP}kI`U856RFm1)zduZo`y9NvkTK*gk7qL%J3Y;ITOStHfmF=BG`?J9czcFz-mx)k zh>Y&;8nLh)GxYn*iTX2a_$PI9POsU!?elO7rN*VFQbjz;kPhiHf@8PQDs9hMr`Ps7 zD{k{Gb~&@@p%Kp_pRwz=|5ndFBT@03N?`v`FRj^jy%DLTtnAslnPX%kxW05mbJ%2g zOVGm6rCcL$Gox9~iLrIYF(>rpho>C=H<+EH4Bq&n&EV2}oks~2<45U9v}{AjimG8( zvRSk2EuxXH;6+;Yp7*ZGs?9+$2YtFM5z!XWr2%5V(8mIlTk{1M_1Mz}4e-pCo?@!yS8OTPOrH-@OhXu6! zejO=xe|8;YH%x6lXb2s#IZ`5EmjBqj>DqFPm_G7qS!yVQpH$m zwl<$zajR=J_UF)Rw(r3tw_kCYGtN*Cl6dDxVw~7oE!r)N`-gthV{!3zB%<&SiFlU}D zrN<26LUi;2&JdjVPtyavzp(;j@%iyISTOQ(X#Kb!TFdU@E86;l2z-0Ys`6*CLR`)R^=kE>D;<dXN|bu;&h6DzWg%0&GFH5ujp;M#+Ir1$AMEv3?CP1bXsrr_@SJs z8VO#ARKI-a*xK-=ws(?LD1pQAx2(4gcOIYk58Vxn|1}W_Jggj1fO}J`Pj+t!z;F=g z9UPt?jwLUh8a<3ZBMAoi=V?l2l0Xy#jm}}TxI*B3TAYoa*`g$viqV2jzj@d;HVp4L z$Y{>puU0+CLys3nkF-&u4ZmKC{h+0o6Wlnb9DZT zw#%g^a9~2NIT51Ik-j;&Id>lyd%ntfE@P^E+WBDaFgV&`DwX)h%iy6aajts<-!3Hx z3MC?v#vqcEo=6O77!wTD>vrWG&0X(2AKQ%L9s3hPX)95gAo$tX*k8bB4Ow?S!h16a zO69ZiHof5|=rrv;G*TJ;#76~z(D_S9@c-&5>RP_syA$;F4)$_8F>!F{HyslpSMfx6 z-;7@9$8h@`?X?q_W`<+DpMaChV#|J(_~E?3O_6T#VGfKzf%7DzzfsLXV;(_85=3P* z$pVsA81e1yhn((#HWgnUzq<#*f4$n>5iG%S zx~sJ#+6a5m=Cmm0x2U%9-1Wy;{S0tg3If^Ae?sKvZ3p6k(CmkclJf-dn}p62mDNFK z{;i8?l^q#QPa<-CXQDvY?*(ZCiC$#K`K_uAC5gSP5JKLC*50@!tyqkJk-yt|wx8$p zLsOOKQkBg=X?@YM{#p4ooQ0Mymlj4F-k64qIUE?m|6;%=Kw7GY-;yGUjGZiWB8V1~ zELb8e-^lVHY&3&xVYNAGg(t7J)AT8M=e5apNMxkRdZ7N*FeS~nx-9A<$k-!y;lPyX&RE@0alr=stQ$$8f!a0*vi zs`WTvA~+WBuj`ZB>&Olf3QrhmVK8zq4nOhf8E)G@&-u=;;@(Sq-DHSkw+i*pSZxe++pNB+ndZ@i-y1&DheCQqATCX~dJ~P&Ew}NS=`;#ZTHG z@RKKXtw2i`jcaX1K7W0U%j#2GWaGY0hz4c2W%fvkZg*r4uZtiCx(sh2@shF%m5))@ z5yL^gJPgp^;ngQXQ_Olxy`qM#>1fB9lD*sP*y{~B^tagS{yWaic$#Z5=qVgGGBQkx zf;UUqQioZY$O!_6eZ>HQ*`vrjE*WcfHnn{c5hn}nF0Vw~jz5j1KJB|}v$}C5SoMo# z5TMzqG|%bLU$X5>P1+VLxJ#z+^`=A~u8vPlB^DJizJw}6Xs4siG&~7b+=A5m<(tbs z)FmJ?xS26G9%Eqy3nf(ReEpGWLm#jT4oH`0v6z8?=+eJ3K`b5-g~eJt3!XfS5OyD^1);z z0sRz{<~&i!u&*D?x3QvuMA;ZndW(LOa@L0Q`?~&q*u;`zAa=8Eqz)D8!RNvsyqEd| ze;8b;cvxsDLT~n)X;&5t8yY2_F(dXocz%)WI71T#3*Z7d>?jF1ZJUmn+HTEri(MQe z|HTmk6ZlsZ8W{zlgj`hkmQcF?7LNTG!VJ%Z`bz|a{drTno#uCaU($M$oH1W( z{4|5#CYa1Z@_R0I?MZnbUZ~V|a!QJjWGv&JEU%V|$jJUxfxE7d?~cQ)*s{aLnC2Iy zLJ3I8{6N~sEq0PL(N{tFO!_o6BA*KP1TdgXz?sL0K|Nuf5pqR(oe?t{>Ux&CioCy#$YbO?o=$!B>G?8Qe(b_#<&#$F_iUZeTTo(U>&r z)P3hqOVUjk`RiU~&DOJC`kRD~SJ&V#w~8;;&f5ov5o!^~Aiv9};{EG^p`~dcx)E!B zCVGoli4Brd@P=`JrUZ=W?fLU@tPy-e6b?~O3ojLckfiD}>Q^Py+q+{=TjkB}yk3qc zJojVm5x0xGmrXqKbYx1EoltLfKs1~Ms1*!<8&B;o zSimGfvNA#9i4-6M~QCuKfGvkHc<8pP_1q_7Px#vim1cTF|M(^p6Ejl}Nm zd&h4y!cp$6t~#k!{qpgT93n;;D0t14iT;h4i)BB@Ph6;h%O5H+Iy@aHENI#*mbPDfpPvQ(BrGnudnzN z7=7!pC2#l2yiwI6rA_Y@))QxJ9);EuKLjd*w9wCnMw>YUN*O~V^)s@1LxUPYd)%hID? z!UZ%m`594`a=35bXDPGvJ^tJX;x>BS!HU|Ct#9<_(JiJqF*7!m6ZnvuF=~+!Qca?O zLC3AAgU2oE81xE#hyK%vn=_>8cQd!#ai^8cZ@cl(ag61U2jaq$m3r-QWaY6#b5H() zE+`fQ1nrkM%j)4DFfxteZtkJ|(~*OIf^gljdB;SYoSZE9dH8htx@``nh&brTmYU{! zn?7mLUsU5oed0OSk;*$U_f1|zDw4x7*0R|yupyhwTHNiiThIRL(1X=0ud6F6!y}de zElg}{7NSHD9z0)dy~OvFymfmz$83DXFfTecZ=#$IY@UM_^u0u)dG%Uy20jX8#5bKa zrgSD!ia)qnjK4M;9ISN+!=mKx?DH@03pL+@El>nb9=b^p23uAMZ)Oa1W!Mw3 zl8b!`PB)9YSjUhB2em;)@s+b)f!DR%KeAuNk9S&)FryuVDNj-zKXLd!l3vtcW(-(O zN|&b%0)<=EJiHCPqAC2{Ycf40{b(T7yz5%VdbK|3KpaWVfCx40l^Q)=E^9)Uz8`N1i-9au!@gzDPwr#sA-c#|4-}MsQ2rLRfh2^JbPO!Ld)| zDU8D*FvxpoE=v4pU~7N&eAOtZ^=KyirRljup|KsySzGTulCyX$Q2&h&*( zy;H@bop*ESHyw7Z{&`QZ&3JjKzTQU6F;yNd5t5(T^P}9OT|IceyvVnafK^LRLy8{b z#7me|H~K%K`!7}LQi<~d3I?<4B*PN=mn|&grU6ZHJh*m7_5vd;0Rt2i+uuh~%WXvY zw7D+Y#sIZH=XgmjHVkZOtHTdzI(;z!I?Za`Z^+4CO7EYFou8=nJ__<;=0!|4R8N!^ zS>pJI&nA9Q+>TObkE3{unfh6U5`SQ%-c(0V>}pQigz{+v!N)vo-YQuPBe6RHn)SwM zH!h23-v8YEB9DL4NzfKNVod|~-hdu&_C50`v~@|ceb0&;ZuO%nAjm4dY2)28bF%}} z7{=)%(-Ca``FU9~0y<3|r590;pJI*d$C-NHpS^0mPOAA^7vo2TAC?gGhz`8g`xSpa z)9CxxXq#-;^=bE&BD?R(z!x}r_exIwR5pxDL(qu@axrI$-B((#(HDlqlp&?Kiz`+m zP(Xt}Z-T-&Wne%B8;)gJ)Gws)R_Z(-LC{WxXG? za(-oc`zvwL<#T}dn%4DSoX3ID6+B8Vk@wXpl4Cj zq2f><`g+KgMV$Eior3zWX2vg4MLg!YCbDc4>Kbqen6~}UGJnF{#0}44mnlgHKRs`k z=+hKNBHMO(!e)ZeLA-pLK~ghzxz{_!EGqHZ968-CKhErTVZ{c;!-riNRXo5W13&K z0F(ZS4495YvI(S}uar(f+b`c6_C=jUgPAts$r7+XL9nv5jpF0o zWz#fEyKmnTR!Ip%qHtK)RJnhhK1G^lgbKGG9Hc5V;wSVyqo5J|?vD1IC7?30K^qUq zedGG@;d67dY?jjA-M59s#OjkhE0vDMey7z7EZM;1m!$+6K^kQN zsAFR3@HCG$3!V!mqKEx9P*vg+Eqb0?{o@!cE1~lFPwz+KUo)UioSr8fd1w;K3VXpkhu_dMdRH!>d(g0X4_11 z1a+Q9;u$&ik27Ao^CSd56GYtEGTkAkt1g`rSR0z&6juzUDQT6VqD~is_C5{SpPOah zFo^$Df9=6~WFal&n|knYW%~V5i)^*?%sfz8HY394j~-)5J$>>Y75GcD!~&~~eIk(HodfhbXZhwO;Yj2 zZ%M^z!rc{OjZX}cClTDuWfXKk`fcR4n>RN8d@eHf=likfJFBe;y#fiBL zk{cUy-TngT5l;Kvhps5sOhu;)CNmd>yHW;?WW6HZSt&CQUN8%z zJx?e{8}%D`fek|1kHPc$A*o>t!B)&4lZYj_XQDqs}WshYSH zE%1#lxI5l#92E6$6BStL-N(=(r25-DjE=}0k-&uT0Qz~iG>yrY-0(D6juBxg) zM-Qlj02WDBOnEpA0t5Mf|B4r8cd$QhII40#665f9-k84Mp6io`Lt0pG3m6Uy0Ih@Q z-{s_26my71=_-iR@9ll8Q#vUO2lPuqBU_=;&kN=4;sk6zR1cxUvCs||wF<~cE5UT| z)u`YCqR#j?g_~)$`?%ld++>x9ALvhaS4UCH4S9GvW!St@swXe&XEe5!R!^kV))v5^`(t)Sf# zQdE`UagM%nx}WU6;Q$oOIS7JJ$oLorWN{Eo8l#9LANWxqQD9A+qQ!*Kax?cA-0ZG- z2jx5j=j5K4!+Uxy!hvkIP&8t0_#nq(v53`=4FQT6hX`;V5$VlLeZ_&UZ~@8*UM3rb zu(q+J*iz-iDK2wnAY(xDPUE5!ykRif_R0%tDxqW+HcE2JAuiS;9zD_Ct_rz%ehSA~ zkeR;R$=~lQhC4K?cgl!|z3!4vlD61y5{vT^14zEgXH+INWS_G)XZeYhP%U?5aC-ma zY&+e|>2F|NdLg)+Ru<|$A$64MTC9?gdg?xMZg>WH5JzKS&kuw&)TY zzxcpCz=o%2Jmm&wieZ%bH3i11qG;@?%dGo4zlagqJ{0YTl<)PY!h0r_J~hpUUxYyv z9BrNrY^S&goqw1gj89{?UjDhfx@5bP-hEALc(+Wxd-t-wzR5ockRrdD z`K!cWx=M~X52~j!l5h$ZHs=Lm5apr;ST&0Ta|WA&XOHoPKOA#Xr(2tt5tZRF|+TazgPduRb zXu-5#*b@vOr~iX2IwBkre<%rz4*J+cIg|e7UityzQCKr|ZEG!Fn7VZ>J|xgMlEZA8 zRcSgl&AB1_Jr3PZFkKu3_HK&Lr>K$miynoGB2=AeVe%&*&h25D@}dPi>H{+i&bIX| zc5v*E*({L{A9em9IuMfTx_HiSuqDd?F5^;cu$$#obhwo$b&Xo#I>?&vSXH}%+=gDH!e`5*H zXe>+XM2e$cHY^h3Kujr3rv^fnY&*kcpFB3n(qRTvlEi-{Os@)JRRyjxjE-Ic5Sd^? zF!SL;L#WT)NeML{UixE393zR5=UlYP@kXs&g(qwvjNiI(0iZY{>C~w2q)a|j<$;ni z24Ab`-Jr$s^O+OoMbeLC$+BLt5(EBW7-+zX*x=z-;NQBqFS!!Q?P0A_MQ%&l>`OY~ z_}76mx(h;7wH)zf#_?v!PlCS6&p9pFJvLu=)j_FE-Qh?sa@)30~C9Cjkf+{v>?Nq(~9VW@8d>ddd~cg~CaJ z@fV*G37dR@5jc2Ne(`JSOm^Ti!ZUw2L;@Ct2sSOWke1|vzoC*3$E;dfWMf&;a6Fpk zflKd2T@$zEuC*|wNSzYAF))M~aaiKR|j#-nbk~d*v@^4)5 zUUYrPL871Ad7vmiWVy@_@LMKeIlV6c|3{fH2q29h|If$&o)7`gX(ePK5N7Otffe_2 z?X*Zx`qV#Fep*uu3b2s`MHr;<#l)y^dUM{1Cy8VbND>EsL{WOcoN6*eC%cj9R{UxNxI9XJ)hwH`dhruJm2OK$1r^XW< zmf&D8E}d>T%T$RaG!`xa@j|#VKbZoqsD+K9x+ zLi&{S_Bfhzy!h{2*QDMQD#dGLG>nVqELh9Vxq!Hei|e92zDgJTr(l3_3>`gA-Xp-D z1o8}o4d5EU__N`}{Vo5i;XAoGt6`BLt);&pZVe89_rxLC;Oi)qu?x;K>~*&pkv67 zh`f%q(P3C~zE@Uw#}S18f_D^vYW$ zAU>WP^CddZ9lZyxn9eO66hFU<==y%0j;hX4R(MOareOfRbe$#sTKsnq8qB}hMMl5* zk2x>um-{u>h_umGK7`7PQq|!9G=H0NOeh)9+%yI}_9t!GPb2cembE=c{7JX z=@M|7ECn!Ga9q?~!;!guPxHa!ouT=Y-mQ}KLU_GWW{>!a*T~BBC@ZO=Y%aT_!vTV2 zEf`3106tcpB1qXdEm)TZ2H^_iq@pkIz_i*Ll3I z{qhKbaBL}e$K2?8*L}->f1xAWaXni$wRo^_u+VM)_ro_mb29_vKDds|S8jiPvFtYO zv5x^JDEjWYy^dXlB|Dlq zjwJj($#SL#4hs*Clau@C6_?I01Xc_h?xwrSP7OQ|a*Q-F_5DkjG#B9_oEY#|I%COo z`eps2N+G3me`xNa>mtoym|^pNJ8pT@=mM#Ru-9+| z{6bILztv|pyZ^dw{0^>Dn#4?_v$O~~?2aVC@R=X%S3+6*PcT3!(Aos9tnVzrAL2gz z!V-3^RLLRaz>)2`zQ;UUC?9_fxH$n+xs~lo-@F4gMQr#KkfRiC6{Ycz&c60$k>g@? zvi=~#Jaa7w1B!n>NOs*DPjgdEqzS!Q&G4Yh3@ue`9LD z5N_W0!&!_^I%-8KJc+nA;=S4Xn&bXcpLHfz+)g7E{2$PmeOK%;0gOHN>FhHV`I9H< z)tmfV0A0ueF4gxh0{fH-AGjsU#Ez9zy_}mBaBBq<*9;I77FX(UZZ4G5n6^wyi z=04x$DH0wnSD&G?GW%F-mG?BholEO=ulvUhep^V|7Qd*)x+;(n^?wj&|MXnz^?yPo zG?y6SrHb#Lb|zCCqj0s^);;T5K@>+Dp)nv4e;(FDmT0?L{0#fik==O2M(P;Wv94W} zFL2k*6YD|WxbRQ=IXLm<3$Hc#htxYbRaF1t?m*o&W* zKID6wS~4G;0a1>m$-)NGVANsZfhD3wc>KFIrCk4G^yFk zkNP|kbvL=etYnr^@llRFFCv>?YU!T6rU<_70NUU-HDhDr?!HEa06NIJXw07nKUU^= zz7@D7<@sdFZ|xwekN*}t2-2TW=)Eh|6iGY|Ao?87dGWIaGF^n2SiiRliS^sy10=vL zY7+-z|2YS&Ix>iP2S4-MwR37(d*sxy>wOGV;aP9rbNxV+j)IvoXHT1E@&l0VAoM=F z64ApfQ*<`%{jFJWiJw}cs-kM#OD?U%DCl@$VusRWPr7BsYYUDB0K5%dra}MRxL(jeE$!Txdp ztxDGB9O-CP2e$;+Eeh-Gbi&TUsV9^S#1{C9kMcQi;_f1q0OK!OtNe=aC#R(^%Y2Xd zh7g#aBMA2CYofx<8xyn?*IUX9@1_a3(^^ZEzaIW;V6`(Hyi&%mGxY*(&tJR}v(h)E zXPEu9<%OBm`+?C3u0CC#n5y(-vhra$Ufw-fDMIabGr>vH<8;+wt}cDytU&6|HjpCA z5-(zHGgB%vUB>U4EHz|0vpeSC^B-0NcH&(|hLQ=~B(JelXv)OxNh8+%zFRBM`|u*u zjNalakU^rs?*v!hSDkb;x<$MM0y^fKZ>q$yHD~$~hJK*p^nhIowpZj?~@lEUOlev9H4U1=LPS`aNn1 z8dy94C@8`v2X+8v19G{_b$GrUtESIvn?=-U(^!=`)N_ZRG@3pvMYyQ&;@;ZjkkUr| zDn$g5(^^{ScZf1sbID#avJ##3cu@Wem;K@<_8Ya9#)u+ zathA*u>a8i)5G)nhlDRuXBIh!NgO`gJB_pRvj;;}z8zD zhyKSVC&>W><<7InD%Yv4-RHL?sG)L-Z3O(nuGIN=;?6FkS9%vL2)XqR4P3FB%pFv!t--0n6fKO-D3!oS>U+6uxQ)ilnamHI09f>!ntEy1-9oer%`F0_AQ-(fq?`*Ra|0(>XR ze9H?8SgWTc>dR0RFkq<6)z%G_NC0wSJQej6G$w>9{udhTjq_&mWI;u zdH72Fl{AsqhwabM;DnQsn))|P$`EbTz#MyS$#g^o^}Vya%fjjNC8%40k!HM1JU2%~ zQ!$6P%-ew<@1}*lTc8P_c{dwE&FExBAFSCyGx(+~Z4A;;&90jXLU5%Ss=k_2#N)A}R^h8yQLhA`u66WhRB z1CvrDTiV@hBsNRc;&sAB9)S8}!sEiz`oISE3i%*bb&C>p^alE^0w9z()7geMlLD~L z#*VPju;-%c3=D7T1=)**(${IFsgpj7Lkl@sBMo1+;^=N#4VEx6`a?)nE1|}&L5d3gh!5cs@d4u z*2aQo^Va(1l(FK3vQA)ff?KAopqS@nn_BaZQ101g?r!m&htR!p4!?$qo@%N-hzsws zp1B7vQu#`$bTEY|Y6}VriUP`Z$^uV6cfbGly=S|yqaCMiN+R{ z0s%A(K}NA4N5dpTfzuT_8g})Bg+`eHOS-8hpjSsqBCnJ?ScKYePZ6*NU8`#Ce>Qd* z{c;WqSfY82QNVCA0WGDxaK&nH3I&{wE~94L+D$MdJ}s#@3BZW2mMqgeUyG94?svFB zW}R(9&ksbJ0M2)I7P=Qaa!wKJ^ZmZ>QfzKeji;uAq2JjO`MT!L`>``!-cKGsm5iY>bV-UXQ^SaOt0cDTn+RTft+jJ_ z5h9aJW6P<*8Td4Y&wUhyv7C;2irhjCXjzT%TEzEETD#K@2ugIfHEtDWI>XRk4Jx82 zLW-%JeFkxuv&l|^XT?-lvF-l!EE7&Cm!R*zxqg|v5O9#WW77P$o2hLfOzMRC_U$m8 zGK`&##}X{|NJ8qoKs8%(XT;FFKMTaYI$&C6WQ(Vy>P$PL+s;KX=$&*#bq0DQ@4=_uNuK$ z_Z>4t#Lb;(wDTe&v`Qb)sglrF({*p!T8(kuBPa+D3EB=g)NI6nDk8pWCc1e4(1HJYQ6C zGk`-haAw#xsSjBFmOM!C@X(dS>6>i(_%DWKNqGJ=`Sa=aQxIfXk0DYdCEQ|ZvQHfC zP?n$M3eQ7m1D64}L!vg?4TU1D1h?9^EWm!i8V8hCLsL{@u3b4dXS6xLyQ=c@No}ol zYpa+tqEbv;+?9wm@KbNRJWYNf%$k2VQONlIpfuUYIE@3P6)Av=Sk_9|xC)mE^{e%C6}rfYA-OW<5qmtXlV=J2alSbrJW7JY9wwKP%B zlS;`@8GF8hBVKF7de^Gp1AZB~yle7!cN#G{U}s}hZ;-y$U#i(!xy^L4Uq$pLF8XxL z0?u4+4&Oz|0_uargoNKmF78VCHa17NmdjjGsc9!lWPpJb917-#m3Xs57Pk!ZZUH{z#sY!Jw!viAE)IPQYIHr)spu7whJlrEO*8>*1O=zftK1ECL!@ zJltA^B@oHK8ZGTbVq!ar>H|iJ;msMQm1(FvUb;{)QihLV$K+_~qU`Ch3B5rGS z^Ye^=eEJpEl;ZDtvjKYYgm~*_F@2U;0J?PC=eUYNWV-Y3->$q1Bkh6o0~^1o*z>q5 z|D`*AkX^#Ruz9aO#>*9+0Ckxjq#VN?Y7USge;#L%k!DGLy+#Q4RRr}vqO4LB4B8Ej z@3F4k>%(Jr5>xiTlsSTpY@J; zWT7WCZ)fvi^%*fg;ACZCwPWxhCi5*EA?>AzkmTkBzHq2CKg}cmVl#NDurpkqFpS@k# zc(RE=Ke7GPI;b%rk=kK)2%vd2JGd+<)m}{L~1W? z?tQA*n}bKrzQgwI2Nlkm(hQNsfD?0pP*WT06+u5;ZyX<#&NoS#gGh#xbKx z^0jR%>U2<7x=UDk+rD?F^Gq4fXrxuf9;4mN&Pn-DBk8_$Gkfp(3G3}n*NpkKmSFBc z`BCNQaE&J#Mcg#x^5lDQ*OHaw6q_^2)gBG%&T}kMmn{X_jSa7v4aFVaY8nHNcy%S57S~ zwLlvHo@C$IWx)B$W80s4B?)$*!k%x;K@@CY@`<<6w%p_5>FfRCBRXO{&H+=i^PL?% zTB=$wcx7Y>%_@sD*?X%Gf?E#3 z-BXYigS%WyavO_oWY{Uc{yX7hGJOVnkhLYNRy<@f1f!1#je z?wnWWseR|#7yrY)x%YkaPqtV?V$V0jXdsnjEct8wHc~sK9gF%Sho>g{y*X!IYK@JJ z>wO(K!uc^hmXmB*ZW)<-q%WD{RcNn#iz^|)T`7?Q_MFP@Ep0{ew*`pF`7{S~E>=rKOiB+kXc2B?aM`&Np&^6QX%D#Ic>MRgZmjU-4R zClr`_bLT;~&QUKa)Qk5~MvY(*7h4)C-LN*fXEK0*H?by;SuNlh7dG($1WzqrBNzC; zjlTIcl^lYR$^P8>NxqH5IHq=8e9ULzA`I|kS;N-V7zYN%Cup!F!B*{PZ-{RGEj%Q+ zFfoB5n4+KA*a|o#+`#5Du5i_M?1^2JOTK^bIyshBOC~w&4%Yy3H7N14A$rxg_sv0E zTt0aj`yc{5T}YK^Aup;!5<;pRqV+#j$n@xFW0aFwt6hv8CP-I%(gidt9Fpz*H^e$- zk*<)(EWdw?pKhuh6alQMb#daLAKFH8bn+RI5a4WMGsXI3aCz6WbFlfq20H4~_{Mn~ z$8>W3?9|-w_U+rMxsr}s(N#X#qMJ}qLPC;d9Lr|HcV=18)u~Xg07k9C=JryAF(__> zaUC8ewf`9`nTYR0hb7U&Oyx9zAQ~2VZFROhZUu9GQtQ5m8rmeSQn{oEi+I;^t#Au@ z7UX?xawQ{OZAg@!wtl@rV8Z@q5o)HX!4AAn+ai5OS4gJwv7(v}ntywH`$Vr3=mPum zCE!mV;8!W9=jW?u(&6KU^{z|mjUWE5OUzG-EnIr2`J9bA3ek6EQOIZ{K;WSM=L#J6 zArQI*#ap4=1^`-|iMz&6k8T*i;CA)-f&nSv%Ic3nNpUp?h4riLLHs;ZH`zF45UX;C zUedvr1H28~iky6$R~u%Cq$whGDd+41xs+2`Z*z(XV$#{Qt#}$_#9!C%_l%q}sGVnx z9P+sk(6fWMLVI9WO5YQXe;Mj1{Tu`Vk365+d(DG&Q_oIy()xbj1-0 z@Ns%ELR#vobMI76H*-(OVp}ivP=W!jxON>eF+dAes`;RPW;h?<0waY6emqA%R}cnP zDv*5xelhQ4#M%39$mDOkq6(c$bLmq(=}e2Gp8D=7T&Y{kO)DNw7r0U~A1RqOl$X`r zT3sFyqYW)u)+=P-q1AAKmr`kkX4`oPwmR}@yX6lcd-}+qil6C>_+k%y``vO^B6BYs zgpHd_w=yrcoR4BJv5l?kvDg)?&#nueiCE3y`}a!=P=cB}MT>1`zgQhguU+$MX!IP2 z7RLVBZg%^bEw#=sd4PO#mXHeen|2UN8HTVnNbYx0dd+4oY|p+q=8F}$50c}HO8Og# z!hq+&^BeQPtREnM9jqBmO&)z{!OItF(s>~4sBLeTV>@gDEeYmkvTwOi3^0KS8vf62 z#jpi`HcDK|=t=m&c@WMOep}ulnVdVH6jVFyIP7HaF%z?|E-jkURLN13G3PsL;fvAr zOYYnoUf3R&+!-G_C`TFLdph@Z&u58;Wl)sh6kuzuO%Cdx9j>2#YsY!6z}KTCc{6(f zC;IPio~_O5pvk}MYL{&z2YW-HQbmY`A}r!j_Xbcq@XO#;885c3O&>aN&=*Rv8ujs9 z@WY?(c(#XV1BR*MRPH8il6^$`h!jAVZ~gmwyX7;96^~1PFjW$B6czLgJf^}oR3f57 zLhIu2mDR(rR&01ph-(Uvr-ru6nqmtWbO7-vHWt>x%+K_L zFm^FA_kf}5qMq0%aOJQLENwhje`8~weZZ!k<_7$Eb)j!<$bt-yQoJiWrLLVasRfuI z+nMR1S8D|rYr)xao6fy6-K{bNe3)PRk{Dh>(|fqlE8>7&Eq3}00;(-+oKx~i7RX?7 z5QvOc!F-d%ZIm0TlhJN>yrxtp!(~WqD9>r=BGU3c^nIw-fx6XZBrLQnEbOUChXaNe zNCD2R=1ym(ya~WO47JN|lrI7gLiS-Zh7^mFvD zSB<=p9lR-47H)Meb#Dxr9=CWOp~`?LC3?X-y27qk;M7viVMk)++mgNYdv7bA7`Dng z5K=Oh7&a0l2^lM&A{dD+@D`O|ZyaiM%J9s}ur3O>ppK7=>uGT|GKx9hT>I5KY7D1f z14frKBL`ETwXW~_v;h(PUVQ9a6@K^GN=U#38x%ce-14FS0xz++U*xyd%{n-i-Ff=J zC2fnCo3A3b+y(#n9lws5jnEQi?dC2|!H--&=$EaAAo3(<4x7yWejo z%sbO;*6gFPp1BpMjG&Q0EVq0Hae&A`f}!(2ONTrR$5D0pu?c7`)t+jR>c{k36kBpA zF2j(f;w(}t9)(z7kA!Z|_Hm%jyR7;601TYY#ly{UN&STrVPbLa#X`VXnAE>(e(qtq zl#CUzS0J!iWm`B~cw2$-#)~a1O}>(vsfhKii=A*_Q@tw5u%f}}4R2h^FnVp{$JxJM zOA}@Hj`7CLz8Ep=o=1S|s;pM2*Kum~L37xo^X%SUk50I~41M5P>NjwkjrV0rs1(5)agb;{c)fAR^iT9Z`T=-(xRh0WD~}m8r2}})Jz;tid_ro|F4JY~!j?+s_MpVrwzLcUCNdlr z$btk)33+OXk}Uu*hS8bWGwb4f<>6X2o$N;*Id#Y1q(r+hjDh>lrOCKBWDqj>?|&M_ z@ZW~r?PKQ{2ntM~au{Pg?nNUi(jRFT^$5y~bJ74lfMY->s>j>!Z7oKRiBWWV!Si@q ze;h!U#L=djFm6}mg}6I}#N_n7$@=$@%nNzzzCh(3K{D8HQd?AV1=Ik7goWC=cM`Bt zU$rZ)^gQD=HnZQ6>`>3OcDH2Z@P-?O?d}-(G=JGjnIo~y;yJzZPD*= zYJ=ob^^%BK?qxmk!mRKu<#+Dxe}FdC;~acjAEwqOTPy&}vGu;{5>9yd%qwjf*LGMW bNlj$3`Q|^g%2c%YAMl|huPRq5V;cB>P$$CQ literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml index cf820fc..a7e62b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,4 +31,5 @@ Documentation = "https://github.com/MadiatorLabs/ComfyUI-AutoModelDownloader#rea [tool.comfy] PublisherId = "madiator2011" DisplayName = "Madiator2011" -includes = [] \ No newline at end of file +includes = [] +Icon = "https://raw.githubusercontent.com/FNGarvin/ComfyUI-AutoModelDownloader/main/icon.png" diff --git a/web/serverDownload.js b/web/serverDownload.js index 446530d..742e1a4 100644 --- a/web/serverDownload.js +++ b/web/serverDownload.js @@ -626,7 +626,7 @@ function injectServerDownloadButtons() { // Create button content const btnLabel = document.createElement('span'); btnLabel.className = 'p-button-label'; - btnLabel.textContent = 'Download to Host'; + btnLabel.textContent = 'Download to Comfy'; serverDownloadBtn.appendChild(btnLabel); // Status indicator (icon)