From d4745591a9831172a7b6828e2150d06946aa7d21 Mon Sep 17 00:00:00 2001
From: -Puter <22245429+puterhimself@users.noreply.github.com>
Date: Sat, 25 Jul 2026 16:12:04 +0530
Subject: [PATCH 1/2] feat(zopu): chat server, standalone chat route, and CORS
---
.env.example | 3 +
.../standalone-chat/standalone-chat-page.tsx | 186 +++
apps/web/src/routes.ts | 4 +-
apps/web/src/routes/standalone/chat/page.tsx | 16 +
bun.lock | 33 +-
docs/dogfood-plan.md | 1281 +++++++++++++++++
package.json | 4 +-
packages/backend/convex/_generated/api.d.ts | 2 +
packages/env/src/web.ts | 1 +
packages/primitives/package.json.new | 13 +
packages/server/data/zopu.db | Bin 0 -> 450560 bytes
packages/server/flue.config.ts | 11 +
packages/server/package.json | 29 +
packages/server/src/agents/zopu.ts | 42 +
packages/server/src/app.ts | 31 +
packages/server/src/db.ts | 4 +
packages/server/src/env.ts | 46 +
packages/server/src/git/gitea-service.ts | 360 +++++
packages/server/src/sandboxes/agentos.ts | 114 ++
packages/server/src/tools/issues.ts | 68 +
packages/server/src/tools/pull-requests.ts | 68 +
packages/server/src/tools/runtime.ts | 22 +
packages/server/src/tools/workflows.ts | 22 +
.../server/src/workflows/resolve-issue.ts | 159 ++
packages/server/tsconfig.json | 6 +
25 files changed, 2520 insertions(+), 5 deletions(-)
create mode 100644 apps/web/src/components/standalone-chat/standalone-chat-page.tsx
create mode 100644 apps/web/src/routes/standalone/chat/page.tsx
create mode 100644 docs/dogfood-plan.md
create mode 100644 packages/primitives/package.json.new
create mode 100644 packages/server/data/zopu.db
create mode 100644 packages/server/flue.config.ts
create mode 100644 packages/server/package.json
create mode 100644 packages/server/src/agents/zopu.ts
create mode 100644 packages/server/src/app.ts
create mode 100644 packages/server/src/db.ts
create mode 100644 packages/server/src/env.ts
create mode 100644 packages/server/src/git/gitea-service.ts
create mode 100644 packages/server/src/sandboxes/agentos.ts
create mode 100644 packages/server/src/tools/issues.ts
create mode 100644 packages/server/src/tools/pull-requests.ts
create mode 100644 packages/server/src/tools/runtime.ts
create mode 100644 packages/server/src/tools/workflows.ts
create mode 100644 packages/server/src/workflows/resolve-issue.ts
create mode 100644 packages/server/tsconfig.json
diff --git a/.env.example b/.env.example
index 76d0139..c08b730 100644
--- a/.env.example
+++ b/.env.example
@@ -32,3 +32,6 @@ AGENT_MODEL_BASE_URL=https://ai.example.com/v1
AGENT_MODEL_API_KEY=replace-with-provider-api-key
AGENT_MODEL_CONTEXT_WINDOW=262000
AGENT_MODEL_MAX_TOKENS=131072
+
+# Zopu lean server (standalone chat + work actor)
+VITE_ZOPU_SERVER_URL=http://localhost:3590
diff --git a/apps/web/src/components/standalone-chat/standalone-chat-page.tsx b/apps/web/src/components/standalone-chat/standalone-chat-page.tsx
new file mode 100644
index 0000000..9c21fc2
--- /dev/null
+++ b/apps/web/src/components/standalone-chat/standalone-chat-page.tsx
@@ -0,0 +1,186 @@
+import { env } from "@code/env/web";
+import { FlueProvider, useFlueAgent } from "@flue/react";
+import { createFlueClient } from "@flue/sdk";
+import { ArrowUp, Loader2, MessageSquare } from "lucide-react";
+import { useEffect, useMemo, useRef, useState } from "react";
+
+const STANDALONE_CHAT_ID = "zopu-standalone";
+
+const StandaloneFlueProvider = ({
+ children,
+}: {
+ children: React.ReactNode;
+}) => {
+ const client = useMemo(
+ () =>
+ createFlueClient({
+ baseUrl: env.VITE_ZOPU_SERVER_URL,
+ }),
+ []
+ );
+ return
+ {isBusy ? "working..." : "ready"} +
++ Chat with Zopu +
++ Ask about issues, trigger work, or check PR status. +
+xAMP#JMgkT)dLOyLJ2yo3^fAJa_5p zLaW(UFVe;E3x +C3a!Oi8JU$-^%x6a+Z z-0nkK-f700u%d3`GMe@E%}2X2G1+YBz`aJxW@Sa!%subyYc`v n$-$7{`=gCoHQR4q-t$8{C!yOWh-@ }4^(4D5V|%;wf>gW<7d*typwyMuQX=GC1xZ?4=K*wbY;CvRV@ z`E?Mp>rulp93TEh-y?lr>l^=< V9VADi@>RXl=;vQtm_Khlv(@5 _d|bZ<2&~l;Ky=?Wu}Q4L(}2{ zI`GLx_~)(R$; ;+IS gtt_J3}t z4eZhyHqmBKw%J09KH2I1pmn{Lti_mZ?0hD Y26wsH^`mMtEnW@TbGtyeeUm#O9c VuGPDAIZ@;L_GMx@E-JIF+#@lM zp^~5nt2EaaH%FOVPt!?JZMVYwz?ieA+~ePTs@=`7^8^_iwt2+Hquybaod;E_v8q?I z&Z)ES8b5jIiQ&mTn8I$Tw!4OIyT1SEueHXb53W8w^2CB1{dxfY^u`Tc&qmDcOtNvH zz=d?(*VuS=ubn$ >ID76Q9%;KF9@i^f z&Wp!wINyyI4>(U}B)~}=`TE?;R~If@&sSe>2UCeK*uPz5rgp_C6WU9UbkZ z$M$@UI)G@~SNk>Uw(HY}ab05m(c#J7dH2J#64BS!{~cOHXe~~ZaS`E;^ZAj 8G-8_@l~JH@tPSHr=0f!#lQqerGqlqs>7~&32>Yt&Z7H2D`O21vAsKhIRVoS5D_# zFihxj9@{pwayMZ7=G<4eCUs|Cd2Qj`*^8}J)ZHggV`Hx^oWZz!aUKr9HUu#|?Q*br zsxK_Oya0z_9_0Ak3kw-fF|{{Ov1x3b>omE$%I>J~14jRE@WiQs6Q@r6-o)DnJ-es# z5dwq&AwUQa0)zk|KnM^5ga9Ex2t0TQ+{l&;o3^6$kvh4 zOvP^E2zTfqFHVIcLv8zM?AyX~lpU!sw6z~_;d^cxhVss_fzjs{`>&35USngWc5@$B zmNlDte}bz-`;q2$ApF1 4Dk}2gdhXoU%6Nre%(pH`?Y!L;_RwD6iE@U8O z bncxUm(x_0 sjoa@h1FP*%=;A4Z&b?naQjDgP$&X45} zGL%e?emMe=K0Wa>2C9{bznb`qiGMTkXA}Qo;*Tf(aN-Xpet+WkCVqF~w
!;^lyyo*WXD*+) z RZeHxnAN?^mJkE3l|GOGOG6R|-26L2C2FapO=ZmurTj5U6Al9 V1N*Vufv%RTRN^ruv6$lecr{bcw^bsU9r}s%B3Hzb>e}75`-ZaE zt@k}{w=ETwTu+@KaX4-+UcYjKUtC%6E}UIxUO0Q5y;))G;+321 kF};_o3_S(1xv@ ztiHb?yWOj=HIO*jel38)eRDvZ8OdddUx%Gu#mBeREwit#EiY%FH{q#F&Eny lJ6b!!Pp`4BO%)@y4Pwyjz#+PYO~E {@Vv ~W{BpTC907&DNYui)cHU&cq}EIw{5;3NHEd_+Hpj~@x} z@ixcDo4~X0`ZM@= Ho_k`0$4D zA&!`hmyY}&eJA*dCr%6=|5wL<|M+hl|E1&KJT`ai 3Fs*C&FB$4>m)6aV TKOX&+(VrZ> zIeKpN>Cq!2|7_$Rj(mIM{gJPX$dSq6e>eR5!+(4Dr-oOC&kvs*9>FEj4 AhM!J-1hjFaGdeExz#lUM+s$hxTgm z`7iI)V(JI?YVp*U_G)3x?$zQ+xmSzNg?qL5{$Q^b-{ )!1`;G#H)Pqrr&1M}y(%JsKQ&c8>-_r}k(tcyf;h1J67; zG&k1K7kA?DH1?0~vj2;dL(g^Mm@V_2_(J#X$A6&v_G6##zWwM__wD0Pb>BW_b>BYv z *yr|Y@u~0MtHq<=w^xftp4h9!!=K%Y2zp)nei^d$l+*xmSzhpYD$2$Yb5N z4}Yrr_9KsW-#+w6_w9oZci%qn(5Hu<>$KF&(k8IE(?DAWxYzw1JHA(oqsR7YF@AKf z7GvXkwHO`StHsFZUM+@4_G)otc&`>iNA_wlIJ8%bfkA6%zVjJv^Xvwm9GV~9ZT)`$ zzGVNzuNsdsnfTSC`smZ+|0m}6D C*< zp)U{q#o(_DE+HnMG4bq)e|F**PFy~5^!RTbfA6?^>|Y)GrDI*dseL zJcoFJ4!iCg`1f-;W6vGPX+~!b InCh713AsWGYiIU zI_>!G?dIw1ES*+-_h lJ0~MAOr{jLVyq; z1PB2_fDj-A2mwNX5GX=`=Kn>=&~`$A5Fi8y0YZQfAOr{jLVyq;1PB2_;7}p(bgOu8 zL%*}8t1-%n`_m}>z1&o&V`wSVT6}-HTZQs8;VKT9uoLN`Zmw`qq1==RcBJERshOYp zk*PRYT R)8eT+S8PO62OqS1Pn!FJ-n!9Bzj) z@N5<&(q}R$D&LNZy^UHGUDje5#v-znUTwu;Ib%U#>jHBLd>QdTN!txrYzrk^I}9Sv zP9o_`mPXP`T _f$zW0U%hb6 zRJnd2Mk2?_nTx4^USKa?%$c8P&(_*YY{6J+t02*K6eK~U5?}bSL5PN;!)`A;XD_!Z z&7}f+;o9|8;6}FOaB_w3Ikt*pX*+QeY1eb{Qau1uBN~o+9**2CdzmS)6*mf`tHRip zk><9DQU|V!&tNNBraBB{6sDhG-vTD%nR-<>8tBs#ovO9vCcdqK4e04Rw(U8UCVT1G zUc{EYSXY)RjRKoVQYY}Zm)dR=VrmqH(vCbow3EaWA&X Csjoz1v(wOL G6U zzi5x!(tL2OG_1z;K*x~Dd=K<5Ibt^>3e<8zC*yjK6shOgehk+|gz$N#3PIOlX6=eF z3S3ow{)POP-aDB*w+nu$s_O+70}?9bk&5g<7zT!G4F<-G>@e1Dq~gfsj-o#1@b@u1 zNAOM;*orS=-%WjPyPA1eXJm;T`5s)DBuu6DJ>_Zn0N9FuPi9A$|DQa>3@^_!ywzHP z#b7G!dV$AmU&pB}JYU$-;ox_}L?w>UZt?)|yDks!iNzddYsvGw&01}_$mP{wa$T5( zojCAfgus+KVnJvJDik7MEWui2`MVf0m|h7xo+Egzs@91vik89@$>XUL*-okgTe#A* zBPE2b5*|9j7u@kQS Gdz7&xR0-YoQ^)3(YV1)VqDVw_~!r)ThM-YOa*i41m)9^^QCkF5w!)vL6 z4#pE{prXVD^8$iSgr1p9NAPr=lzAxv?-Eh|;1}v(dhcNJ W<~{{Z+gWHY_mOrGJbr3Kc)-561rk+g#ZSpvchv2-L|-%hmP zsWJ&kIwos5{Pc^PXLwiE3#`RW5?}k8nFVR2lLRcVL!_?R0mA|T=NOuF`6H%iJnGqn zar5+UtX5T2S*|oIx@cJ-6g&*v*tLD1gX9GZgSZAy+sskONs3d)^~sNUaOX< (q%)dmp5vi$fH_MQ%CKx5ccDgQJoP?2dW1F)8 zQP~U+6J)(vBh-OZI#f)UsHUyV#+ nwGQ<)9$Xtv?4i=8MgP}<#nnxZ} zsp^_Fy-z#A{Que0b1z==`I$49&s_2@yngA8i{4BAWfQWuqz)z?lWb-CP;}R}lJjz( zD)3sg<{sj_U0W$-q8KC+rg^O3@+N^y5*VTEI{NI>Qa*VraqmsY%YzfZaMxCn_ihWU z#Mi>a{6}_@<)&$A78gZi^E4Krn>sA=y9RiZm6SE@^{%ZX=hc4q+duuy0z-*hhLl%< zocfS~lw%0Kj5tT0S|GVXLWxZLuKEjPD2K*Sa&D|uB)#B7X{s3%fE-`L>p=t*77>!f z4jeyFS_`-*tkixijXK++pzgXq$%QFAy;9Jd#9Bwn#jxY)7;daeLpu`S`CTj@B7I)Q zaYSbFK&dU B3 zNJx}Aw!;MW;)i}1g@#3O%T30T6Wgm3+aVpcURx{5L`0~quTsgt^13h;qavmhT-rGD zvFa1Wi5GOuU8N4?&~zvrvSD#8DV98iuBoH_fZ4GJAxkU?fNX=r50(Tl1JbGQ#JuZ5 zG8xO^F_s)BYeUPSS`@~QXePNJ5OIX98_8SB^Laq67{M*E~(5sB55Yd2EFu_ _Bgvrw#krj(35TjOvJ>5s6Dnjby_!popH E%l2%}_PSEUUah7OO*l4ok0#WI9g2NVhO zpgYJ@a4Q}Z6F|~p>Krhn!Ka>LZr2d((wK^HDCe*v=kTr>xDJ`Hx?Zg{Dj0~0Vwqy7 zu}6NWz|)2%=1sw8fl8R21PEh_BS geSsqp=vdk$e)CO>2-J?Hx5b-!lcs=ifJ#!QEh&Ss!$p}>w6!xUL( zQ38oUo`CUpQrA=)Ds$*HnM&`blA~%*ohpcd6Crd1U5Fp}3T`dbN BsgMA1AsnU?67>I_#x>SOrLT{<3$q;d-xlfOC zpBzDJp#)g>;@=^7H|0fG`jHOw_>m80vVIV|0zF&pI8nsXQm+z1<&X@eM?=X|w9Ta= zhBgg7ByFTV;w2NL5rztuVgyxuDBN--Q a@lf(5ReoTDxJO1|gunxpf`W7X z1a^`t87Ezp-^#+LkeT#uCi$@1!dbG497v@@6C35=F-vwZ_d$FuBm(`=iyajFK=ewP z*%UIA-VG(k(9YMjY8E-QBG91&)&$YkSVR^eW^KtZZT6u>>L3v)hA=kS3d)?Ph#CbD zsO?tIN&;pjDQl~X%sGEO3mkr6vkKjONNuIjSSwToWbj!%-<0f3Bg~a0gF=Q6#hs8d z1o0z}871w=SPr+b?1!f1h;2jIYzRH300WQ)@1`P!IQ=9R2;ld;BrJ7OI}Jd+4?sEb z1M82!_Ok^(t&SCkYzjsm!_{Ij8IvFoa<(f|j%vFq_T+w3#W4S8jjgWPRQlcOoIgoT zK(dzJttC&@UeU`%<#v_Pq7*4|l) 3OM*nyH4Z^|^>j-LV8DHQH;Cq?;#e z3u^-<0lE(s7;W^(MAMq89THVRjI)dG21%%4somPZVZ`e9#_EflD6OTU+FDV%vdcoO z9wRu?@NF1~;@HNx xA0n8cJ^x#)3+h zNahF~^eJA1dYFk0qjK|aWG6lQDIy pJxY$LEz)Y@QR=4-igRd|!b#zfMh_D%>?FjLIfW_@dYn=ZJRZqh z_i83Np4Lji)2 f-CFbfPnE~d&MW A#*wP615Ja`p3 z?mGNH T~?@SvC&^8%C3&M^DokX1>&(1+-?h?2C_!Ec|mseCV(Nsgz508fFV z0?C6=LOaDqLKsFM=7)Bu1xOWNDW(;cn0cvVRLD?zcWLuPZBsRh0%{!x66g#;DyhN( z5ZqWO9;gsgAQx(riH>BLmYRAaQ|aAQax87p&=WdPP%#5e9E6Bv@=(Mj3P8a{P72 Ehtrao^lm13hE`RRg0Uw|7$Wo$ZXIe&fe?8BBVj1K09Ab~9)@8660X#1pV}{GZ2qYSznhw9UGTi#%G- zVNNO&&-N1(gAy)6RiqyyOcK(7P6~T*b-C#`>R5X2SaK|_RVi8^41Lc}z_Qs0a6{CA zL^gYb^0-(kbkf*&qnMRj?2S5>o;sGSQ_1tRsz{qDOq9b-MRv(dX(( zo}kU5t_$YL0rTS+QTjIc6NIOjiY}29DXMMz(gXSCq4YwT=gBf4(d%C4$vKX8rZA1r z4}v&Cg0iiA$ODQraxqa3p$w=35N}9h*HNj-d@_{YJCz(mTa-o^rXIwXz_z(q?|~1i zQ;@Te-qA5C %nZ0)}cVJ2*1RO$<(P#x1?yZ zROxISx_ePtKhMw>=Me@m6HqmPY*(y|Hbx9W1@#r+wMZ|Jh?RtrB=snVyGO}Ww6E4G zh2;qYtR};SRkrIP(-et65RrtomyNZ;z-LJSS@bgbwcC8!aK>>+@vTQf#m}>}#Yu$V zXr%;$l4{3PZ;8OX1%b5FFmNCih(dI%#LOER%0Uc2d6rfcE)b#ydy4P_6vq{aJn#Y- z3R74HicmvYN4`|7#4E|+4CFf=d`boL|Gu*r<5zT}f$FrG(}5bb_4P&Rz;kqsY>6M@ z@h}M8L?$OoB3vX2IK-s`Gu`NYrktZ`i`RZsB8@ODvrz*Ix_~LDH_V$|R8meErqFRJ zd5P7TU@VS&@Qvj@8%mC*ZOxPmSd|b9$pNHwP(Lh0(2l{{Bl98C-T6a|@l6kCufd= vXVW=0rloW@gVe2Zb3P|k0~?+-*kyZB&kO^fF32t@wCO!w5Y3%tYpYwhydM) z(5Rk_Fl^sWv5xHfFd;7}u_!GW%0U=Pj-$02tCgZ?CYB 6?es{f1bLcvZMDFi)oG-W5r*ItOo+kKCMe3mAaosT$kieP75cQL zW@$MYO0SEAL7t^G@sV#U1QRNR8rbMYU>Tl7MwmeEI)~~xCg=*1I}E8}Zs0+12SF;B zGsj@|LCj%^*>U`hayQ2@|35P5^_@tL{@Un&b>vU+EBz1xgureHe8i88&-Y&)>;K02 zt5?CARhy0HzFJ#d%RcNz6BACgT&wCKNanew7>> d7K 4@NG9Go8phgY?-A3v}f c4b?sN>mcuC8zj?N^H zO(?X@UBi>5&;*r{pV$m_1U-$19WoQAmbYAXaF+XHCk9)V`xAq^TJFGpEO(%* 4Td?JoTB4WF zRnywk?0ZvcwSu7;?`c(4?6|hFx~!X(TD5_8tM%Hul| 7D mf2U=mX|Zon|KeVX7O;_kHwTTG7ri8XLf1{ zV&S!E>(-KLTBuoWt=HBpY+JQfv~{b}TzVce%!4!64 *SCwiyiaqz zS%EqV9OYWg+|eg!U@A>3)k<^yyk5um;jf%B{`Ir3&&&DOPG1bKUpqZ_@wB;;tYS}($MY_!??X)URG6)_fg8i`KT+Oo0T1~yDadWa|>p;M~Q)*wCg^d(}sR$O;=4?dTzz cGY3BXS#jUwa8H^=xN<0KYwzZnQJ?59KzHaXH*-J0YdEVURHy7Ls z*RLID)X7~NOK#cEGQLd#N$({p)xH293&lV1u?k!(SIkaQ9VFTZo8vtIeG8e(Hm3fr z%_YD1S1D4wFtTl7fFvFc!@$xXL&jGKhR;Rq4Ivo!xab=BNPUZ$b!A;f8EeShwXx)v z|9*6>Q4}Z(4Qme?_!^Q+5?O*KwFff!5Z3VmAG*XT7~!soUt}(a%Utq{fH&$I6hyVK zmO>ODG8Q?dfft~Mff5FaBSYjs3#68E76u4Uc>uf@O4;bq)!kRd2KOP!r4d#Q0UboQ zDd=ECzKaZYR0@kcR|cYcVrj|x7c!Q+G#1SFzleXq-cbVRD$2h|ao0rw!klkksLYHA zEo8hQ={iX;4P*%DlRCkQtS3?x3Li@FB`)3?&Ook&W`MoveuR0S9_0T@q2!^bu;vNN zFn&D}50I7*B|9EK-9e(*JPMJxs>E7CWGovin0LKozr`(uIiJ3$PeHOl0%=SK5qt^! z`A}oAF)|V{0!h~rIoHrE>*kyp@_zBYvr6F%)Pku`>9J4A`|`#4DS=X9paUPKkr4&R zKtPHlEG0_0kC-56AeLGmhAgG${FE^7!kZQ70s_+INCq<6si==;W_$^BnL`+j$6eF} zh+M@I>QpwOUJt21+mUu%WG9KAvIIU#97AYIXe@_G21ZGsq&Uh%dzb>2IzxrJl-|3P ze8%-EA_fXf1yQPy@QxHBPmM4$^tw@X1ixvlX2=*-Y0$HfpYmYK!(jf8m}HhF$fVbS zR60};b;DE5xwQGb>$+J*Eo7=gPoUf{QVe{fwTq}_tg!nb6dqz<2h2-gI9+K+@@&nN zql{}BcTcKxWL~c|Yb&Z*iPiG*dO zF&hd5&4zlL4ar 3$0m(k;e=6jMN13L=3hH{r?3?ehx7KCxvW01@ Pw&lyP-ENMxcvfwKY&fwiEB5nQ4))?Gt($WRWAvm$eB?fjB1EP4e$1Qqk3wd)9m znUF$=R~RBu1o|J2<8ipXZZ0BsD;TgWrUJK|hMpdWo;+jw>T3ngY{Z2QP4OZXpwzF> z5VnKp6v&p8Ype|g%JWLi!jYl$%&y2hVT+jH=2}r0V8UGCXIesB!J*|&gdiPMNQ>MA zaXMN;V(1fJF2wv_e*AFsaK>lk)OLnl+`YGwqiqYF6#)gRSU~mAaTJ)95Gz3{jN#R4 zAskOYgsRN-T**!jU};(AY1?8^Z$FL_j=rO ^LB3d=*g!qm9p zcIrncJ`$ux)egc_s5|e4fk09EK$Lm(30&$`dh};eAbc80t|n7 J9L+;K`BX&boIvGm-r N2p-~y~Q|^SSAuExK!$1h0+Xrr&w~VZDHzI7^6UEfGUiM zA#Ec>uc!peKtb$;P+1K$6Q!=g7?7RxZYO!xc1723K 24y@2u6UWsVOXx5w~$< zLcLw+%qYk8<4|!#Yg4asxP28TN8EPlRWSemQYJVqAnhAT0Zk&5o4^RfAYkQV8YH!o zhN%K^o23Qp&^s$jh*LlzPCfT5PM)}}6-k{rs2c5gI)xTJ6rqKZh*;6m2iKyJdMLCf zy;4gekfroat~hz(HeRkZ3dbOX #pKeW$9Ot zltRnQy)83ip1Z}_BERFUqJ?G$5l$hBMB6C{eN%-V!Pq`3(55bT1!DRUT3PB@5ZTHB z^ej2rwlEqF!%wIo#)D$S8vMRO*)-^8I5w7oMC_oRG-&=ZJGNvf2Vf{U&UWGU>T<2F z3#LIxE{t6zQ3W_LF$pSiZG}K*J3tAoFpVNaI+faCLEHolLA?$^dCK;S1%~2l2(L2C zfs~8-dO{%05KGQr;dBh0&5$K3DK%p&iCyV^4wPqX*HDG2Zgjni7#6UzD8t8H8+jez z_!%njDZxApL^_F`G(zuEYL7)?{{MqyHN9I+j=QxG#Zu70Bw-R`