From 281f3c1615249e4a4108d4b81127c5bb737496e3 Mon Sep 17 00:00:00 2001 From: lesetong Date: Wed, 22 Jul 2026 23:35:04 +0800 Subject: [PATCH] Initial release --- .gitignore | 3 + LICENSE | 21 + README.md | 126 ++ index.ts | 48 + media/screenshot.png | Bin 0 -> 207153 bytes package-lock.json | 3343 ++++++++++++++++++++++++++++++++++++++++++ package.json | 66 + src/herdr.ts | 92 ++ src/state.ts | 343 +++++ src/tools.ts | 259 ++++ src/types.ts | 57 + src/ui.ts | 174 +++ src/widget.ts | 25 + tests/state.test.ts | 178 +++ tests/tools.test.ts | 75 + tests/ui.test.ts | 178 +++ tsconfig.json | 13 + 17 files changed, 5001 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 index.ts create mode 100644 media/screenshot.png create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/herdr.ts create mode 100644 src/state.ts create mode 100644 src/tools.ts create mode 100644 src/types.ts create mode 100644 src/ui.ts create mode 100644 src/widget.ts create mode 100644 tests/state.test.ts create mode 100644 tests/tools.test.ts create mode 100644 tests/ui.test.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a1127ae --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +*.tgz +.DS_Store diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c38d2a0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 lesetong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef41c43 --- /dev/null +++ b/README.md @@ -0,0 +1,126 @@ +# pi-todo-herdr + +Hierarchical, session-local task tracking for [Pi](https://pi.dev), with atomic batch tools, a live task-tree widget, and optional [Herdr](https://herdr.dev) sidebar integration. + +![pi-todo-herdr task tree and Herdr sidebar](https://github.com/leset0ng/pi-todo-herdr/raw/main/media/screenshot.png) + +## Features + +- Five focused tools: `add_task`, `update_task`, `rm_task`, `list_task`, and `get_task` +- Parent/child task trees with generated, stable integer IDs +- Atomic batch mutations: every requested change succeeds or none of it is applied +- Four states: `pending`, `in-progress`, `blocked`, and `done` +- Session-branch persistence across reload, resume, fork, and tree navigation +- Compact Pi widget with hierarchy, status colors, and an adaptive progress bar +- Optional Herdr metadata showing the current task in the agent sidebar + +## Requirements + +- Pi 0.81 or newer +- Node.js 20 or newer +- Herdr is optional; all task tools and the Pi widget work without it + +## Install + +Install the latest version from npm: + +```bash +pi install npm:pi-todo-herdr +``` + +Then start Pi. If Pi is already running, use `/reload` to load the extension. + +To try the package for one run without installing it: + +```bash +pi -e npm:pi-todo-herdr +``` + +Update or remove it with Pi's package commands: + +```bash +pi update npm:pi-todo-herdr +pi remove npm:pi-todo-herdr +``` + +## Usage + +For complex work, Pi can create and maintain the task tree automatically. The extension adds one short prompt guideline encouraging task tracking for multi-step work without forcing it for trivial requests. + +| Tool | Parameters | Behavior | +| --- | --- | --- | +| `add_task` | `{ tasks: [...] }` | Atomically adds multiple tasks. Nested `children` create descendants. | +| `update_task` | `{ tasks: [...] }` | Atomically patches multiple tasks. `parentId: null` moves to the root; `position` is a zero-based sibling index. | +| `rm_task` | `{ ids: [...] }` | Removes multiple tasks. Removing a parent cascades through its descendants. | +| `list_task` | `{}` | Returns the full tree as compact `id/status/name` lines. | +| `get_task` | `{ ids: [...] }` | Returns complete task details, including parent and child IDs. | + +Example add call: + +```json +{ + "tasks": [ + { + "name": "Implement authentication", + "description": "Add session validation and route protection.", + "status": "in-progress", + "children": [ + { + "name": "Add auth middleware", + "description": "Validate the session before protected handlers run." + } + ] + } + ] +} +``` + +Task IDs are generated by the extension and never reused within a session branch. Multiple tasks may be `in-progress`. A parent can be marked `done` only when all of its descendants are also `done`. + +## Pi Widget + +The widget appears above Pi's editor while tasks exist. Run `/tasks` to hide or show it for the current Pi runtime. + +```text + Tasks 2/6 · !1 ━━━━━──────── + ◉ 1. Build auth + ├─ ! 3. Resolve token issue + └─ ○ 4. Add middleware + ✓ 2. Define schema +``` + +Tool calls remain compact in the conversation. Expand a tool result with Pi's normal tool-output shortcut to inspect affected tasks or full descriptions. + +## Herdr Integration + +When Pi runs inside Herdr, the extension reports the most specific `in-progress` task as a `task` pane metadata token. If nothing is in progress, it falls back to a blocked task. Parallel current tasks are compressed as `#7 Implement auth +2`. + +Add `$task` to the Herdr agent sidebar rows in `~/.config/herdr/config.toml`: + +```toml +[ui.sidebar.agents] +rows = [["state_icon", "workspace", "tab"], ["agent", "$ask"], ["$task"]] +``` + +Apply the change to a running Herdr server: + +```bash +herdr server reload-config +``` + +Metadata failures never block task operations. The extension does not change Herdr's agent lifecycle or notification state. + +## Development + +```bash +npm install +npm run typecheck +npm test +npm pack --dry-run +``` + +The package has no third-party runtime dependencies. Pi's runtime packages are declared as peers and supplied by Pi. + +## License + +MIT diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..bf4ce65 --- /dev/null +++ b/index.ts @@ -0,0 +1,48 @@ +import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; +import { clearCurrentTask, reportCurrentTask } from "./src/herdr.ts"; +import { TaskState } from "./src/state.ts"; +import { registerTaskTools } from "./src/tools.ts"; +import { clearTaskWidget, updateTaskWidget } from "./src/widget.ts"; + +export default function piTodoHerdr(pi: ExtensionAPI): void { + const state = new TaskState(); + let widgetVisible = true; + + const refresh = (ctx: ExtensionContext) => { + updateTaskWidget(state, ctx, widgetVisible); + void reportCurrentTask(state.list()); + }; + + const restore = (ctx: ExtensionContext) => { + state.loadFromSession(ctx); + refresh(ctx); + }; + + pi.on("session_start", async (_event, ctx) => restore(ctx)); + pi.on("session_tree", async (_event, ctx) => restore(ctx)); + pi.on("session_shutdown", async (event) => { + if (event.reason === "quit") await clearCurrentTask(); + }); + + registerTaskTools(pi, state, refresh); + + pi.registerCommand("tasks", { + description: "Show or hide the task tree widget", + handler: async (_args, ctx) => { + if (state.list().length === 0) { + clearTaskWidget(ctx); + ctx.ui.notify("No tasks yet.", "info"); + return; + } + + widgetVisible = !widgetVisible; + if (widgetVisible) { + updateTaskWidget(state, ctx, true); + ctx.ui.notify("Task widget shown.", "info"); + } else { + clearTaskWidget(ctx); + ctx.ui.notify("Task widget hidden.", "info"); + } + }, + }); +} diff --git a/media/screenshot.png b/media/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..efedea0ce1048401d94f54e7be64f963cf134404 GIT binary patch literal 207153 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 Y>Ri#%@uJuoaN_VO;v-Q!}HL*@y_zEGtPyfw*bN z;>CMQRA0A5ODe?={`p$P50KrU4Ake}vL`~(=m-5SOjG+j?`cE$SAJY%TY(6_!mBOn z*{QD@u-JADY*(P@DI?yFf4HsB@ds|B{svJYM)dGK7YY-+F)B)i>Dm^_-@qHQiT`xS zUa~Qg^*d-N={k862jCS7+t z7(M-M2Pc4VysWTwa5sbjw&$3J=YiHAFZ<>90jK=mNcBoHg5Uw@s~{P+l#V$#wGQJK!UZf8rk`GXyBVj}Q2VHym_*`+o@Buutb}BLt1n z++ts2e2zeDyb`P|E^Tp-5BS?{`ujii+o$~fJko#o&HnG8kC=jWyI2~N=qHA1On?CQ zS$NOjU-2ePRn)^}>PZI@|L&IlzLHq@K$I80y)n=jb$QW%fx0P+?4FRWSGkLuLbbK1 zY!(<=YrG&*)%1vUF4!f3C&W;N3$}1fWc;tbjU?4}^S%5}zTQ&0QOmy{KaYYfRa~c4 zT!%JM2tGo)d!%NmaG~N*@L6M%z`ql|3e+>{OJnCel=+@^@SOd4G_pM{`Y;g!gfR?d z%vMOb)k3?`5(ZN&$~*-!#kkh&SG=umoovq{bUr&2rSNKrey{?2^6Eu8jeVfwX?O1>E!VGifyr^~yhw%N9h)MrpxBdG!vuEIbV@1%vkcJqlljri;lNy0?(+LOSmz;xR$K#Mh%TRRz=gd?MH-{>uu` zU99PS$ZyV~*cD_`soz7>K&@EOU(FK9>&2E~6qfd7jgBhQzvi_o2WyRwsn73sG%xGAw!XQtlS*ZEmRBViDHWxk>)L_d zyI=8Bjz1v9T|qM44h}C;WLhq&3=~fRROD5jhAYnCr#Cdrjl5=B{`=GyyrD_h_n}bt z^lU)%7>X+oApX;t{1rBh0rYbWAADSaP8#1mzeF_x85!QjON~hgcF@S2kQZ6a&?j~JH7D7*ok{HFFxWF3-&m@a`CaHK$l_T?_YR4}m+C}o!cga^NjE)(kEV@hLkLo5~G~5*c z=LNZ+%?~0Ej^H&TKmWl^uGpTeB}`+YstTxZPB7Md@^u&VJ_5LY-w+Nw!uZ^s_w`G8 zmg)B6L46qHf)G)=n|6ZDI394Zn^w79_pBZIK!FG1t<ZA=KzSbjWeqV0L$f5RFWHXs+unTd4OPf&Vww32W5vR1Ql5qI`wuz~=E*iJ zaNH-a?{)Td(wKPTO8$7)gvuY-yy{IsdH$oc%fj=E(=zwKSBPmv!9mJQJMkzQT-O~aF))>=RrllBNX**+|4Yjg3D};AN+EK-@ zoG&uxHzNlzy)!W27z&b(Y&;FVbOovVver`Hyz8dt19%`D}9jqdI$*=!l5kOn}9R*Q>5peC?ZXrW*_;z1@ z)f$k}FmCT1&w&@(o`lI#06N+!CbyDj=5pg3a}%Zz;S5Ij5gt4-XBCkW>$#@wjcX+l zP+Cb$zosh?C;XreC)G|-dzNT8!MM7-ndrd%i!)wrIMx zg=fv==QQVN-vV^yJ+PE&bn;|c(xbI1X}`a^FJE01p72!md6wO!QQ%kac(DszuOQD@ z$oX>I%9p*guk5m4BGyz4J^>`sjZa3hTFFTUFG)p6yjH18^cq-A<|fo^%d!2Mi}{x&22Tpf zlHMJr9%%C_=a2Y<+e1C}JEzB%2X+r962ov^c40skWhZ)$uTI63SR2KbyJlEprwQNb z_$HG;-qQwU)OG4Pe-qeZv6m*C67&qn=PZGXXm z5dwYa2Ykuv?T!T~uHjuk+H^l*&-Lto?4}rWXLTf!xuZGs!F{rJQ&V$u*9Gx27bsv7 zR-oKje>Z3FOU5b8naj4njxm$)Ee`K3#SulN2XS-S z_6xcRJNcF}x($4F0h!{_3Fc6$m%UxB$SF~Gu80D58=WqF8bJE#=N^#Jztz2k{`+J$ z;L}N*wSU%mP0}|>pNw+-GV2z;f9FL>bSP-5K}G(pbYptT=~k~dyaSoqvtSwu7s#UCIAiWMLm3Q*?2>sd$^9( zk3HoGq8q8QJw1MOO}bb36mLhJLPxc{MY=qj0|co4Xl>+erxylTw^@v?d@rOi-mbfW zbkcw!z<~Vz9d--dGKLPcLG_!XTiAE!5`aAhvpt;l)0JJ)?7}GX4vD;wuLyBm5Jsd4 zNvOg2zXFVOf(-CF(bl;Ly-Q2EM1M`K`||QV7R`9wV?60&OZf?PFk23BR6vQ)p4>LHg_iiXeEiiI!UsSrA`s;RR}|Z)D4~~u z-}(MTLEi^%?A0Pu7E3c(I9~}P4JqJksDcS0m$s#Y#4wQG&OklVur%fkV+S>$4%`?C znycfO#{DJG5tiiZ2(bx-KoSo9I)YH0a1_lTg{^?DHEDVX?nt-&Fy!7YqBq05K@;#L zsHjf#uC}vM;8t+pwhpi!DnYOzm##8CV z^FgNL z-ooD8j*=BoE?!~!bpWCGLY7+-3|HEx!T{xY#xIKVjIXOfw#3Ca4z5*f(Z`vv^<6H$+L8U==E!>M0HuWIK)JFGV~3|wAba` z%E)<3SLvPRXpm~%10j6PA7l>yTXoE~#!@9rAd>;xS9Pjy+YRUV$1CAFYJhUqKTc1EU7jVw62r0EIi_v) zjZ5z^5uOw0>pU{&cfP^=qtLp`5xclV>tX-#<~>sCmdPymL398HG~e$zl(}bp+cRW^ z?kwJmuAOhec8d7BBiL9aFmJ2g)R6M@JaeFnBXc#r@M)5=`z@w*i=gI`q6S|Xd|zd7 zR3~l)Ti$f-`%R$P_T2uD!%_@%S%*aPL|~o)#kXX~lo1ZltjyHF?1J+Q&~T(ktm~&E z@)gXUeDrI=`A=(%$zpSa=i?vf?RVJ^;p4{;1EW~kBYqml<}uV`+P*2|CC7E~K&HAE zY0E#)!50umJRa}CR8u$MzJVEcxccekFI$v8!ls}2uYf9X$QH7<&ic#y0!>DpvNC}#pZ4*{oUFU?{h0}# zHECY>%HwIpGNJt@72&V8f_6JpY%OsNv1w7m`T|QrhM+c=ugbhF>82G%y#kn{WgG~8 z{1g9xx3XV{^F5FPsi`>*ee&*)GyrOP-2Jl6(x6s!R8>#&{7qZMj8B3e28Oo5yU&BS zdhy0+-Ip4u%jRA=?8_~{ETw!cv#Wt_%;wYv(#G#?_O!pn>+TT?Tur|Oe}@s_4t_J} z(Dvr+#jB0`=tW~k4j3{*I44SmARsPF%$s{`BrK|N(NL4$K)0i%yfN)!`$VQTa_rdS z%5bh98brmOBO&|-lTY2fAG+hE*U=dnA(50Ce89+%Xu&Kvpr~=$i*gZ{*tnEXQ2eG} z%Zxb=g8}I~K_Fv7v%5pdQyt{j0sbdJ^85iwNQM1bh5aB3zPp-vvK#hOmD_oc>13?loP}bi-ny?u~_vQ_U5!o406tJB zIf10`b>0y<%|EZXj$L&Uq@Sb8(eWyWh;%*U6k(O3i1Zdj;gTKDqsm>&%88C+s=Um6 zT)HQ(gtPp^M0{)+4#_f)oNCy8&7c{IQSX?Ixe*a<4NV1gE@-)5xei*)$gjJG5B|t{ zq$DYm{X_LYWGLWiUQTlGBlaSnN+^@NtRnhorK#>40Gh%83U%ddB3ro8BB3wO6DqOFP>F6 zWHmf2kr4sy6B-HWhRXRfE||FU$E-I%1I{H~bqwDY#8-tpBPyv{m*~4eCy1|sbjdqFYeaZu6k>89zPg9le?lSqEB zLhj zus1OVCNd7W+8+l0s1C<$u{{`xi?BK19yaCg z#{-@t4p8fdcvZXT{-+l!>0R#1d%?9&vy%4bmyLqB>?zdui-G*Xww8(BF#{)uQN;23GL7P=CzzZA zm0Q3!aLQXAp@Cuz3Rgzg+O3wrmtE#%eD0$d{*((deY_{ISf*osqW(~pCW-i+?$WKV zP!EF~G8~8|cH}thL5mg90m{Wdcx5`Un2=YAtKRYa1S+#9CgH{ZXW(JKt{Y|uol{A4 zdc^4uq8*r{%D9~NhnM90Ie+&cTHq{a8e+T;$uAd#yHjsLhmJ07$pLKjlkCUIt9lA^ zIv|<^13P$xtUoNA4Rp`nc4o$>`ej6=v8Qm zU6jL1*RXgp@n|ai+csyJHny+=T>mS&+FSoA_AHZlAaP-Ycg5yG*^FN}3)z6|#!h|?+v>ufXN+z;mu zM3KO~=qZ0pl6{Dy<&(+XCn0m7^c>Qma(v1D(Us4xUcHLRi^R&nKVx7ETruvHv)F$8 z6F*{j)YE)JX@$Q0p28nuJtSY~EvUwq(U3*!TQD0d;Ha~IXS*d3o69*2N!ByJQ~TLw z2rXX=4^6ktfNj!XKIiKFVb}g*VuI`nNtm0n@0Pd|K$h{M&Oq@T;0-y+ahuB4?WBKz z;p%qJar^n{q?(QaSR70{-wXf?HrDPdOnWMOwLcl(N@&UK^ACj$S_I5Gyl?01tw)V=##y<$})g555 zUBSCEkX1}6j}Q->O-+UK0r1yOIK`>8U%W=B!kCR{E(}2@%M#iW8;WKXTP}VC<>q_} zAy{H}zm|-yb%}!qhFW)`x%5Fq0}%)6sizw%38;wzDaT6Uj8m*-_ItKjTP3<5=zCxU zfqR3H&#AXAZN83oTmi_4S}{hZ@kH-`!Gs$@H+VMU6N> zT`;^HFqCmPpOozTA*IO(3kocc(>OjwSW5tvL9Gm!`YS7-k@-~-GsOVN^|YM{o|ICiioJSdB;vMa^V?Z z5`}XBX-f&=Uf~+gN}9HuAqwiOs;S1z{{+0oPsZ(9Lii7GTq0`Yf(YGKGrROoD?)*` zdSCEI4HqW1Jx+a@Mu%io0(Re6Ly4iSn&glULf;~W!ZV=rokk+Z+9igBGl-ZFl2Bd- zijM?W&s}pvymsbD6I!`go#M*hjyZ699&wv(3>4bF#u)Pc4GW3r7ANk1 za@qL&8acQ3y+Jum93|z=qJ{*ND%%Jp(;qI4jq+sPz_GPVR3p$d{qgjRa%;yZanBPHXg4lAZ3u;p31fM*&mzukAZx9Rl5x1|GN0c z!MFfV$#fY?XR?b0+ca^ce%jwA58^z@M8W7!(bty<+}s6JbtoSRhnhO zs7SWb0KJQ9VzJV#>6q;y{3lApcL^)6#-?eLc3Y41_HKUG+Y9P3 zHp-!4bVVZcp$5J|N<@A`_L3PAoxnvdTDN_>Mi_&Dijt%4%hhsm>1X}oyj;nsaO8X3 zuR)<8!*l!UMML?PWU&k8Wn+kHilf0%U`pcWSxdv9CFdXF3tLm%$Y=#abJLRQXzqW; zz4Ls3T#F6`fMszqjx*huAZsLJGBCXP$1GO+C5X^PZSJCxhi?FCS+3V#5clat_nXV6 zh5FUN)z7O&M;#3(&L%Q`G!dY@Ww2KvlIx*qwRTE*y{Kij?yyid8DbctbSavG6bYuo zKtpGXY0NH3Pp0*?i<&~q{I6ViZjv3`!bl{#Oh_!g`2zC296g?SaA{4Lcf zPoYXvOk`}TCL}4)xJg2h7Lh-Th}7tJ30~n+Ovft}GRiGn+{d*rQS@G_F6A{;pbjH-u#tBiiudwTX{h_Poxmh9*#2m8sqc32%XW4iCzekCC@d*5j-Nfda7uAF}sG!H!LVS+2_yfjE=%Hn`s6Plk!xkEr z0%NsHj8wFmNRy!YTtoJqgL|I9sKwb5LOp{0{Yfd6RhttY;AcnW-Zc7qhM$g`v$|K2bMpnWa#N{wDmoN7pitvrph zt3yV~qidX;za5HtcTJHD8dlM(V6D2hs2_xS2gscoFBOL8e?_xtGXWMlM4-ao-Vi?~ zi8kSFZe94?;7B%lclV)k+&^&@bTCBzO)^=6juo&4h9xxw9NrQiJ%o%dag>53lK%v% zm?I$ib8~_;&Vz_N4w-w^6%ah53dhv-h|4;_!5@~pYIxqHEM*TNneq_fI>(zbnH@Z{ zd8eV3;QBHxgF>MZvkvh4FOR71{>AR`lZC$9F)p|5e4r&*H(A)f=k-b_YnQ-2UuNAQ zJGcWvR6p_QP|v;>iOj%?N*zR>RI(BOODNsH`9}7MHgrrf=_Z9tS$Qbqg(yWsp~gq8 z$tQ9T*LyJ@&@K=kPU6{a((l4UYh0*8i_|PdWB#OXLVaPEtm6VQv$bi@Xci36xl3_cX%4D!@JbW=w0 z?S-`4-Q6>>wL1@DqGU{D!lN}q)}ePr$Y9=dt=3WnHJuvLkp}2uZxCo%G+1L`ije)1 z3w3DS4=@m0(|1 z4vlOYkmeyNM+&r+Lo~ zY|8_%Nz=xbPxD;OSskzNRp|*-)MPrzS|WE)I6;;Gv=c-fmZJ!SF-Ki#e($N`%)O~* z0Qx}Q^=BtfurT&aY4Z7=#4K@?(L0&zQ1T&is$zSJTakbmWF@z-bM zG^11f8pHuLM~j|0LVN72W1oj|m@ZW5qVp3Mbc|_}Gt$zIKVTmtg-`gHs$gG&n)Xd> zYf2&nM^^tYVS71(rjJCJ`&2A*OZaWZ1_j4*Q#i-eDhtztn5o#mB<2?l86(6)xvB)D z56O-*w~!pJz~d|gPjfKO*F<=l;zx`B&ruDPN{_Zp`^;8wXyUKCZG9xum+TP?2HQMjnAKh(g9 z?73pfS3goNr0W+`AP4R;{hPm%X-VvyBA`1KF^or-b_Kgjbj#EoiuKC8;d;9hf# z`1(2Le)s`(K*$8ejTr(XJEvJyl`@*ptfHU2Vn}%b+y`cc^U|d>xmny3da1#Rk@4De zGZ%05_@Mp6#!l!6&(irPN$e_jh!UkwucfV|=|GXl$T2QVV1cYMwL$Se5PF{4T}T9e#**50lnU&4`0H!&56~KY1V%u6rTK@O}HS#{z6ax zVdqDW+PV`-)RyBsSR%H$5Si|AFx_OPJfYeo5@cL zEO9f16d;5cWc;|T!+{k&Rk6?C^YJzK^AYo1fxloZn9xzf|vMY3Jn2-je_>n|YmBQ>94n_)J85Fx5XEt$lIWS$Ih z{t?K7y(Q_@+-`{pQSj=|b9ltd>f2(X za5)%9;l62!Z5{>*=`ejUJCZQmpC9*nfAg1Tl(FouRM##<=I z@}EfY>J7UqL2wnA&e~_eKT_5GV61B&#C2^;OlRkso>x9F#wzRDU99}}e6MDx_e zx8$&)y2`_#n6v(B2U*fan+jv0X8>uN855wOWbI;_gv{rT$R1F!pURG6b)vD z|3aga$#$MdOfzWo-~`qQW-FI=D5UuM+g}BfRIC`W|4XCBot67KeAn!$5>nw zy|8l zirY|dmTARJ`&~wsADS?ve7{R7KQCH2nc^M%GG!iPyCs}+DTKQ|pIe(s!H7OT`e2}i zY4}>`^E@5G<6>(+LyDCYQv9-z9hph|odz@9v!LuIVV$OJ?7u-uSE5(ZA1Pwa>R=Lr zAW@dy>MaaLwR_@TMU9I+E9~00M7`<~4Xz>9&2YIj=qW?Jl7V>$hsiHH|k;VohBLl&^jdU*5L$?sI4Aa zzIdiYLgH`YRCNPWnFqVgpD_{b9|rRWaYa3OW89|`jY)Kg>e@}h;0B_7DrO;{oz=oK zS2{uQDEU*0BM&CRog~sY7WEdj7O6%p9~Fk?M7K`F1cuowX!Jj2MLJw+8!%l2dI`Y0 zH`b&4avW*TBEC)OL`Y{s$h3a_anb9;iD43;j4Lqq&Nc0$uhT2}0XyLX3b6{`>sm4W z`Q&O^VP3CCk$IlYd-0#(5?AMi;Blv$evoyYboL*%f8E?nXhy6{41dB_G|7OLenrv? z+^3G}!Tq3N7U znSfzunfnWtK&>vkRbO^vw$sJ9ZJ7?Poq@0PB}Wg~V5o(FG#W>x*6!CUO;U{Im_n_6 zb1d|eVkux>Lt#}KaHuQ*bu~%{5#~@Z!DTju*rE9cQhS3K{dvrEv-Lj9;+Q&Zzx;_D zGjW{D51_a@QPNA&PAevTb$>fFPb*M8oF652ahps==aA+3Y#o%#aesy~%)0V7uA!tC zT?Pk)1b*9(BWU$|8ua}~lK~!U-Z8=c8|fyXvFG`i=!)^AC6Ex0is6wrtguu+__f;Q z-ek#ThCV(U0~c5LL2h_7AUe zHW8R8vfQbpQ;TxyYm(l7^%6qL`R5<&;Wtwi*Z#JGGzifO} z4z;G`!YEaVm7w^Uxw!F6 z)!U-iF(N0Ne{}?jMYfH>Y=C3-(L&o*R{8e%&Yw?y&-N^nFR=H(70A6>NbcQP40a`- zba5-raeSWW6=K4WlH~gIX24v{gpxQu>jL9-J#*VDM*fyp*x!*NmzdC2H-T@a%B<7J zAPF+JLLo+f)R;zjWo5L)zYYlogi_xIFKI;Wlw+HLeWwWB(N&^1!yAVg>N`!39*t7@ zj_ziDp?^Enjov6YRh+E>J|Ptgj|e{WI4i-$Sd;YsE#x_A#d zqe#}iNe5FoYpc!wpXiR%TCA4it*z0RX3*=Xoh%~_NOPgA6IoOS$;Dv#4kPZz{U*$? zxm?0cb2VS|VA#44>Z1LHzEze3nokb z4Ood> zhA?^;F-c)^)9a%oL9a3NF>QOZH`kbQSoZf2AJ8$^)$!J72=g=U-y|FbFwGW%2SX~5 zu)d5ZLz|FkHf4r&KnQ}VD=4>AgJU#*v?V!f$1P50y?B`6LPAYeg4}Px91K4FWVV4@ z8kZ3LVh0C?02|9)&n|Z~Rmk8C%z=}N-u%vYz(D>PB9c|`AFv!P=x5k7fP3cwzYVkjCKEV-X9(|cj-$iXfQ@E7^64}T zxLHDODq~;^7kD`$Ar4nI0z?VaBIqQSygOK61| zxs8-`rK#!BqjqugZ|$$4eq-LTeY;N3RmJQ$&yIvNI1@BsRX|$yVobCctl=GXfCu)^ z-?^JzF8&J;1A~Z81vahM9m7IT-R)%k!Il1Ji1@i1UawnDrKFF*Hy|X%_o(%PE$Tb- zB)y$KFDzGZcvr8+64%Tj(m5fW%0`GK=Le`1ju}3+5W!0bLYI0ALr#w)+IxpWCI-S7 z3YeC`6ufD(H<0q7p8Ah%GhBIxR_>y^+vK^tR6CB}wMt7wDHb567quy63M^wswP3=%H-4-Wy^8j;H8##&@_+F5rD08;+uBi7 zYOUf>#feZyYOTiBA}E1qt)`5+1dC)8Ldf*pD|Vmmv(KK+`SD#>tt~@_H_!V#Yu)P}w(;DurTIFT%?)+= z)8vRVG_seI^q5TA^}=~8RF52^kE5;{&4BsrvPR7;dj|ZTlA46(4*#-8uO3K|50`q_ zAdf7%VGUEWXU$WDYc@24xCxWsJ0ykv!@g2bhfU>G`Vqj8*%l_fl)rxja@DA>n_&zH z|8IVjf}8)L_ay7kfB1ta;})tcPg0DJl-h;b(n07F(u)MAtjh*lO2p?@%eqA^#Fi0v zy*xJ;!~$U(JZOg^hyl7G@jv>O|C=y4;Ra&@ua>S={tA?d1afNQDIa76Gm8aT4Gr<^ zhfvM;imzp6Rs|I(CTJFVMc*4mm6_d6d>)#GAnC`4{sULb-z_e&E{8nU%|&Y@k2$cm zYE+8K&In!gfB=m?rN{*g!)xpXEiu;pTJU53vV@3W@PJt5+ErWHjte8-AWhXHu&5@X zzn)1s55!8zXhxFrWKd}BksQDc#tvYOV*Rt%?L9+Dw1zpv7*fUQ&!x<7;S@*awErwH z4KTZ(v5hr`T+f(9BNoPwgHe?2MpQ&&+YR`7PIU(FSg4*Wm?P4+{ra+fsvh+$jsA^TQP z0*h<_5x&~clm2)oqPjmEKW|kx5xPYVPaZE9i%(W;gu72Oyyq=GX+=osJ5QYMsE*iV zr<0Z7-rw0(^W`g~>t_yTa(6Z}I~=5K?%WbABuv%CTqG@Th8#BF{i9RhcnaINaK51J{Lv)P;UXwrg z9M&L>R+utUJdHE-xpFxz#Q+sTV&#I08V%@T{QLF@z$05C8Uw6ic6=`6zH2!L(Uju0 zb~m$Qn!o09#0x0$?A{!aXM&cO?7e_VrS|-C#b_iI} zSuHw&AH`cCL`<06$-tx^G0Ndh+c5wJ8}MjdVxDW#gqsI&UhbFP35l|ZH4~(kFk_j{ zGEt;9VZ4AZssG!TJa3hm_!cL@X=$%HMV2a381!J9toMKO?+iXIe*Vp)H$AzxksMF} zbjHFPZlZ>GgfLf|1lPJhz5o@#B#MY;_&MQsB9l`nc|b`a>5Cc_UGww_WckR4pwz+F zw`hn4)ODx5maixhLkh0Qx)A`|Rw{3Tt%;;O__;Fx&Xev|kG_9K%Q z*nf$;Am!5KHXpd7UG+MR&om2bR*zzHu>Im6_$^Lyyj~^vGkIZPnz#bVn>{&F&_3p& zxaBTF(rc&)T@0H8?F6p5-Oeg!_(Nuw4~2IF1JUlI147HRQ;Lw?HOz8?Y63o4OA_N= zQ1`dCp}jh4R7@1UVLa8J%v0G9fqhwN!3rH1z!{mN^WFk6B5ZPRKo^Z8r1T&_>x?|) z^a9ZbM=JpHUg#R(DRaG@533`0aoSg~i@H_><}PRzBwiuoIvo!b&Ky)5|B7+76{H0j z#yvIc&wh4r#8oKm6g^5LWz$=O_h5qVlWsT=Rg@6z;P|rHv78v%ztR{B`FC&&gIx%> zEZMku|!O)BfGg)yw}7UdU-*@L+YA14&@X&pJ32_XuoWLaD?K zt8)GXxPM!U={>tYzny2X6%0`JB`d{Ope_T}-*+aeB{h0BfQ9sO%K-b?7usS#An+~d za{K-@2CRLBh{K^bw{bEqDaqxnuruBd#J1-Wpn&Pl?|msYjb!$zJT(i8BTM0vouZOp z0LV{(L`}EqpiW&-;KqL6iJ}ii-INWgS!mB%jgT7zq0l=e-7@&9>*ckBlk1;94#Yd%_4}0= zdIGLQh>o~#GvjrorO2@;w?J-yJg?_`-lN2VX(_#%Q!1~Bsyo%vHuCo7#2;Bf9`oY3 zld0LiSrT}PbG@X0*>R3&fpV<$4=|su_<$^XG4LHhru>v8a<2VVx@@Zcf_VOeN5}Q_ zOCYwRP{`H#Gj*PVDw(+>JwoDW8Z9(j619X1UV5_?Li3?=)1v@&Hm7gq^=Ud@ONz(y`!Yke;;P>N% zJVGsm10TSczi;nNFSjxQqHu0x1u|X{9R+oy)c&6qu$Inzu(C8{6znn>36w`eMaUDK zmZoOEa%zQl0h>cKSQyZ)&G~=~i6i}w!6^xE2^pX*)BJys?}tB+*_~XEvb(DX?&N6K)tuAjr116<+Z6ov*T zC|r)Rg+!3UfX@j=W^NVW4lG5dKO_vX0DRfqFD-6hOueW<>J;}yeEys7Ah&ozB3L~6 zbIJDjeo^BzoPjHoJQkn2hg+UqigeqV06{be4;S>sio`3FFV`e5X^Hkw6+?d{u)j7R z&9u%?q}0zdci8dm_rR)5)TiY%Z}c~x#!-RV^RU?T1-bOajY|D&u)^h+8n8Qcxn__+ z%V2#WIP<^#4Y0Z_DqYU=ByCb!sd zUaYT}7g`P}=dYLjP<+eE5}6;-kI(Rm>`(Y$NV|#CI%PgKALBBQ7MaIs+h_R^$-uQj znk&4b*g8Wc$FjcBm?n*}{jG1D^<7!Bb0`UI>(*d(z{ZT)rb`_4;~a83hi+AWJKeah zXLeVAt1c){@0;(wTNB3VUXNTou+=pGnYCI4FTh#IPwEAf%Qeb88BFcjqhyjvG7sZ@@kBN3mE%CcvA|2|ANlPX z!NT;0K>;clx~!G5zXJZ1RflUi1HH zxi(02s|6#bQG38!l~FMhE(qU0bVLg%GY>!?4~02k*&}dz6Si&}I8yxmSIHYaVsXR9 z&;Y*I-qanC&aJ9}zvd&y{9-DX;b_Hp=?=@mDiUeXI6qA-Ix{rdj_BX|yTZIe_{xq) zSlA2@Z9~)u3Y8;XBypxW>&ExWW^9rlVArzm)p7!Cwj-ZM$5+lGLZw8B^ubcfxW8UD zXfRqEw??JumL8$3wrgMsX3Ai)-KwP9uvPNXL)ix)JxNVzm9>a z;*-}wJWACcO0Si9@>`G52z_I~?lM4x^T0-)%Qwq~y(M0GcST4n#F$|jG3)y`9g#*9 zp)x#7!gz7l|K5riVSlE&DO4C8Yl4EsYKu%69_Zr>FF7`-VMJU+)~Q$oG(Q0e>y8x* zgLUQjsT9)=G5^)(8y-OkI5c7~rTjdC)(<&%$WOK$`9IhahZ#RoP73AExp1(TEaw08lVaxm{_io&m!$+L`@X_bLj<-Dj zzr4_(BZ1s~E?<)~u69Yl&N!G0I%6bC04+j0-Xl_p31d-jc2;%78PJOdvU=9J2fSR8 zfZfOMMpgoGvZH!q9c7P%S0zf2CQ4uNVqef+!7;-E%Pp^xr!j8rnz%j)GaoSmEa zN!y9?bB+aXvQe1pNI(tpKS`bgZT$bl+Zdj@VH}eTaWr`oKYvF&nG`|H4%$*TKQ5V> zr@0a)3Q8Bn*q0JL3Bm^bt^4*c2}ZSpti6|8(kotV)80|1y~!O=9TE!i7#RKj39mM1 zN}^lF(Vfggk+ihy@<_~;-D`QzpFV`WN{l; zejKUhi1K(bLfF2f?TqoEPT*uU#vrDRJ_zHi{ON&L^OI?Jq`&2XU#Dm9d_Gy+<$@^$ zf^_)Ko3sP%-n_h{axt@P$ge*h7nv(LkbzRcNOhnf9w~TG^mgB7Q*0g|PKCk%!0W9m z8e6t;*Ge$uYml}MZET&TPX|XpcZeKGC}Zphc{PlOh*q@lBUN9>%XSI{A~TcTBx#@X z`zI+As14VnpEYKNj!}pnd;PBVS=NWJ^Z-c;asOUG?DjzT0EtO6fP~@sjI<)a%4kY< zl;GPZpd}lP7=&!a8-NFQrRvjnL#>HUjREN!7y~ha3c5v$V(OlaBpS`j=XW3)x9tNN zq6vk|Nl0%PSW+Qc%JP7XCCpYkBjOS|7`@5L`AzwaLCA6hFgJ<(i|)&RP&Oxu^lyU7 zL;OT2bP^N$lT!O2ijVo_!g%{XE1N-g8c&vq{%6GqIE`u#WXfY;M`(p7%LRE5Y2FHP zBeu`5LU6(mS$$Q8nNvnHTwb?s8;pe6n;J+<<1A@#Y$nAXa!{qZ=u||Jl|4Gn?N~h1 z?j;3C*C4jevfG|DUDuGn?t64v385n?>^ts~G~TukM-?3mNCYQ6HQnp5V(-`6E0i|p zOL-@G3N%u+M_-$bz%G9hWfX#oIR;hu!9AWH*EL{}LOj@W9}H9`Nj>{@EKq~hbQp)h zdaBHE*W$%nhb2U0w=l^=l&^L1Ccaa@-j`mS2fq1F^KX`gQ9RQB?dfS`9i_GpXdzNA zgCHFkA|=XuhDxsi-7pV^;PXGTk+yvGAO7I~-ETU_1TBaLhTBC^v-_A3t9XI`N*RVg z2d?MLU|^OZ1aCSy%$OaqsE^5Svc1||8jvU3Pb|F$KuSU(JKEnW^H6~HULItg`yX0~ zi^Z^4I005n4Ac_g!oG!}`R0k-i{MSELw5BP@OoiY8hW99AeWM7tTi2Z zp|BrTtV)ge{Fj;_{)^ZG;k+XVmmfAP;^NaC6{2!*P;yKyV$+*~ULI_RH)xAFDnBUg zj|wUfKcrrW(Sy*wm2!_@0*veqtHgVDmp}Lt&wrhrxf@ASrqUGE594Ep(p( zK*A>&L52pDl4^TpjubvZ3xkaDKKou_Gw?Ex2!=7nO|RU$;0cIqIoTT6E)+rDYg;%f z#Z^Q1zGk%h*c$^;_^tLCvb}nX-OMxp4;I`%|5K}O`wmh^gKA(%^6-nmTRqrxonSOV z*yjCB>&QRd@tEAtFQriP8VNt?)`yvy9D+vhwPvJ8!K+T5*A1;b3J5}5prRG zRXVcdNIGS;;wN4k^Z@aBZv_}Kc^FhmlsKj0MG>(1M-0)c3SBnX^md!~kLTm>Yb5w8ku>ll{K{8I9Vzk|W zc<0!&Rt{8f=-w-+-pq>&I>J2m)1B9LC+9}qTL_%`3TLn=&JlbF`I7Ebfzd$5-jhJ~ zN|ehbAnTBMMO00e00zPT8@KYX2?w0f^b78ok~M!W$Bcn%b|;Uim~_KmSS|Fx3+=@z z@bi|t=+W?vfA)b|F6i@QKOZcV@eyT*9qy%208<1FtMx^GxYl?fSLttk0A*hf{Hn~Y zLcUOBNyHFyie-Fo1&AVcFm^L95Q~Mz!f-X}N*nr>YyDukxhlmt!0KymEkc*znKYiu zWv>;w{$h2l1Bb~VlLk(#X22{x!1&xz{X@3)XnpUmV#{)J*C?Nb=K9iN`1o7U7X5{_ z79of+h|DWjj{>EG-8I9jf1<6=tb_~sx?rmtM>)TPr~k!E?@Ekbk}kQM#7Mnyj^ z>3fno2NB3!sx>K6{gHsSAsoZ12#M4(i*+|CTvBGwe~_w)=NL}D@OKptAu_zEyHiw> zz%L5akUI*SgBLFU`ys1NpiU-zbUsDb#6cMldomm+zcp*-#@_e zWq_5lul)h-pnl4ap##=TtTxuA7$>prrkK>qxx<1OWot3Mc_{=9kR)iTHFkS|Yf^r) z-9p4fLbC=LX`|9OD9xFHAG6@QBNzq)55fS`d)|JT{)tv%D3;~gCP7|q3g3yrlh3{` z;j{+)Bh&UPez!Mloo&tI`=PHifZf0F0QMBQ9KrWhptna8KkIJmd@`7ZtHo*}y@9UD z=mj~DyB6vgZ(v*gP0zhT*jZ9jgEI+2ksv|3C`Puj0Hg|7Cs5P@NJ8Ti1(`%GLLeZR z5%g=m1shXBt(;d3Q)c1p&$}zwkJj0lk=0P0jbsdK{x_dz(*#y{>k{bWvRbBaG;HGH z!h?b2xcfXhCdS6L>-A`fGFFe@gOkA7?xnZD8Js;RVr~0S&-H_w4vuhV%W1w+_Z6Nw zSq`ZY^X*Z5eL_OiL)#>o>S5lTfA69`@Om?~*dRagh}^QH`9p9Rcl*jHL;}xioA(w? zUl_7)t)#@(p85$0b<3??y&J*;xg1y`fU^Q2&Y>8256FM*`#8P*4TiymKm_{DOIVus z8SRF77ywmb=VAi=h(!*FqlN@WFbH+GZno)<{=H4R=pG*Eyukz)aHHq9LkpTG^hAht z>~g3O3LBHT!I!Osrw~+q>bCYDsD}xWzkqw$CsuxMfmRG||+9=@A z#{2Ro&;09LW()VV5=-<6&?u*tA9V=i$;UD%+AU8z?2Koukq3=pj=tUZY?T~It{GY3 zaVU3+Xq`%WxpTq1c`i__7N3(SyQRHVBqw!J=)ys#kLq;cJBzoW zEV^jRIpv#T{s04c8qSl8p60M`N?Bxnd%%^>1w`0C>cA;NaLS`c{lXi#PUk8FsRv;Y z8`6rA>DTFBt%gPk?t!_duP6htz<(;h+W_g zQH?<6B2R1V!JJzPXiSB4x~J@{x~*k2n+cBYdp!1lGkgKX5h`T8Q-}+oLHSo(+9ug? z$HL3*=jD$}Z2XX~eRE!DPXTJst0|$Cv+Ua8=(oRmJba6wgk?0Pn_I-a7Bqp{X$&;a zCbz47DVKXrcQT_!1%`-XyLXg|zWO^O{%n2wJs>jF%!@3C_8!0V{tN1EwG8JzK(UKD&Zv zc?Z-uiuXaF3C5ME*&T*Z+zRf^Jyl^5=v)~z;IUasIagZfprFgKocoU+DyZwl01Qw( zrNs!Bx88S2^GC5e7CC@19pochvKwAExCk)zpXe}+wo(d*UphneK5H&q|Hsb922D+} z14glASM*B_sONQqDc!Lk);DCEgexxza|@decx-|Bw{);vMc<^soVRb#r_I+%l?}3~ z|DWJ|0ula#A1lB&rBGLkAHBOMCj1j@EZ@+m^`Pg@zUg9i&q*I+AI`WHPnxuWKAe{W{Ky7>K=s{zoE#?~4}$ zplT@3SpS1Fl6xy)%K+TjQ_ z>a(ON1JME5w+NS{1#79 zisf$u2Q2#l2mGzYe4ldn--SXXS}OnkGe_q$4E=qZy+G~5z*L;VKz~mpkS_!!9IQi2 z`l{3iD!98ol5BrG%ZO>~V5!bedjEqJ?5u-LkAz$_&_?}@)!mlLpH~I;7TOuU4bFZ( z=5Ia6l6^l?Q9`QSP6!C`kiQ$?BTo??!LT2>QAI!x&P|A4;6muG;~~iN)z3vT|3v>G zcvPSNI5)I-MHWMKJze$bi;4BkyaHKbZGOaY+sL$<=*24o!e-g+Y{ujFS=zc9pEqPT z|LDtzsPm4Pw)<$8%3Z2n@xnjvu1$V*XThY@^qe!cAc?>Ghd;ih{&atuydkxKUc!V4 zEdWNryo2e<6Hf;j$#s8^G7#^(2UGuU)@>NiaxcbmH19>V%cIAkk`)w!RQwS}5$jl` zm7-s-Xcp$$KhX9Hda=t`+Tgirby_Z0olDVeM9FFD=f(SN6p{roBx6}VO}}T;h5Anh z_tD?8M{%9{q$@{8i#Lvhm4^dO3LijL)wDhJ@7%>*#8=Dt;K$@(AS^P+bK0zj0QO7u7C?;{ zp6Aa7`_?S+0uAT)3)Jn{d^LAGkGBcd9O}3!mKrdQ*N2EN2ukMyA z%lR)3E>}}rH4J&uJ3oT$b{cY&YWk6U8p;6r5Tia{nNsll2F~i7rDV43drObI&*~K3 zQOsP_wZQ)vV27L(eJH=zP;l}--l|}$7Q(ZHiA*K}Ox*WA+m-j$V^>VEv@)Yg7mZ`k z;#?!$jvNXs(NuED`^{(|?B5e9c#p|OR< zJU$qFl-g&nGqz?U0UeM+A(bOETeB?kw75*Q3iEL#f51&tN z1VKTBxmdm=YhDH{;Yw4~f9uHi>Z;+=iGw`sQ&*0DkP?FMmshLKelWyy{&j3SwS=|} z>lXu{^-_#xkXP+oGbf^|CTcJPZL8(z-$g%I-g-ibwa8qs{-!z8Dni8EkN3}hg){X3 zYnH|Dm;U$H_t&>aWUU`|ymBUgwYdM-PrOZDOa4W$2Z;|I|C0H8&e4Cr9D;sG4(Ybs zt;%A6clX;44=n7u~+P{`~mezdyU>-4h*#Lqm(_Xny$Z_C42? zM#1Mn-)EK}gt1%Xm$tupWWDvHGjS+v#O%n0XU8fykw-G9Gz-cHXS3DGJqGF=Jf7W7 z&6CYk-`y^7@|9sW9Gu&|8Icr}ZUXYxZ@c{CJoAmqKD&J<{}6>;tFyySBs@q$2>%6D}C};h>%56n@~GoZ{*J+w`mXJp*!cV}Toa9IjeRm$&;d6uS_;-u5t=s#+;Ui#Zyl+0NKy>k6xQ1%pB!%g(iY2cW zn%gO#h|H|W=uf?Sy>mtcbMG&n|BTZLDrkh+CHMJ{kAdjdXpNt&3k!R&*fG)py4Stv zd40c08$`sMa)v8E>ZH$*$4`1iFJ3-(nEGB~_tub*?azOmWPKaYAG>|BZeC|yV?HSM^$91BW@XNA@9g2v zlN}fG-z9b+B*rgXfBzt!J;{zxegl7N%}8OZVCGVANL{ca`HRDXfL%yCeyUb z1M2IC1ZOwDnYyxzaV{yHg)_bYl={JF(nt+>vf_5k$oUJVn9DT;=V3a|5q#l=p^OKM4P0uc?na z>RQ-sOB3MfnwwO8!t(C9_C|oZ@#{M8%s!DVJ!v*7_0n$x1M!QX2wl1~T42cX3LHCK z;j#i@Zg#Z|?(irsIFlISvG~UdtX%7vLU)PnXL`rhQh&q8D;sW>{+xKrb$8bwk*Pr_ z7sbPbK7HEY`n+!koV5&|x;9bZ-ml$ibDuwTt<71>xdCSd6aMxqSCU0nJKxUie=IGO zQe0pa!8mKZCiaT%#*UAJ`47jqaK4T246bdeFMw%-m#WsAzgZD3eynIR`svi7M@L+e z+xfT=k@1xBV9s(j=N5cZmCcfzWj8mSsdToChyT9iPxLQ){7djAWxou;zXb2lf7!r# zJ^(iSbkQtx{$!4I4K1F|GT(Ly6*-xjfqmarzzwY;A#y(R<+0d|%*=gL;rt(r;ps3% zo@pE#u91wh_ERTQ?1?Xe5A4??M1k19t>7dA*`i!oq#*YN-N+BSfT3)t5rKsR&K;4D z`8;CL)DfRYteifV`}ykd;v+cZ@+aECjI#FGvqd9y4Llb_S=fd*n%{smynu0k$d2D$ zj%x(pU~f=*ZVW2S7vgXfPUn6+4vJxN4Q0@j zO$eFvX)~Jg?NY#}Y-)q3sBNneK~(vK!=Ttd%QdgJB?o zY{jO(%q$DtFmcdvTu{1cU*b>>-&tc2fzaC$(9|x@kVipcGL(2)NxML z{UTfHb^By-@#rkcjsvSwcYmGk`5-yJBq==EX)a`Gqb|%3JG{Pp-Z$xay=Sv#EEsh4vZHPf-hTs0J$1jx@$@_TUJlc8 zy?&hU`nBd|sX)yipV6W^X`%>qciSpKpZS&@BdUwp+$t81^PjpC| z&)c0~P~?8JNuzwKJB<@@(@{rhD_{bcIW?AwHq7hHX+Ch0KB1__lbeSPJAy-2BmNds5B%Xi4{<{mfS=`DY~QFF*b+;v(32ar7sFx8J+{I6N@; z&4Gfw)zgzxh_^?QCm0}AoFqpu2Shuba&k|$jVzhsSe#f;T0eR4o^s?Q5HZnK5~fR% zC`$u08{x{qn?A)43WJ4q?r+(g}1 zYTNZ(sMqEPqe5XIzB}MTD*L%w5?Y^@*NOa%XlWRcAgz~~E@(6I#=U!q80ddCAqtsA z-O`S#pEETJFAu2k6WGun1~Ib5QsdJUH5trpn0Ixr0Htl2H8K24)?dEZ8y+q89KM8M ztZ;0sL_0j$0>ml9F0ixYJ;s5y^G+r`Mm}*R znY3GITIbcQ4%_R*Zk~5wEldQuGM!-09P-gfyPYp;r3G6FCK?VTn}>Hr+Tn%IOw>zo3YgQ6YgL%7cO{1?f0|JWd@sG7bUpL(Erjr_Y#- zqsASim`E34M9C4_R}9_JZMfrCCQI7S2dz|n=OihkBR4u=epvfh25#RIZVK1R^^UwD zD05T`vE8k3Nos%cvjZ^0L`$`=vW>G!>W%wnP$8~IE4C<2ZF%Dz++*yAQH}6*PNh;D*i|aFF3X9k zs`)Ja3A@XkuftAYqT8*Ccv0^@nEpfza*=Ewxs=|%XoH86i!0UItDcoyzqR_k#9bF$ zGfJym0*XhaM7Z&Io9uDg z7EyyhAI2vwF-INhTWd4mPO1JNt6{feR%0Z~a{4OV%SRMt)+9Im?3JJB$!__W_778E z!47=r^x0QAJJANYe(ZGfw8X?Pf6X+gT=a5LxhlyXzUd5*WQ%JpRZ0ak~^Yh=jFA45vfnS(Vw0i^zXXOyCk9*rP|N8l(j z$|f>@Zx(`3gJ2IU*p}?LG*2-hZ$^l!EM(<(5o?(y>?VK{qdRUV%jJClh%aW(N96}7klw~uK8mDD(OTD?f8hc=$eYF$f50Uv}W=A`eq@5zQ z??aut*sJDCGVwlKUQoMCvzP2r;Qrb=3!4HfZn!lAh_Xd@JRN<@+GY3EM95rn<2pkm zjHZ_T&K%RIEDfhLKEJPWhlrA*-#aqJGGW`cS=my^-Gk!4-XC|PQ@|Mp}U zEOZ}Pmp|;!U6z6=8MqIdhpX$?Coo?ro8Sd~tz_Y*9jK^q7&L!yd4T2IFGyQz!=t<3KT=Bi+Ie!!*wo+>+m^yD|`<1M4M zI!N0mvCPOD(TObf#*n8v2VL&Y=f^DH+C_KlV!(JQnu_iNYd7G`nBvGC<>oelL1iwG zi3@I7uno=3gl$a085qw^q21MB@Lay?dZx2{k=^YxU0nnJdSaDtaaQf6PjTc3iPETd zSLDbidwS0FS%x)4$HP#U3m=Zm9J4a%Su=(ms`N*@_S53Ho-^Ne&H3@vHp^ApO9ip9 z9xoR#f^#tpzTMfsc+T~V_i!=u;*yev0*R8e14E(Wd4Jq+mxi6=_W(A!8?EzeRc)_Y z_b3cUIA&!h8Mue(_@FnJ_g3Z@$ocDYlm&k1Gw2M$9eipe#!OJy#i1!cv(SWR7`(@4 zU+KCsl#rI!M<7XarOkG+yFGp_ej@WK_5nI`a5#_LgWC*8;UU_~*|Ra;grG=-Vn@C^5H#mKq%xRA$5b1?v-@sZR%4~v zJmT@Gt=p>Lj(l|^kJs<7HA05ZP;k~d7N^@_R<4kt_rQ%yh>`woBFb$>6IC!NjerQ; zlT!{h;jEuTZT7LDvSiL6WEH#%gSUAY0s@Wmxj>OPTxlv#_xcSptx7w+5xt^cTXzJ_q+EMNx z|2oaOFECD9KE6D}zs-SpbSfkHrKfJY^6_j$yg+^Tl)y5P@dk%toBKmkeu2H~yw!!1 zP9YN&-uqE!axgvb!uZ$AniGh))!_==S$p1KrX^dnc%%?gCGA4YV@~P~BGXLf+jD_D znxp;oUk1eUtF`I7BDNQjS%?a9KE&YJJ@L^b2zor(Z53WkD%BpcgoZ2E7Qz~Hq}Ck( zdGJoP?fc;jaea|6hB9{nqS7frf>m~NK6rRDkwKU-WnXN*^B7<_Uh@ewzi1Rs!?n3 zI$%<^5;;R=S19pMG9nNfR7yR~qg|&B`No;~ zj3|QPYLloks-UU$=f?~}GoEg#cs2Rh>F0>VK97k@8OBDS5+_q`mRq32ewwgk5<|f& zYq$Vmp*ick*bT-qQ!I~eU&W+X2Ww3oA#cvKg~;0c702HlsW36*5ELYMJflor6Zf+AyFPI}cl~ROFZHJ{c3w z-19h97^;vkS<7d{48>?p+(a9s%TZ9ZJwG8dydQv#u~fgZKKYSw4F+xqbxS|oaBxkN z08eDljYEa()PAUeE$>_&Fb^y!_CDHEq^>JpbU92yo0l}8i5eVidu$HiQ@m1LZs%1k zyKP2zs3=#lKnN;e?NCWb=6Guj?MkJo$jSZrFxsp!8olFTKl?=(o><6#S+xg3gkypu zSFcc0^Bt-V20-k3QS^e?*qP+ebCi}!!>$@`vgTB7w$v{?$rE(M7lRa8K11`~vZA+i zp-Y?^k5+9&GND1C1^;kN0oi z?ArIMa>5dT1;r62TYI+Oc6EzK@tl6!rO~-`WTBBSNM~pL$FGXY5NtP7U(eu1l@;wD z&APiRzj@Y+3;v920)DB~sF@45$BRf>q@{1$ha9U(;5#~P7ZH{S4B>c|01ofp+wlfK z(UuH^INH@q@Y_kQKk&ci)QA+j-t83mP1(hRN7~)=PuHIg=!Kah*|fBYEidgT?3u4L z#5gXk2`87*-^8$=>2*l1Z){}lhH(*aRtoo3FXU)Xa!OVuzZ?K#F5`T95t<&Qkx8lE z3<5UTy=dv5dqux*IRPrqpFkQYNU6qZLn!MDrBdA<(%r*;hyYHNWK8_fzHh`fpxqc} zfXw5@xbpM_ftbO(vd6>_hbBmtWfeJM_9S&lU z>B9?bXPKl9A9Z4W+pG&YyZaUDZ_MPIQ$u8eL$9gVrT0NjtF$zU_0o4h9^Wo{x}}x# zY>V@DLl-K*_p2PjFSLyiW{;rqf%=`RIqj}G-n~_dbrYSE6Sslcdh0`fFB9Z zQ^Ao?J5CXfB}y2p|1pA6A9JE7r#Wx+-vC1bDm>7;GJgD74Nc)pTia!3x3sTpvZQ=R z@vO&^(DH9!c|M^ZmOF^6fH7PF{mJFG>L2W&4X0Le;l|f5-%Y?t5$S$nGj3YQsdvoZ zE?R!WUkI#&F``BEE8%QLl^_%X6fwl6Tn4T-B1T+EyoN#ms`1OUFtGa(M0~ilqjB zp(=9) z5f^DBAvt<PS44$F)+fR@h;DSU4<)nS zy@GgK&dX-@LpZOq)u3$WxD#<3FNxVfdz@wD1S?m&dOEX%q$Cp^9MrgXQ<`%e92~BP zKObrL66MxXkP*dQWG{-;2H)P_SccVnnYSRuG8?3cQLl$`_EWmfDBvGx27>{{ zR%BEtn*-ioF*MQs8=xg<67EowfU*|D<~k{-B>BX|H|27UX8lEoZs+J`UYU*yZWEjiB*+=8U9iXhS_t$qh9?fnU zEE3qulQYDE%dnr~UToX)%H4wx=D{H5x8TFF?i0lX^C8jLEOzfCY(?O4B3Ifn-*Vb& z2X*GkG^<&UKBwpQga}G#GA<)U(H;E_wu@U%L^FHBgbBcWdC4hm!Gb|T_ns3HB>@DB zJz7Rtz4Z~-oK&A2I+LPX__r{w!aXJ5WZqaVOlgWq2JL~-&OMjvp|`r5eD;uQiB#WP;h#+4t%*R#+$e{O_uy=sfyxy?QOMWX*a&NyjFehc3 z+3o37SoTO4sNfitu)mfspr8Krg-Zuul#V%6Sot}b@pfWi<< znV+QZX0+LftM(RrqtN}CW8sx`7h1kTxhV3PNjcxo07wp`xs_9#JXPtY$jS=8EBa_8 zUfn%3=s=T&QyEwoXsI|~U>&tg3todc3LMFFlL@%>qA}8t>;6KZjBvx-@=J{k>;4vJ ztS#G%)psnL9zXdy-PZr?(=C7thAm9nFW+tK9iy9Y;5Z6V?xG)m4&}IU`R!WfQk=dv z=rILpsm|2xTW1UYS`DUhL z-{-6{m*@srw(OP-qfxWX@qWeQFa|uJ4+iw<>w8l+be0UW<7aqo7YTazA%^XWwHk_< z8gZm1VzBvA{{2e!Vf!WDS@~N2XHhs;5r<$&_o4LOxBbtS{vfxeGYDUvEtlL0gX7XF z$@bzIW+$v~F0uk&L)yB2WZoRWnOf(7z4lhV2lX6m4#pi6@2WDgjm<9L4NDR6Q(NwF z(DKgz_~E>_qNVEb>FSoex4{-pMAIJJzMl|VdQ8hFG_OTXAM8rdQ%k@VrJKLZ8Kyz- zC)za^W0I=8IW%CgzLKA)WGEdHMiU=^k$JEFUyzA_l34W*2ZzIyl2rtfyF;s(LlO|t`CX>K(l?n%F$H2>h27E`mKDds4JHsGnxkH+8u_u$q&MEyQ)(& zAl9^OL0R3KwO|37(shY~bnx;jN#zs@8`>e)fg8-s|1F4Uxf#{~%@e)iTRAyP)Arl? zFdfu;-%VJ?{Hgk0S^FT?;ce!8vPt7;Y^0@d*k|3Xt{!8x2DIhZmTO2I{z;3d67Fb4 zu&d0L5=4Ol`xRd-TyGHN7ludIk2*Kq=34DfQFlEH#@a=y#t8W@LV<^-+Z1l*t9Z%x zKR9QBtoa=litP)zGNvNB%7u=woEv42PEGFPw(XMYGM2BG z@r8yix18+#|^N$gv4+>OVD?UU@HQTRPOsn-!u z`agdBOJa5uv`r`g1H8Qy9NFk4G<~(6@I*0O2RrE$%X7y|nQ@kPuRI-D|49q~M%`ii z4WtCU_024Aqc`Y~xk&5ieVy1Ua^i)Mf62kuk`t%;_p}92nkhO1!QtxZ<|`ZLCHFjW zTJ`C`oC?5Zk%}Egz`uMsm?Hc%G3|@YOfT) z)5ajREHk?pNQl6oS;T$JycslPqBh^i%P$Mcb3MU;IG@iho};GG&6oad?=d!3j$FC&GSjJqF3v;x68X(IB-k3|Vb2 zl8h#@?h|l=IqSqde}(@HNf?5bv)kd~exu90_K?l}@L zFY5phL3CI-2E`C|7Ih5tsu%=MAS-aEIUlyJjt{D<_ZsTj;qfvKjmhPJzO~fQnZKI7 zx>mj)1MUb|8*Q~AJfnypPW|zcE5Hmi<0maoQ63!|Pv&yn`ma7@aOVP|v*o~5&}ZN_q+ev$4u0jEHU8m14Sw?EoJnQ(lZNw1yXgDP;T<*c=TlUS=Kw+fe8(}$|s5XmSt%Q@b|V^6f3IL>4T&vp?F3 z?qOLDD+E+;13v(-JM%2|PsV?8XCCX5wEcz^t7L*3J~klR4g49<0tSs)J~MT`>7M?_ z>V8>_;_mi6?Tyt}bEHv?TF0t+_*l2C&c0@cXzecQRr^`bC3us*dH^e+KJZ-Cf~k-j zU14(`e?Wid%{g)KHUG11J1BxC9BB{Tv(2n4P{E^A{I4H2dVf9JmN1C~@K}^6EzI#F zj83_Rid^FZokz^PX}Zcy=xmceoTrtxwUiEFKcwL?yuAM5KTzni4%J{9x0V-(87Gne z(zTHx$hp87WOoyvo~W!e-ag_Y5?$B6o8b8m|M}(2GV@H7($&@T>^?YZBhK#r89R}2 zkW}j+y(=_7)LrvWg9L;9a)dE3_a^VS?d`TAyS9Nj^zWG6;Vf0a_nnah16>TA7*Uqy z)kcv4@E7U*nEx`iAhvr;l?`YwLKKs@75*YeriW6~C4D)dY*J1@;t9vzWT(gH^(pP8 z0j7;P(vudAjNzoDDV@^L-0-l`xrl6n)$mMAf%w0+o>9v@9NJ0P=)z3LBNk7#@=IJu_XElg9 zp-&7nvzpQ7DeeUHnvG0S$0&Zx9I(biNl;AQoZ>k~D|HP~=u>pWOQAr?IQt{!l7}o^|MP3|TRuk+C9RC$PsQxzB>OX|cXGE; z*doDkUdrw`saa7TM#DFFZO2=JtxMV2oj}@e-%R+jptph3z%lIZq&r4lbvL8+m)%iZwxw8(T$KhVQ+6il}=*1X_ zh&M?zO|hDe@`3?hKru|QQBSv&nx?A9glLaqPY-x~IOB`$7?zU(=4hqK?0AnxU7ALv zWi5yU8L$-IbYt8J_+xOnjXE2Ty|J8@M^AjX7t_+VSsCvS&1NR+ZpQlZ`A`RtGaigH zw{F{}l^k{CRDfzjqJeU+3j<2R3^zEY#XifJ9cfa9ACZRn6A}~iy6f|Y&^%C%d7v?n z_n$rCtEs-bz>EJYQ`&b#D6jC!D+w__b1-_nto7!Od$WJjorb_1!{#ilGSql~Mq~G5 z&M6nZG)s0ws_crW@v?k&G--Z?Ai+(^E;rrEvd^oHcR%==`VMOOJC7b6YG|-wOogi~ z5iF>ULGkigQ1ieXU8A2Oym)A8ZKJ>H&J!QF)yj^By_*1I$-Ok2H>VRqjU~b5BP^zq z25JT{!E=e`hNUgXU0ZO}fXSI~TXH?{ZxJR%S|bf|!4m`7qaMtYy%L^sHW~4*0(&!J z?Uq?!ONW-v2i2T00#0p_4y?QX&3LOz<(8(Mc4#M(KD=7_&wN#<#$2b8) z+Tah-MT6W1p!=sx5CQ+mg9SAIv)|bchW?_TjP|#c&v}Ge4ZAPM?T#!Z@fp}vpoxcM ze66D4h;>C7c)S-A-9An`ZM%T`+nZ#|g;uOMjMr7en?kOMF?>rnKMDCxHY%8hO~~u% z%m;4>It}u2EJ-(M#4v_L-7(W2b}kNafsi3bY_wYGYB~lDyGzUN>JD?xbWBE zile!SrPoDfW^vtb9SsQ+rOE2^e)G*|ie7ec$^@}Q{Kdc$=TtwU>=B6%IZL|hfQ@Xb zHaUPTf~R$_*pbs7V(Hm@^NcYt5{G2-#(biHPd~ujVtPIyyBHgNAY$ zQ}+fLtmns~O8dCx%c<7B2>a3?}+OAalgbZ%-66w&N{pAn~y)T=!_yhz&56!tk{Dd=Q4U zqn8r*{cxn8b`a}_4yPM-0-+6*w5#>>>8nP+X)f@EGr+%fA=I$WAxp->@lC?fsMT-56Sd{JNBZG8aPWSj@hs0r&%H z6`qsjK$OAn0E@lj_Prt6o2d=Ol?5+~`{BFLglp#@)W!{z`5mZ9sk_4_6EtI*D|d&` z%2E%(;I5yQK1RW)Z7g#M0aOJbBJdS zl8*tE4K9ne$u?lwjG~H@JSfG*1R2_Vrcd8wE(bx`upaPez!}_1>V zb!FGea~j~HM~;L2?RM5Ag+wB5N<&ZpZ>>!GJ6!#Fz z99y{P1Jf_^m`?{^6*YhCf2?}ESJWMjN&?4ue=I&PbqHaQ36XW)t+xW%Nw$5LFcv2N z=!{HsShovgq$m@Mi;DUQUfPO^1^Zzs!)Yq@H(q{@+3BA?wOUl~y;+SG(;Q<_!Wi04 z(7L{(FWJ5wF>;vPp0FJs8v}m#U`$u3BDUmiHGAG}%Mh+1?lpqN2MaV=Mqbi?dHyNa zCBm!77ob>3Ge|=W&@Wpq2SmoN9s5nXlTQ%ZP(XfkJmE;G19;7Oj86xu)Vr9aG1dT! zpv5t+Jg#lWnt7dPs}?YSdQ-jk<{3gjtdqRA;?UeiLhaxA_3WDEtKLuCb$^qC&W*bx zQ6R*~lmrhDcrdIj5N^d8IIFINZpAdj*Eh`nx690Xk?z0x5X&rPwm-WGoDp-@gz~aT zccQpm_W$jB{AAiRVm@`Wl-dyWOpnD$WDd}g8Glu&tjkZv@_j25!FL8a$%ud)zeG57 zo=e~hC5xsxM4clBIOCHR6okoilH#~~dUDG` z`}U2NKj;dDoCHpLcab3}n^D~vmzFkgWCAf%Fj|&@3YGEoOHv`0L8~L*4SgZTrGBLN zW6-RVZu6W5B8Fi4372i$Um&ZI)Wy2_)g?r`%3L#64}0};Y)(%$yDa$MzD>P&H?Vsm zr-6sZpxgO6%dovHbY0Fwd~P7j+rF~|h@W8iUQ2mdXp^C!Gtrtp7{4ylM?IILFUCAj zBZ1~2U|3urP<_&uuS+!4Rj^D(ulH6QF)RfO&a@-%ZL&2wz0VYFo@Q%nIQ0cLSmvsV zmUdTJEijj4_@t4o+*-^qxxu-)_S}mQ#zrh6H54^`8VUWEtw>p4hs>rW&MQX2U6^y1 zq94L0RL?ZK!%QKpKKEv&j$h*vs`Criu!zS5?-}ECnk(t+8uIT#hM!kBFAgQun;V(1p*!FEv!h`VWjL5c_0Jl=@8p3#ToB0PVK7Yh%rGIhEun?)Wx7&+ zV}XxGxl1}%(UOytZwfZMZJcf;2w`}Rx?G7OY&#|_xJ7Kbx*T8uQxbLqCSvxVw0yHw zdx!meX*emzW2P~5e5|(tWY6wxX-p6Ov9bMkj)Bpc*_vUd;o@v`~6csHhb*Weva7Sx3 zS`<*0=%}?yl~G5jpv0w>v1}r0SQFH`Py|#|RFpVvm9`F|QZ`uvf*=Z}Eea@0*rOtZ z5FiOz?(aBn+j-}iXTF(vp5Ob&_xt{s1;ylEuj@RI^H?Gu;~|Hby@T^cVHF_h=osON zxX(Nmt^y@UJj2$u4J7{s2?rg2wn+@&awow52mNr|UJm|do1ktOyX(edMwFs(z#{R< zw)Abc;F{@Yx&w4Tov*(?4An8hrE|Jd9+*lyt_5Bes1`~KD`MNx{I%nBv>8=C|mRopv0!At^ptFvSpBL{<+xLKK3{{1gojU&Ux06mx zA*vLAhn=52*^x6jP?n0<6+(?Ft3JuxUpuHs8p?d_o2L+Zvb_ zb=5+82;{Bm+=~s~B~UG%0KfQHu(>`Zun(-REIi7SMv|lYnVQ0wxjP;k~}T z`AR+b&X^&%{BiBhN!CI|hAqVfO)xmhe*s`SvQeZP8MyM z@3<#a*Vq5$&}7CPASATCQ9$A)>}wpqO;i}ofm&<3UIY*8?PmFS?yUZc3j^asV~Rqh zjrFDCNSWraxD^_9QA(&^Zk(x8U*m`Ab_481RpI&Gm`Keo1%LL~}J7!>}NqQD~fy}_0#(H8>^Y(3d+w&t5%a?-}j&N;p zhenB9heZ4vRBPSXF;PqnyLXG`y98fnJ#){*bP96=lKw@ ze?27ks60Q0l2!oboI3bgdkSw@KJkVZdBP$YLEFEQ=k6(54;cI1TaZJ zPC%xxF4vjhO>-E3d{o5Fiv(YAuJ9x!*#0eAFbT#lVl(dvUp=QF5DXsT=n#INGX-cv zdWPNY@`}Vmc9-xt-zZ+R82jgt9a-CmyNJ|jYbs~4KeEearzL5u3KpE=yd`@NBJw3J zZO#-F-;khYM_RYB3 zI>$9DZtq&-O*EjTVfCr*Baq&@6-C)ubP3C=@D#_uG$YE92emA|2VKTRDaOYTv!m1= zd3@)f9ph&aW1AzFDv0qc1WX4#))`!*?M+P&!YyB7TOUXzJ)~Lc1gRI6oYR+x&AAgc zjCgMF_&|&GL)z%6mVeH*1lXKPfBDfm@M#UE%N5;zR(o%Sj3cCFILHj2j~~*fo{vP8 z;C#IcxjNk0jp6vMnyo2Yau%qxN80@}BkStSw&mR0dS zPMJD5NqVJGql_C~n2%;~{x*B_i=s7PAPWrZkaRrxR5NnA4muH02j(WGP)vSPz2wl9 z<`UOmrF*JN5k`ka3^rqcx5qqv5zuk4%48pyMKT)hZ|rdj--*j_$9-G4B4(sHRxMU?E^7xbSqgy#WSs*!M4>KbOle*_ zAfF{x{1-m+_F7Rsas8# zd6#~<_%^7l3q}<@d2$3hT*Xs@DnOQhF5~~|-kkzG12yZNa?m5T-O{ST!*6Rl;%=6_ z7>9jn(*ODUixx6>ATi9~C>O9K<6 zp)`jcoNtd5i&#t32yBmgP#{xfb_+}<$#<0y@tn%dot{`jVjc_{q`uhHQ5sLOHrkZS zoe%^RJ8;LOi3kFTHCZ+qWh<6|fGensF*W1gti%ys8HzFw!y#$1Vs6v}eAo(>PFP*L z?T_#SDc-*X=d5>`L0qK$S$lpH$f0<{%lc8d*(PuBp4WecDFB9d@=7%_*o*7yr`j@m z&Ia|mi5AWn&;?T@dn_K`TrOVp-pobx1+JKfG>wr(Hdo-Xa z+It6t#0zwv1pa2V!mMSV1WC*Pi@OYCPAq|e5wMArymeTS)L?i*Q%6qm9VIfH?2X)i zxF02mE%{9yHUk80Wr;{1MCIH~TTuJ2s)c zYrh;Z(mWm(Nsn!5BukRE07*rXz&+f7qC_ z^9K$)enId0Q?)ziw&Q2N{kbR>jJ-ERQ)0%CI_5?x46T&e)A4>rcPLz1;K-K0nS1%< z{keHilJ18IT5aDc4{feYdyw_FV9tNP?br+gOIN}35}QXRQe=X!fpYM8ogMGw-plOt z7{@t}*n$MUOrdI;?ai{CKuc`~3!X!Jo>y)EBBNcV_JV0(|7C9^1CoVqsOO&m?6VAg zj&($G^5n$+bJo9~61S|zQ9r~}*H*#N_jSlMKP1&Y5ZSG9eElB(tVQUv_{O4xNn3q< zaklnNO-^1~C>T+%Cy7q@Qed=xMvC!rN+Fa$b5oJ>6IdgwX+=GaUbC|y*4QAZ1_Afx zt)N`^FnP**Wfxx@to6S<%h;$eUM6#trgT_s5`oZ4PVv%6i4leqID4F{c|-m@5;72K znC{#bmnHkwO1CTQxrK0?TkfAdwa+|{#%eCQwh2*PM=8JHYqlcvc=Y+3)wM5fh|4+H zuuqX44r154$A0qk)@~%r78orV_v>3Mdm2uBGn50r(RpO7lCD+kZ)%ydKGC@x0ETlR zXuo9X$-KfdFf6~gZC1FeuRQ6M z3#aRaow&(Me8_HIxhQ^2)z!9MnJPK6bGco2?KqE#A6gox_yuW>21Qnd3>F$fg_on$ ziE`0RFeKHDX`bp4K|2w}!5Gfp_^N9DZs z&at&p9#$04n|Ex6b6=cu97dNr^$3u%lOUa`R8l!NuluG+7p9LJp`xOEQW)T9s$Kg( zC9_i{u(diUmGrZiQJ(!@@DH1YDC5JnuKnRBTP0YC|KtNjU&RZbyEPo9L%gu@gXDF% z@FNR0_iUFMUOWx*3+FWpeJ?||tt?LXVS9<;o3URe>jg^>_9H&yDKaSir$p-36hyuL zl?LnA>$bxuDD5+!eQ%0}VF*ft&bLEqCOf8ga`>>$s`&fs`C7$BU80>XLeO&06w0x6 z%|(kaNjqqM?~I)xLhv10q=~D>LIB6VWbq6vRDg5#&CI2wI-uTVBIq=xdD^D`z1AH1g4A2yul# zb|9aH#3@Ga?d#_o__}AY-gWdScK8P0n==C)v=S85(_BODH``;P0&}eRLjrBa$&H!( zImdq6j1&_-3ijJ=17|XWFJFvjYDoTGqfyNqk@QFNK3C{xat^JZ-28LdNaaJgu2zjGYrgG>=35hCY1C}l-#$1mY4vJj!6zrV83>pgat|2-4xq0uf z8e^L1sF>%m`UZh&I-U{Y8(S4wguSXl6%3_G`9bo~BFC~L55gegj~a2SziMll1*S^X zxLPEJQEnCY-$6;6H!Y*C?*Jjl%J8mlh?y(g~X>;Fos*MEr61k^;XYCks)7a~S7TPh!+Nm)BFNtNrW+)g9Ak{*CAs1FG zQl=b)oM@q}x*QLi;fnc);lt|Ch0pm6ODgC=D+XqBE4|@`ASAQRyn(^CD z{(xR#hSF+kY5*@mw0Mo)drgxJe>UcmCT-+Us zB5<#{AFR>4jvA$3eYQw)YzE0?nKh0ADl9G#o?PPynjnd6X>3QSPP=E|he8#4RuwJ*U(V8vfIX7%b5 z+wKLycd4_P4<>>05o`e1ma_@Qt`w=s}AjX8+Op2?U-r@lU`_#PR6%D(?iQGGB>%4fXMvj@uAAU;3o``3%!li#S=hP(- z;FjJgG|a!6z05n>;=8os&TtF+V8i>I^z}Z0w?iYD$0NAgr0- zI_$~y4Aj~9wPMZ_?S;{jUMn_Eji2Aq{Y?n1(~qIzRl#H6GRO=YIHW>`>woYxQLkJC zw*vhjW7-U3IlKkxFA}dEH__=Bx4+hPC$RYYAC5C~*4ju;6O#u-)o>??0V|(bAi0^j zV6dg^TJ3y!wPW`}(iZn5Ih}`n zWLE%C3|q6!UW5poW?qYh$Y@RS4ymh5s`)Edv!BWmSzk22&{rBXfz6R5_lA8Kyy=xz zMoSV*7l!0EE#}Kd1hu+_kD#KlTpQ@6Ju1_!6TU7HzFVVr!vuf0zaCUYidY0^Bn_jc z{-2V%Ol06JQN)&$Ono#MMcEh}oJj1izszmc2FnE^e!XU$>?}|Ft*kjAuXAqDPUoI) zoe#4j^LUXlNqfdh?+1SHw0B@K3E+F}4+!a4m-9U)Z2rnhMgGlPSgD}ye2&S3O``En z#y76U2w8tGzu1=hBc$km#H@-R11sTQ9AOELCOj^Q*YN{+#a`CqPkRHA*!!-c4-n!Y%J(<)b9X0LtQ=508Fp>ZHw;(#b==Um^{-Lm&xs&z;=%Pk}J8LT?n4&Td@ z_bjg3Pv6}0l?Wi$ovcz?$%xXn13DO~Hq|R@U*jZlWtwN%eS7uKy-reT*qw&!{Lc5l z;k)@BnVXKU^hW0H-+$|Vuw?IJ^~&UTEXAtmg$QBtBTIG_z0+*p4T^Y)G7ge+@UN&9 zq7SCCxBOl#&1%CkjxYk0Q@jN+)1|&pU`3U$?)2x7zK6-7`33eG;y&FDJPQWdNA;s+Lr36F5;XwFWX@)Z_fS zpZRprI`ZP6V**-_w#L|?MRY#2JWl~|(8x!%L?(*2u?5O2d!4q+Qp4YjryB%z|0a7x zx1)mUS5I{RHJ-Dhu1pl~;>F!BDZlCqPp6XfEZOxy3oWw)tE2=ws^{q{WPHiNSJ^%L zde^epkh0yuPj_2BPRP;Lbj9)dj#5|_mjQB{8za@^aGQHx**N};ium{6G|SJo@G@$Fm{f9?--jf+2JB1R(8+;;F9n8xq-g+!q zvpt}g?1IQKTq$yMAFF;$F)j@=0Gy+(O;0m?Y7IFJ2$Wr?)rz$Xo!iDZAB`71aBDkE zEJ@01jd8;g*__Jj*bQno5<)O|z57-)eh^MgCubA+VG;)tE%?-!dpYyFzO&YwSapxG zDnYKf^5go(tFoi+4nlAY5||I{crT}h^?QkiIg}jAd+yM^~wH3<kFin<^pz>hM-nER zno;C>l$b(Zqa-%0W5%W=SF}TWVRPgelM$96Xlj?djtY7dCw^!~H2M2UqQ3asfj%d6 z&)%VD7@3VsSl$~m=Qz8Nii}wU(Sv#(mxCGdA6!PZV?Go1v_v!kb>s!pFZU*DG9}Hl zYil72US~|B{rMCX65pOfdrODJz7Wavo!i-TIwA4{E?A(K?KVgLOA2vx3dw&sy;c5ai6+ce%!2a-Nxk8u@Uh zkI3J=rh1P^WX^#(u!G)Z+CUCSphsp8Ec#*;ST{&qM9$L8CI}mReu}~Y&bbHgL=#9g;HK;tx%Jvc!l_O^##Hp!CGI%Kwg;YPSzRmp`%N1T zyj6}W?7qvA{d|_0zdF=(Tc-R&PHOZL^N>3y5ErL;U|Ha^du0BxY$=5;G52N{U@6|$ zDX6-dq0;A+*GO!v`p;Oo&N*h$<|}L59t_Kg1!OHY&$-n`0=p6^S@zYo7-TE{EgKQ4qOwAGYfMC1*8fr|M} z$9er8K>(cIH_k-8GFja7zL;$Pf|e5kqv??vM^mbWo=WsP;-0N5_dS0QB@gyvVVfT+ zlC&9_jl~m#=>rnQZXwUA$h)JvcJ0ZMJdI1Y(Mo>?oOot}qR-RnA-$!4T-$Zz+`BA! zIy6sV`tMI_v-I#I#wK|&CB4D9dH9-7nl87ac~{p3+F^I@>l-=I!-F%)a?-xrk`um| z_@8+mB%Jn+U0wGMC`@t%sh-Ii@h*&l(9rUmgdo|XX&V@E6>u@SFwu2v>bJ5RKkgJ9 z*q5(Wc|Dh9uRQmt6jcw^Fo1$=nQySR6E%A~EDcuL@2u-RZCd9r3B=hhfh03#PnN07*E9V80IP8-1tQm{DXC0@EVF1vt6f z*=D&=%w-$rC)-T&QJ0ln@}>~;;N@$R9h+adw%*qUqS%^lsT~iY)7RJ1ipN;0)t^>8 zL~MH|1So^AJ-rVfB=n$Iatg4#o97=3M8#*E1Q-hgSt=r5mo4U$S(uSs1A(&SI0nNK zWVUw-ke)aHio@eC(^{&PV<^{`0JC;P!33)2nNOXTDT5O@9V(LT%RUE)3t zj0<^%GB4TsX{+mqmz?n*X%#&sJatXZE7Kekj(?Y>e|d^XCf(Q0bG&34(iO!!TP2Fk zXc3BfQYEE~sX{Yf0YB#idKoaF0`= zWqsr^1=nAcF?F(Cmp@Ldp~xpxD)kq1b&!+jYh9V~u3>ta395@6d$y%oXD1t&&(?R@ zlHT^({+^`nZx%GkUb`B*)QBL{{c-Kd1iyQiNHIbnh7u%o7*E1acM!&9t_ZgS!~K7E zTKtYWna+d*78tXW-TA;=!P}Ogxn{1jC+9v6n67Zqq!ed_!a%ND(L33{Z;QVfY5Y@^ zWKR!yXENPX?3KBeWLG>eA18F5oI#bFU<8yi#lxc}tgtHVeQLo9lw+*5JyPvPznoXI zpdU%~iVu5X9cE8>zzcW+hW&g(^dTp~BLU>Wa^j&j!WCAE#k7AKR*8McxX+cf3DEPv zSf_@CZ|k*nviPgJ9cmSCa@F194ldK=3b{98bWmGLDs$Df0f#$u zm8TLWq(GBpa-hjv<5yK-b#}137^C+_5_cWzMkJN82ZFNW1zVDN*@{(7T;;DwE@Fmp ze^eW;#a;snB_kEE%0Z&NSqrB69m^ps=s%j<`w{Lz?z~aAp-_9A2b5)^q#v?U$X51> zdsk8JkWfVNw+is20?-7)ZcXz+jw)NirTSO)JXFz|WoYH=hoxxm`9F*tW38#W2V{&@ z9>U{^4t+D$61cj_&PaRj`18zx};!LMu(g&B^FFbTFtPGmW3!o4;Nx zu$+9?Gle9WA2;z2V6H;`aid1D061AvZ+M53b_fJ05T8+5xWIoD;6IgGLn4qfj8spx zBM!w2u;2vZ5sukkxRbYvmRuqjPfo??mV(vo(CqI8t-}X@<=`G|>>Pk$a;|~$w z11b$!b`5C4HK&<{%)hKf*ggkK@>7Y>QPj0bQgAc3y!}pfeZxHGp6%7SYDbGsC)51W z_Vt1K%bRKy=EB!iK`&&^XPBEPWNF%vAZe`uWJrZIM7M6VsYpAbWqPO(%@cs4^j)l_&9x33ZB1J@6{cJwXc{;m9nz&G}B>fg+h z#rSJ3b6ZzUElRD{dy|V053Vjs>N7bxk8VnAq2%1_$V=&l)3|}=nqTL-#0LrMHRZC) zx;h#G=ScM{NA{^RWqhMn++~MmAxxhXHVz+=m9_!)@OK%6BlXFMhjSN)uAbU~VvBouMl9h3Q;^XAW>d>NZEen%G zPb^IK$tPzhv7d}0Hrb8@Q7P&tUjGW&V^>49`F@!DeDiq7* z|Kt0vcR{tJ`NgW=lW@_~u=$fu4l{a*M)Uig$sVD9G0kV4ag#(nDB9x^yX>9yCiT(o z4sT0xSLO!o9+nJjpzPY z1vy{q!r1Ttj*kkxLz=!V#Q;aBDu5PM7#)(Te6bZon-N1<&Z`#E`p|jg!D|rq#tTt< zr297rX=89%*+p0*8IW~0zO|q#p~Ke(3~DY+W7Xgk5{Zh6iQxKu&r_EZD^V(+8UmhtfjQA9rs8xKyjS<)CO#0qfS> zO)+i(%CeN>X?%}=j9u-2eEhwhS9Nf*I^o6{`IhV$-MWg05>#wd5|$VUYW;i`1NLoT z|8qDvkN+%r3oIPnKN@MWT~;C8gFgq~m)T4>o54?1T(LJ9afVlOvRYa;#Ecr3sKK zQ0gQIpb``l`-|m!5c-}d4w!U1PM2Ke-I?K;lF8rmQH+VfXGp{}P09gjoq&>wrBWw# z?Smg|syMf+tC636$1^3^FX_p)LIb_7H23h6OU13l308xe?(Q5m4 zea^BR%Ghu!aR+N9lhT(h(Fyc!?x;a`&tmF~-BnCPwpcik+v}c^Ki#wQ!4hG|oEU!S z*QO!eV#Y+Iau7YLbIrcWn5{kO&*X_4vV47frbL?F3sO$w^&gd$2a=H!n`B_fYxj^O z9yK^6dU%hK8O!;PtAr}`r~xTjDC{UOUa7~xIZy%xpXvyWIc8d^M=7L_bKwnLRAQK% zjGRN%>TKjxts*qfkYJB}CTsE=g)$e`0b!LEVM{pdN@gyU3HDLyb*h2Qqu2h*HOr^| zS6L`yuEHCf?GM#D{Nzip^!hF;Qfd|1dA;pK@XkuJRnof=)?p{I8U^nf)ewD`d6)(B z3{Mp?}<*>aKdCCT7kAzC>Z-q^w9B*l1g2fB6AgN7>haNv)=l` zI|Zz8MWdE>2(WcvFr1s9s{?k1A@Y#KZ~X+1h}kM zr}~6MUBj*{+=r~O*aoZadPte>&Xh{q^9mC7NlKVPnbHYxDl(*v(fmfIdihZpY+z0l zEc}Pl8<&oggo$HZVm=x>0o%(k6KF)a+0&4gB~wE-4kDg3&;hqDRMMQFr7;x;ra1fr zD}9~<=Jl$a1^?n21wKoCSI=|Hegr3g78r(M0uJDOKctoe;8EuiPkRru=FlNTPZ@Gu z95W2LP8b-c7K+Ym!&t(?GG^BZ>$pO+=OH+?!h0CAYX;(ZNUXBRVES8xc#bz455VA zsmPR3Hxxj^?kOY-Ad`2PzL-m;N3FUStQ|&+{K!NNMk|BiP|75tf;EZQc!V0hoY^x1 zcr|)&!*j85K(qaTeH4{|#=1O^-Eu)|;lS{kosp^F1Fzlq)O`R&x0H>6a3N=kTzVBQ z+?}k2YLDR*^CfB2SERRSgDKv{a4Xvg!!DLCVn%~!+PniK?fyuVDbu^MQEJF*8?M$p z5bM@JFPXk={t`i-Gp(pvNdv}(UJv2h2V>?jSuzB-Jp2z1K~&0R^wQJwf`u$YO#<(O zGYo`L-6`*F08L=xfIsgQzSK$LL`1@Vj!bnb5~o`k#&@ctcRN)<4%% zCG(wxkX-6_Hmv2~=moI7(VK7|(%Hk5ZZZdQ1aRljlc6uM`P?N@oaEdZS*xII=O4ZP z(#>o`@sd!C-ORhhP`tP0*b)qzY}3&MT)+EdV8~oV&mELVpgE?tijCS4?MGJ<*;3A|PL;7o# zj{<9msZ(Kp7Y11t->n-{wughd^p%$lMGu%1E+A$17=5S0IGN!O-`i;iW=O@Iijv^R z=Am{m{J?i2_B!pW8IxEHRJ|hHm>tLx;p30ZtZh_{Q%;@Fn8Id z;;}?ygVDQw6vgR0{lPm^hW13DcNtrNDU4$&^~r%c7>0Yh!;PIN?Rib!l4zcxnTKMr zjZ44hcOMDcWr{C--haj!4YoZ z(N%2-1R7}G^LC3!fs@=;7<=ijEIl|v9op2)#E2pR0!7AIQ*ekjrRS+N?~Da}5mmL^ zZ@M4>td_$g5$jKVpq*X)0W*#V@N<6^TomlpHPE1gE3rHZ|jRAkI$Y%yamOUnT zIW`5UVcI)V=?|N#_DQUrjS5Zt>?69X_QB9?W+hm({opE`#(jw1K8wGyQS>dc))F_q z!vO&#o;nAG@?U(#$FKu!Ly~S2uZtV}>liCUfYlAkCj(+`@M{`v>~GWucUo-7e7*Iz znrULv8F?kuPQ_;|zN?G@QhSWHue!gw%_SmG-;>QJh^PwopaB6t@SYX_Iy{BvKy84(^;Kv-mM~=8okR6Tk=(uCbx%l3SbzV9=yCP z^@~}U!R9pxQ9MzvCaM4VtZu|Stzz`ldi_z^vF55P0~_{=bSs6r6QVPPE~t+ymA;<3 ztFluka*C!?l~S)?QGd)zulFyuWjxXrS@jkuN=?G=CxwkfcHN2raE>x2vV|eNHpA7S z$yLEC2-Y}?6MUp>w#H2zlf+8M;8`1P&1W|Ai%y8jlK!|BRu~ikJs*8vidjCPCJLr6 zMU%!i1{15K>puH%)F2WWHicy6238-es!b(o50<`$D&@+C9&*ujdWy}O7BLf^mq{St5ksA)=#rEJ zlg^USUVHX=(DJ)8$t;pFBfB~7$qMLD#7hbdh#amz4eoDM1N@El>ovnV1x-bB;6~`@ zdGYs8t=TSWURR48+Ri3fdr>J~6=KGe`s7S`j_Y6ekiny~z0d$sFm}jSO@liH{XKxj zvE#*C6hQ`)hv(%_-X+NHJBxI{M&b4jf`-*`U*R1AQOaj`0+ekan87bA%VmG6O5r77`+m=KFC-kpM-PF=Fr4Jn$9S8|NQIToEu9;bxKT^B@;k#_75 zi224RR`RRPN)zG_t@jihU!B|J()|@rI}w~=?AGQzXsK3&^;m~Z;7|-uDOX<>8+hOV z-V9{2c4lOyJ!q>O$NdqYuSH8N)1|JK$>bDv9ZbPoum>wo%X!i+S(u{g_b+RK{sVFA-j`XjyI^JYMZhUej&d+w10>kAqfGa!| zpw`T*kQ>s$?HsR>{zMp7Z|eK8LYyf7E)@0O7MhT5$IYO4?>Y>)E^8$7*ESLlu@-oX zu<&-<;4>?$dTUcEAE`iqQ@3X)zFixvYJ(5A+gWh*1y?OJiteA|L&mCgkNLXkP|6R! zbUcz6s7<}~hIs>ms$HBeTkA_@U7}Kok=R!*m?oYU42_+Al!|WW0$|TB51oHGwa5kP}2>a{AyQZ#Ntvm`tJ~ zB;6c=JA8n|B|DplAY3qaVwr}FV2}%&nR{S*8T!;}jjRnm2C%fq3e1@@>KF>QK*`mP z$+wPR;?gPDD~LaO)WkS5c^$}EdKT@`i!xx}1}3>9?393&Wy-XH@}T9@-htyzo6v!F zr=KJeDMGIjD6G&fONN%g&5(4hoB4Fkv6J^DZgU`C-Fum{dzoWR-yQe>)9mIjb^1md zU&W+mzBhcv=&csT-r8cE2>~+yhx5$3BF6Xn7VHWZ-+_q)BL-3G#<_?&HQV^x9bWqb z@oCAI=y1>lcLzv3VJ-xdYNE@Ea#c4E`)g~GRI-kiG%R$_YZPt#{jv^0pkz!{ViR+@ zti=m>k>+-+aV4j|2ZRC`tcrI9A1G2mgDTh$_+cq-~O!rF+*EYj;&h=kkzz+;0Bx=+( zvOT+ZN9ndx+$fC(-z`WbXj|qjuU=?$n)VJ;hXB|0^m$B87%)Z~#$)AJV|E>zgGhCt z%=@4Hd;Z*Sx@7Nc zv+YIQ7nf&okm-Cc=rF{`O8>#SdtjifsRB{DPbn4HY?iDQQ=sS$ z5bKw$%pYM_59rv7(yGl5biUczDX5rdj=(}10t@9&5?faVAbQ4-E;yvg=tqSJX<;Au z>Tr-tpnSzuqwtO7^<5$}l=GGMN&8%@08BnwFTx{U3_1!)Nz8zGIbYFrbaZq}z_*pd z{rgUVSvN-dFC2gFdlKOJZi3hI+IpIvCW;fRdQg!Psa5vm&Sdtk|Nfb-0>JqO8a>N8 z5|J7sBpoRTz$9l8-Hfu32Ey+As71?Wesfwd?7EwCX8)hhx#|##dESA?N73NuVXLEY86hS!t`wih11+5)~}@B0*BU-nfTbEJSzsM(0;@~fduECF(Uyh;Nd)f|iqi1kp zMvk;clLllhmS(55&vpOx$IvB?_MBx?)6)e6c*2uUi@k?r8!pH3)5M7$U_dMf9nVxL z`x4!Z+uE7aC=>jWchGV)GimLdKUWmN?}_Ok;e^HKd7u3;dt`*|I$}WiVS^Du9Rkl$ zbf#T!qfzO9+WXDAF`Q2*_LxLz43F$1ItA#ovHsMp@M}T8e#jhIw7ZH49SbUYoHsu8 z!6~Nn?o6I)4DY_7zGYth<>x+6z?i~LBLRba0nw4Q>e<)3@A-GlqPU(33}Ta1yhbad zF(pezZZ*Mv)bOiAdv<%Cq8`%%LA(B7q@tV6Zhuk(9w^o!gyQv2FeYPrs=%hzsrFO! z9!9c{kfYYoAHW=8XXm}Cb&lF-P3P9B80EbQtD_|FRipaA@ zYt&BYuQ9Rnv6V|;G2;w4lymM~e^sC2k)(twWg$tMwUMJ~bnw3U0TiH~W98C1Sf{0@ zUn+0Y3-00kGNGkX?SkAnI%f)K^;#c<~9I=y$&fIptZu1cQ2hzRAKWc-pBzgRRN0ve|{J^v7-G9Qkc=*VNm*f2DS z@-=4AeF4)bQA}EIUB~tp4{W8r<11?wn$k^ge{;Jm4hYV!-FQR6UZ_>z`K+$4Z8-)O zE2OoCl3>^h)H5?Ji%KN5g~89^pd@R}tLbbLrgRmj6i}ygI(dvk&i#oJaG(_F*}*V- z5ByqS=rIQ$T-_1WtPXWxo$7Xbt?%YNR~Y*IiJ{GT^JY>rWj+Q8v0uMWVE=oZQC$UA z#ycy=dY&dZAHj3Cu{o(AdFgrtUQO6oE8QA#K}lGX*KN=nps>v?r2RXKrWN!FXoIui zJvIY8V`aLc%dZxGzJ30rJPX=DSc5wBx?AvKqZ9Z5q9|QmP{lgTlcOiVcsNK%pfpLr(%busl3%qVHe`IKto*^CQQZ(aBtAsAM z8xtR?)FDq58UUsq__`=Hftm~^@_&|WVqR$i$XFVeyy0BqS#F`Ea(`A!R|AK$hE2+1 zuKv3#AvyuEO=AIh-W_ub*=)=<)cZ3-)S*Z1gn{Jw)O{aaO3?Cuc`U0Sv|tx5mW%aB zlthyxZ0V9lp}#staeM}y8)#e6Is;u%Y80?jPtl0}TKV-1jt`1m^QY*(Czc#$%GqZZ zKqQ{szCO0AN)$s`!D?9Wz`=wLFd|Xgs&i(OcvEOsr{57X+2M%^4Tvf0^oO*jMcl79 zzH@ynZOyZTF|i!b{!z>NwJs5U?~uDY?9Ss-^P#lH07y)h(LE zHPU#ODrKhq{jp8R#U1WZQ&XGL9s-8MI1;HE=67^<>ruxZ&hkOJ3ZWE;++?kRAw1!* z0!5jREeJP4imJz(H6@ZvSu(-wJ2{jRSrW)666shHM|0uB!XP2eU)casG^m4J%hI;c z7x`tr+CvU|=-PvRUSU~`P7|#llhB+R6C0d$LbV@(F*~i(gP8cBcVm%~C^|tcz(*fe zamws0aynK^%+14pSgoqH?B5vM*5TZrd(pRSz-Ly;K}}-AJnq+Sp$S#H+cmc8nx%Q= zH}jsgD|uVJ$MAHUXnn_!HBo5WtkoV?Xb-`;n!H)1y0a;5Q&|f#^f-3mQ5mf+l70_O zgt>OMb4wxbu-w|CS(u`Elu{fY_RNmutf4nhE}J+p0rcna1%yy!$q4Rt8 zGv3_T75fD$!_JJrH{-4J-~m(liTNgB{;PUhkZeOQ*u0!)HF-AX2SCeIzDQAjOyLL( z{B9a4%=gTB7?>T@IM5Y}UFA2>4gBW^&2;!63CLCVhTHT@ER>G|)MoX)PCS~|x-|<$ zO1Y?v`51{aqG(@^rS|)hu5tc`k>ti2#VS=mQ@zU3D6OxTg|%Xh^-)UYmcw%+Z3cJ%XM@!6au zbI7d;4Fs5thjb}XXcMdOCeQq)>j>UrtihjS&4~tPZfl3NSR$;1Xt)#_TlkCm`1p<9 z5F|vKA&Euj&N;VH^MFtG$)bd-wtx^oZ1v|FOG}4iMI#2a%`fQ zcwczB08TwN6=_QD;#pDGKyGYqJQ>?e4QD3HGzfeqn(zS=i;xuBLu~T0O>rbIaD5 zhb*vzP~7q7MKPoVqC(m%5T+$$Nx}h@csJ-dpIJ^mvNP|qcdv66h`E$a)+KqiC>lgU zY@~Q@?wl%wFpLf4;NL6i>>O;&Kzk7|2^x|vP*^VnjQ?};LjH$A*J!3wmz%FjbzHhj zpdLt`vJJrmgwguMpaz1x~*~)qjR56;r z#4ejk>oPSAyAmL>V4BXS@YZ|+fe`m#$O&t{BZATDwNd&?b7r7_kF&p7{vDf=;8gRl z)yJRZ1Gihg544mXRibHsvXyag-xEbQh}U)RC)R+mqTxTYUDKi#+mC%IA49R>ssku3j0a+GU2%lHM`YbZE^IlXOSnmM#kPxm27Q)$|`N|rm zSV29z`NJb1fo|N*dj%UZD#$t?Y{xSHq}Q(Y4}+xa5<`2AmN4`{WZa7yeu)iU$f0=q zw}ZwQ2fx)Pk!^|8tEOhF5=x&}eS`nYBm&|Nz{?*yxZ$eIkQ+?fE6#B~!Tb31LHY1D zhRipYTu;r;ULrhWBr&kcO$^YTjl5I}JGKA#q_i?Wk-r#|W+mh`=cN65E{emz58Yh+ z?!DS$`O+V!%of!~yAVQKTp5iyc*4PpIau#xv3B8)Gf-#-QmkLnR~(pFGGl03dIUMg zcJdePx26vSJNRfYjVuFoP{!}|R3lv&d*8^243S(Q$4i(74UUyG+Ro|Z38$tr9QL-b zgfdB`RNoTYO%x#xt$KVzwCq8JxPR=aEaeT4>gs9^J*!PROw(ZnNX#>$psC!EXwD(+ zNQ0T=O*@&5ISJ|>lvX4y3GW|nz9>Ph7ii(vw}B+|1K4|bQ=-fc>fa3K|5)y=l>uOv<8RjD*1mRM3^Ez3#?-EhxB$8{+ znaY7So%ss;nHa*Em*vEv8`=JCQx0=bZtBdC1Md( z@6%oTQ5^YQ++Eyhmmpmd+`kCh2KHXYB?)Qb1P>C`9MYZQ3Wwi)R#D>c0*zvU3@x4mk^ zmxGs01^HiBZeiAGhoza%OZfI(&h;%|H3E=#jk!@An4M{9yP`DKq=NpR)&cQ@A?U5y{O8lxc6`+KiO`#7(FZkU=qlp11 zcnN%4Y1=XFH&Vl&j4kFOvFW{6HxlroB?MjL(eTiWC*O3tTvALf1F4?owF=Tf!R!1i z+uD`O0|`bDm6BaScdZZrU7RS|-*6+PsRZcYUQ7yrYLgo6igWmJ(-0bMBM-{0i$Ajh z$h_x*Kwb@uHfdsfVMqf_CNZ@pk4EF7ytca;vhI4h z*&a9zSv;fqmGsi1)N`+s2=Qx(nSb%|@!2Oy@DnbOc2HWOd8lT(CZl>udLg-hsPtfs zFr$ebRPxI&qtsCm6obrOK)Cdp_QR2Tfahr|-Cq=~H2Rv%6CNQB^SO69G@_GrE#`mi zOQ6&~33-g<%x0M>h;of3p9+Y8Hju0rh%55@0DJ}e(V`Pv4IQ`S0T4Da2EQtoM>(rE zK~b%TGu({?zczF^O@~48V=p^c6}?_ME4z|oPjxj-pYtPjqBv7~5Q#aNW53jX$0Qo? zF>ySkuDjMbwFomjmo^C$_EJ%jMBmG6(m5+82BTw}-2Ux*Qs3~Onj%I0f-spJSued4 zMF>2x()XkUHg=|BTC!cOH0AZS>jkvN!3&7fP>Lx(b5@2aZVQCl6F8W2u2|WqExn*G ziWTz2%=_YeF!5#kgZ4cPbP#lYC{x$TisfN1O7??kM&XVR;)MlX-HZ9g!33C2i<7rg zJ;D+uRlowFq-`NeMPA$7ya*tDiZ-mz?Hhr_=#hXJ01HWx!tlg@pG1a{cMBUWJmL9SvE~oUi8V!5Q|BHL zCHq}>$;Rn9!Hxk@tjGS-JNPdyi{3lzS-jAab_9%095Vn2Ss4lxUB0rOXO0<3POYVQ zGK`CnYPl53COwf3rLn$jo~o<CC8U zM<8W{0W_$v{4Z=1HhH(AM-oNj4{z-K9Q-D3gLa!hT&2Z!knDaeI(i-U zw1=N2)&OI^gDEuU)8>cNLJgb}$@1|Qt{Vf=$leLs_;c=;q!zRq*WxfJNn4(tm4>JH za~OQtlUMe5kCidnUCWct`$YGKl*8-d*qNfXwsAPI>bApsQkQVrd%re4i)%v%dV54Zu`-n0 zV8~_$bI@2APyJV0M8@L}T|e(m;5c^tI%=F(g-rw?()Br zmGywo>+%lYyNhWVfTs+}0VJEDbUb~+aZ*GQ&oBpXFSCJ63`q9Hxv+Zm6{k=u3T)-K z)3lpIY61OfvNS-nUjfp)`to#y;As>;t8IV`u2vDl5YC~V7Xb%Y!j%T8&Ah`qbKA1E zht`b<>$MYFV`J&lTvG?H=3wF*q?&hSN#Hyp4MEXIVaTFVWK7xB9z~xo%%Y zIj0t52FKGg2z%TI;W?y?C8Fzi%xIDV+i6(;m(pw@ivUgrmpt-@OnUsyH8eU&?0h5*TeQAX}baewhl?qZTtORGVgCK>o{f;x_{bA(Cyy ziz0k|Gg->5`sLsKqnnj6)X%IJ=N(7jB;KAZjK|(D0gVvY0ZC5x0P^g8eUeCC^dI(p z`Zp))4VPDl(aT=J^amsroQ9zG&|J_GWj~0^gP;Z(nO`9`jy>Lc*B!ga0UdOTH60KwsB`{&{$UE^Sdq9+_xs8 zA5Q=5{~ zDOf@lZh>6Qn?|>9es`IqjOf~4^XyBj^J=343Jd)PL|W`|kJTHj^fP0bW=Wgq+dM^P z+vVL?mZq&hBC~A_47j}EG<(G<`?0+(-BM8kMa3Mo3Y%BB0Lrbt86V*Q94KLztW&FH z{BAcH>L&CJ}tyAA#PzxFx#8%8OXcYMJ8@hZ5p zdMjozGtsGKY853v1noq`$G`@-)?Oepb6C1guV5$COOco{CGz=Sy+T8eBG)GCwdh1e zQtW`+xw%O8*qUMrn6cx5=bPp5$)-dZSZ8lHCI#QI2z}SX!^|(Y*RnHL5YG%nwxVho zY;LCxt9fgm__t?<*<~KAJh3VJk)-&!LuadK`Wjr4LTrlnDN~A4G1=n?Ih!di+RQ|K z;uwYhk^1^QS#t2p6NpZL+ctvTV3CZ#5F}PmhzGObNn&o1$yFXC>Tg{M|MqR7+Z&Hm zo@L&tv3A`j*_qX*7Is%bnKz01Fw@drAkWqN|H=C=mG=!~Qmd}Za6xY-6Tm+>6R}sY zA1?%=xTjaU3(?4yT!Jq#_Z4`+aDI=;oc8xb(j!Sjw`>L z0;!RpOX0a>);=Qu8DUwC$KyU6XTw1vIr3jRGn+qzyEFW&Ly)&O0}m~t89%=aS7BFC zzZ0&L^7e_k{N5@tg~d=(M6hsNRAPKk=c0V2I2s^AiP+dg${ zraUom?E zm}}-$iwBhTi(3yrah&M1q6ME$nw-2O^bjTq*(>*SE1s#(Q=Bzj*IU{1yO03&K!SiK zx-eIqa|^@jE1OdS{((wcdL>!lLk=07EI>wQ%|$ z;OhU&FPBrj1X+qa7u5BrB=%3HEZkHtu98B0%~V+D%HYwB{E#JBUOX*lPYZe#FPse< z>A1uL*6@$^%W55tjBq*%r_e~`=(+Bp70w|kQF&}Ey2Qs9NQgU zUUBY64F+V>xKN_d{bR_fL0QMf_RwNN(ZtsW*~!9=W39CjtC5L-`yVKu9{^8mZ9M!W z&wMo_(F*Vzbo_MV5ex@QEL$5Vu_tG1fXtlsky3PfmU*2B%xqkp%zi=dtXG`{-XRUAan)jy_eT)eT57OCgX4Dv%fGERqs zk2wXa?%1%Fb@c3*^oF-$siPIF)HN>(ADV9#NZUlqbbly+4!o(Jg=@*Cr6VktjS^el zpSQoQY$1nT9%}mF z_Bcq2x>K1WuA7#tvuya?$43yby=T4HxtPtqtKCQIsquA6;(ffRhJf)*Lx7Ms_Kx2pvAsNdBwCvvH@Q|m&SRZ9AK~aC-fDZd$;}{?%qDG=KKF2KMA4H zWMoXa2s0xaiYc)%*P89UwS}6?P$Vst)N%193AqkY#v3!MW|m4vM=EJaHd9eK=@O|^ z9XXvko!9Svf2A$M=KcA6f4}eT_WNVE+bHL}E}zfG zo)E<)39B;9dE0YM?~ZKq^VnV%nE4vw$W`a?HH<#@@ke1L7DdZOR&98Nhc7IbF8qFv zhFn|RD>D=64cXq?P0BQ*KX6bnR2`Av9=QnGz8mQ0{l|GU=1$_cdN|`Hm&q%)B#9aLCP`8B5D4x8>b4Og87VxRdy-kR|Q0=zRd~zYO zO8dKm_oD@7|2F4V+a|CbNRanZoV1BtCk*=rPO>g+yKIQ8cTC=@j=^hwpE0>`Q(Vb@ z7csg`K6L_0q7GO#JMt0S@NPF7h9sWIx@>sv&le33P*qOq*mhHp^>WpaH?71;Cq~*r zPkmo}0sWjbF^KAzCQJS(C+C3PupM2P`Y0Rr=W7)f?qG;JM%CxAZHSrYWkrE*uxto= zbi@cEt^Ok%%oc<&^XQu5Mz0NtnUll-2H_SH3%QQKQ|hZ!?3Fea-y`mA4KLrWWW&CR z{4MOzwIH!uE|zK2Z8wNZ0nZ3gktdadGwlWy`gf*_aAV&Ma0o_Hv+K&j<**463Ul5cdhI(%|(f#yYr0#K^ZA6E-@yYG>zwcX$Y)FoX0!om^efD%^+^8aF{ z*Dz10d9`}xB6^JRTf^EIl)wd7&=6SLp0YDrfb^af#$2?xJe+7P^f2(;;P}C~H_>J+&w~}?1xB?dpySC<5 zUDWFI<7Stuho8!^@eMn}c4CKvp~R8};XG^xC(GYS8s?row=51-)2(Gkm4gwjbQlqw zZ6#Cq5-=nQT0n;?1U#lQ6$0U%A*d5i4!V8kkP5+1>4+y=hvgs*@p%iPdw9?5n~bcZ zwgq9nLlFvOGTM61xi24cIpI1dK>`U^KkoIJb`y|8r+NKC~VmV zkZF0j5y=uJDW^ZnMTggYKqY1ZCPN<~9O$th6DK{=hh$572Xfg#NVxY3^fuxHqgZ3Z z>@;rEBl;to(Dd<97i{7Z?(?YLJrLOl13YtlL7Q*yWy_LDk z)p)c`x^LcvU7v*%f}bRCk+noKg8XAsqi>J{%UwAkO6wBwg?@Z|fVFMs#Ayk|AMyEP z`jsydG*RntF-Ea>yu5>Y_E3YcT#d??&oqubD%znVu3L@v@R%5A{NHl6EQkFXY!5B@ zMwz6%`t_5hvAve?-9Ti``gz?E@LGL!(%oc)?nzKxfv?kv`IWa8wa8V`^|~;Ymhhu? zOAuxe7ckIvX|V9lnWTP|F`k9pmDRV+u8i3B!;UXrOYiDiHngT#zQ)>4$Q}5TV?Vf$A}ON>Ghh$^hEp@(jc4X=5AR9a~8uJph#E%f9S2B#sF zniUS~HgSmpgB=*nrw|1pMB-jjbiXnjYqd_;a( zrPYouXavOkb}^?{T$wUan2Po4v_D?Ul)X&si-&i=tu;fPU zecB4e*ds`WbVIxz9$9qY2Ir!qB?Tu#XR1*2K-f?bojMv9y1@oHnJclv`5Z-$$;TVr zw)f-XZf%oKObgK3r;RAPKDQOZ*wC+iy{}Otr-Icpt7v~l7U2S3Nxzua z@2hv$NLZ93Fwpu2`gCc{K)Z3qVwy3RQ3;yzx^(&4cQWl3*KFV}7I{Xzg(^hsrHFUc zSZw{|h!=~4tx@$rX-#W$ssuW+C1`aCvF>th`l%W%8(y7G{DR&PxR#b~6U(uwk{h1; zOl~nw+8@<~cxQ2!VjMco!E=C`Xd~8P3HtR@%-Ae*`pt76_f0`@*St=6fW?X_Av#TDs^ z*}}cFQQJSvi+a*)wx2<2%xEZHO|{0s|JlA>-k5J&qL$WV*U87hBji>pSfE3!W6)OO zvCh{{b5#Mr|Hc8n1H7T7hl*g)RRV(yaf6lfWyB3aY5_XVJ@#u;CiNkzkjU;?*v*qs zm8re`(G|Q4aK#uo3!{T3X094tmB+na9gi4sF&QeCg}C@ScT7qSx@;*`d)b{Ln1&|^ znO>d7Wq*$8+vkySrK8{i@>%8lw+4oVE@$MbPm2B8H+ILenFMB1#4<9iyEEkb6wWqyQpIX#@BKF-3Ys3lVasP!dBw;QAJD3C*HfSG& zkKL8k!%|p;Ds8$4p6v`)Pz{R?)viIhq289)LHgUr47J9vn!WMeQv=HuhcdL1S$Uhx z#r6@voOT)#>EH|;T(*BHAv~7t62`UpL)r~Kk-sHOlpOx<;+)+Mb{l?m=Rxi4MFZ5i zKn@Z4NO*uze`054gL6V1O^lr_tL*n_HgBxMHK<04dB(8mvSH}wDq<9=9_b^z09>G< z`4~aAi=S=2G6T%-R$MeqoaCpSwyJ0bBsxaE$(^D!ce3>hM%Y$ev|IdEPhsDVC!Ojx zhU-RNSNND&On=b9LbWF9@?d#Nd5v^p#3l#B=x)n~pq)a(u>t$hsf%kY5T8B&P!Ef% z2Cb{W1U>m z;2e`OzwNq?gi~R$aC)AqZ~28^SiAtc)d#N3#+Z;E`y*67E9F4m0uVmTM8=i!tledt zAbi?t9imq6FG(?6mD;O}BG|K=%!vu2gT87AYz{{v@pD2p%em#Q*ATo3MgO#r9k9oh zH;xri6mz|msN2PBgK-3^U;W+;)rKNGDCIRt&!(k(`e#X{^1aDYD6P(;Aw*^&e%EI_ z9@SgRB=^k3?4p3o!GCcD>LM>Ac-@bC#Wkp=rY}1C7EBuQ;dV8*3LD#!=w?^mX7b*Rf znHu>rV7JzD*qMw1gllpOC8WvXxVK`_oz&#jClvX^j~D5XL`-mfEv}9jnN_|X{Hh+P z`Sg(=i$Qln3YMB;t;WxBCpPEInT~H@3v@hCvI>?NwO2h5vkZ}GuNn(A#Bnf zi2oX!s>?ro(XVGu4+$4~G{murVcUTHW*RbV>2{h5(BkA)Uq|;q=%B72R(ebX+5$?Z zBZS3IK$C(9^;KHE)(_o`Y6HL||J95-DB(WmcmM^2up47C1;Q!?<0(j!CiEgbiOv?M zg#849b_-1iqCeHSxnmGcfKOz^CVn1=T+Q7Qgj3?43+c~a1MuM>8AkVJI|Yn3|FuDM zqX5z>>&=AgBU-l+p|yE#Zio<0!*8U<#zM^rA&H|>-)@i;M75xT{lzeGA1B_A|aM#C33VPiw`4--ZP6n4S zhN|xB^w?_p9!>cD$J?`OO3k#_UBj*0UP?@{NoW|J&^A}=2Kz9Laf@M(^oeM(X8SRf zeobM7wQI4qI2ObwR0K}nqxYrjzs45#bJ}KL;~fOG)+kt-W$R(ds4_%*nIRSWiaB_H4*T#0fW{`Q7Q&%0n9LNc414&U%-ErGBZ&_Sp)eY$4EoK6*X6I(GCNRW%7{GLW zm@eH-WKRvlxn8j4j0V%r>%Muqs@4nPH5;D25dAoXsGyjqMi zx~su@lkY?2fB=KS{-)OgyW~n35WkWM)c)qx52JMRC$|F2FyU!Of*@vMG_6)*I$$c) z;c|K35O9bm#{};=VEbfqv?Vmatjp((8ScTRyK2j98gM zuKq@M(Gei*TT>*ESlEWmJK*hqA+qM3sG9DQ_cN4&PN5oyzM<&7;J7yHP$1h0kKss# zri1f3$t8qpo3K-BxL7!N>{gA;puj!Yw=D};Ibmushq-7JhKbU^1+@?+CBWQN1hA*9HnBs}2NtG8Y(^a~anJ)hvR!49i~$Z< zY&Ms$a*9KSHPlPJa*IzmKKvH`=aF?ma_{$rS&olVOp^hX{Bd(MA{szQLyuz-#5*^5 z&m%14ePd%}8!^_K^F9yX?b+V$2;OBLEsH#qa%W_}ERb9sAr~5?nQ-&{Gp%$@A5+1| zM6<)q-&(02AAE9k;@VjUEn*)inEeGzcA9%~>ZW*V*4kuacvpXoD1Y>~E20nD8dgT?07)HUX#ixrifUn`Q*ft0OXg z3j%``CAsnk?YDijN^aR7iW9q&BUSR0K$n>-y7IAu))I%zeqQ6i^MFf%J!f+Dj(S}pn&Z2q0s&qNO={98}6pxmA{jT zUS*|RBRf^zLD9WxXeyI^h4VEm@u>UTosIdSMMuxKGfsp?~a>w7{s^vD&k`(OrVN2=E7+D9bo)Sz<=(pk_oNBR;k`VNVLWRWu^zO1L{EC zz&G&-0NY31)Mm8%{GL-}!+?44Z+=Ai49}6K>KBKbxxB^q^U)S7%{FnB7rJQe$F%%N zTv>Rf>_e&vKcI&;(7??QJb8@?Zo(E0rK z%Z6yZ*k*GQ=MN~kJXV30GN%;xP+vX9qjVI#AlG8}I0>$|xa<~JFRCk7$$8U3KrjK{ zMxM$6K-?Vt*E@3?uVx4HqJNng+z}{IAuNQGJK`ld+OE1PKmm%>Y%JzGz5tR6P@fY? z^Xd&4>f&KT6ui(CDetc(wOeP-(X$E(@PKc!ReT7}#rs}u6c_XHU>WqNjKQDrSZU(a zcjs1mk(Gt1;AOsz`1Gc24AD&qDf~j-@t0kUB|}h6H*&nq2Ow4fNUrI^VA_M>5ngMb zSwHV*c?>MMO7Q@2ePv}IwJ)}md*VDRR)Ig`F+8LD?DZDK;b2GyeAlY78}$!rV{%7( zZm{wZyb5aXR%G}*9-Pn`#-3rh4|+zG(4X8VIsGEaj(A0b2W+k;Rxfi?t#R$8DD|J6 z8sl>-W{pkc8eQ0vpM7D+m$f0p=U~8D6fIaSNCNPQ3-N7D$eSfd^|39l6NtP={5D&? zk97l2jT4J%EgC%-&7i>qcLB~@2!RB_L$S8)Izm?HYHd0vN;jRdsW7GQN5LY;(s>vq zdt)i&NZ7Hm#557*Asjr4XCR&afA>8q4~%XwN`w;wOD@n%4s9t|&rP1hC7Ak--9O2; zez7jXRYicLk&lBoOk;XE;X4r)ITH%bNH9`Bs^^27son=ed`8W+KZ_6>2F1(8+RN0l3uzVEUHQ&|VOW%>#1CsWU^I`w z&erS9#Ulb=U_f8*qa-+>aBUY=|9x=DufYiiO<>Np1wyCu;8_`D_w z_PZ65vJ}A0sGN(fp@<%M&}~K4IFrh;>1NvBqg2N}XqG^G+){xmUd+iMs0flAOo(tV zSE87XdkgO=`a^?vCTgc$IeXSI*mZdZ5<=I!U0yrcB@M^|4XoFZdF79_g|i#bgCyKr z-0}8&88s01fAXBw_b!hG0JQ_qV#@qq`vqoXyxGt&O?QqM1^O6{fXJ?sJxU*Y*!}RA zLk;kixXA0Lb{1~^pZ-?jHk^C_z3+$jBPS^mG3*z2pc)&|9|Lj#hjL6_G-_h_z-2+F zF<8e5vaZk~Y{PO>!W6(j1&*2dfbUE!aJyW z*Q13SKjHO0BBN*oG#~3xx}0b&VNH)CMwx90b=z1xrQ&!Fcal31Fnm1_3#!NAAzg(Z zTi~|+^XdDH=gfvBO3E>Vg7HQdHshJQBH{%eV7*C1jv7Xm!mU?0_@OZh|NS^ZJv>VU zNmFz><0-g6(cK6}in#1J1B1b22Z9JB;n*6H}d}usw#F)xasZAt2DoD10 z&IaJz%{Cnr83|q}w$AgV;F^KwfvG$|4f1|`uqguY9fkvLqD_zyP&2M52acxUiP%<* zzWL|tg;%UkGYA51xzjTBqoGFsc|9~WChke1m3zfTxA_TiiTe4qdvohHxi!w>4%1ST zn^SuGnzVJGGh&MWJ<#Ssr?Bd64L|zq$1LuV>o9Dl${V z{GBmldg8hm!Jx1>&`!2d==4ARbd%y{_yUd0K(q{_pMLb?ZO(b=K_AO{+xgzfU)WKN)YU*i(2I!TWF@c_hwG1e{?t8(7ncxL?L*y-e#Tm zED>)Yj}o>p!}&Yz5+jP>zL`#9cyRjSUUkZ=w)5>rh1<0-MRL+Z{G$*9QGKE{q5Ek z_LB9s%$%=kHN`q;x#Pe1nsG$ChvR0@LYEE6b6c$2VT`FUcAKC%r&%th@ubF7VHZm-~J|;AlNgl@o=dAZv>A7K?2e=W=A@ zj5A@95w;0L+!^5+s@F4TGz&R&pTqF^V;~_7Lv^-IT{|vA@EM&;UiE)Yc~sx^`1$l% zAJ@=GrT2>Eu5)4=#`>2{k_Ot=opy5ej4gI53Y)Dgrf+&s1uRSyo@VkVHnthDrgc&K zmvZWaD}x~gX`{g_!DH3~@y?KdLhwoqE^vA%l7DvyeBJ10FjZIQeuY+X%)yhzWZ7Y_ z(7QUq&cEge)+>aqq9AW{9pzPtw3EULJp7wDimuFEySF;?@f3qTs?U9`Q7c`EVuwRb;r>Hnei4WOdA%bk5N8(Vk?RQc#`q+Li3igP)1 z26#FFC4`HGHQpKwb7jMdMnMA+k4g=Yz3CD!HF2>{o9DI0cvi${NLIn#*#>lH@O0ww z()lT7O|3$sx1M7yf@5NLid*ceLZLC^q>ul})9=mL&IR$yq1hbSdSIUaDrZN*W&q2t zq+w_0L=qS$VHWQV=*p6H&{TXhNbeG+8|V(jUw!$hPX*eHZV*M;Tzhc}?V~MnbG~TG zCmY=tCN@}fWW7{WS>9o;{jS#QmUl9;2VbTQTYQN7kPegvT=M-;&&Pg~1|@o6 zqR&;AfRbz&ntS{Vee8m<;eD##MM=o_7&|+jlh$+XSq-7ws2P_uY!v{dUCDmxxrK!( z5Ryam&}t>$mDjqU$aKakx$~fP$sn(Jp=D*5jbJW`A>8R`<36TK&~{dwKgS=wKO@Z$ zKFtHr&0!?dP~q$|-eKCa-*oH)uN6k^@%Hab){owQ*j5_Iu`EWm7!C50Vygl4V{j+m zrT`T6jq|$efpaN>rr@Z65e_H8F);zHvG{>t>M-qkxICE>6+fOmmp0#bqifoUb0#_RmF;u2zI#87ebNWOsq&^0 zA@I@=2SY$OPoC_@jtQ+fpgo627Tv$=Ifw1D`%@GNgt1rn4jf?p~Op#&1{sVE_&Gzbj*RT1Hb{Ci^0xMUtYr_ zl3Y45%X3pkMw{qv4lYgKC!b)9TYv)v-a$$;XhJ#pHob4khDCQnV?JR^$tnzGyjS=+ zef92Qh$H5!+y(?fO=R+su>|y);01U!AXHf3;jv>muo!&3&>EY@;&YwW9Y4Olb`2!9 zLD3rSi`PC1z!{T8A|;qQAxWTOb2SOibL$6%G66`BIFR@YFqg|M7Q|F8<_W+CmN| z|0P|PH&{|7Y89p8P(~sK6mSM32ZHm=t&FT!ViG0;hTUPEyQ}tBGn*Y}bY3htYb=Dx z;MGFXU02=IxYx=%w7@ExP)nhl3W{m+$4PAHWW#WCk?FN0qxq*TMl?^gfYPq*+5deP z4b~m*MttQ5nI7m=!K+Md!~)g)Rh?R>l9~V{T}bE7Xu&`cCvd^Bcw%CQVOaB77XGI0 zx-M%s%FOf^f3vV2Sk=<0%Q|*43Yk+&$m`(A|6~nM02tELT>O|tym>mR>| z)`}=OUVT!~TU@c0Id1wf87FuDcFCy~5H~&tGA?B}0}jXAC;-mGD`M z({1c2D|Ja|Es;0GOH-S!aPvqneDfb;^N(!1KKB*;WPZH#ooCLx<-ZjE)q>a8 z{QFOj>2!-@Y8ojv|I7ckrJX`~ttxE#fz9iM!OMoAqEQ^nx(qJcn8}5YA5bcpfwvQr z3Xmn{)Ext6>E-CZ zv5`&0D`$)07!a86g_xG7TPvTr_wuxatie?UCcdKvMvh5>J*ulmYD>>!giBf zbHq03pw{g%p+tb!@O;}z%3F05g77q-P>uy|0U;yA*pX)PoHEnm&Ld_b7IX=4Ov|pjS=TvxopyC(7 z5}YK-N>meQzcC*=hQbeD)S4m{z6)T21Ewd{><(5ZimZ0V%?sW=G_Lu5urKu=5wY5&R2!@DZ*$9jRn(Od? zKl3~+uzJ<4Q{C_*7jzED0hRmq6?PBQK2X$r zXTNreWaeG(&B6?j|9Ia=t z`NPhAt*lp34xtU|H1I-z%ws)pfhuZ1Aja%~a9ve@uK<<@iTX%;-&dAE22C{vKVusS zq-*bDg!40Ov?5u6qVUF}ic1CktEyjnNHEX)%mRbRDsSa(lq6Wj-p3}ho6Jd8rsQ;@ z*&=_RK!j|`HR-!5vqi70vIPm`>9#7;XeI&LP?fCp`Y-gm7|i`e%i2U?!EvkvcTm)C&NHt* zye&h1klf5sT%=NtoyxilECBb5?b^KVn(RA&C)563c&2o#jrwA0RiskW?pV8Zwwfeg zAFb`2V%s3|nU2y!;LDf2CG1vt9f5&6wpd{R$K04ak88sIZ6uT?k=@)#WC#r1To7Qe zE=b4~LBYlrA$tLkQ1=qNUp9pDO)yf# zaX>Y>A^Bh^#VvPpgDCFqW#D^S!dIk=goUGOl?v(@5b$KZu{r#sq;#J-$gxt3DS4Te z!WXab5B^y`nFmyDvO+LQ3aWRkoD#8#JZP-nturf7)A8?u zFi8O^qNas{*4rP%PdHS3Xbgz4#;u=jL7+5<6ML#W!DhCL*aRK;cyK_we~eKxH1Ugj z3EgnwEJ`)-lKt!9p~eFnungL+&fpywQ%4J5%DI__pKXm*pnyVQ`ZDYd4bN_8Mzltm_h+3{b}76a#D?t#SO< zifl*)kH!rI7<~%U42a3l`@pIsB@md)!?)?FKEv**XRn z2ro`6Fi0pDK)hS@jO@>`B|-PY+0>a^;}rIMgn1y6-83%XV5@93HX-UIv217p+i^~f z{nzmT#&2AA9{ZIzxkUE>&Qq-UuXK6b+n)Pak!d%p6c=!eY8CrdmGRWtWlR%dZGP)lAB4z0HWuYuTo_=Q(jDhpku9T_ERDtpm8ruTm&0RlD8CoFKJ%>hEw3-gzpJ_j zN~GGq%oHB^HoC!&!Y*Dt7#d|z(8uD*|%d|`)kNR(AR3Li{ zf>UU0A(Vj+ploRzI;T6`MofIq8n~l#+)XcsCY8=Ssj$UXvuEJzof!>qg^Gkh{Us38 z$tPxi&cmXQfOw~=GL+?|+lbRz;t80;tIlDDhP3XYw>TxE0uhx6S_}RRG*(b4eEd-d z*6p$NX|)@X+>Gl3 z*~7#*sjKBgRM-tJ4dxc2JqAHU-b8N@c+7()8eJlyg4bFU^MT$44ln4;J2Do572i;) zntn5x8>!Ii<%hv$9ZH~))M`R@MIt`{U77@#>n36g-P+I#vo1=JF*A}IntV*V6&gsv z%VE1YpJLt!7$&s@&ZGe}fP;NKIpo#heLg&FJrY??T`jJLUMv}MIBvDxCC$0P{<>3c zMe<*c*j?Di%vU|{)7k!QOodcw2D>|r&%tbI*GTDov^z_bJD+wmZNWpFBLNKfp)txM zTvCb*s2nx9@*?G!`St0rXfJM`_OxL=3QiHC*EKKAM8%CM3RdzDKG zgR>S~x4D~ML7(-xsX9QKa#u4~@thzgRce)y?gbsc=XR z#xU7?JeNRWPfn>5=2Iv)^>-cw&X{bts-Z$%Z2_LE;S>zvE#jcEG{N40W(o3IiCL^_$4Bt3Z=Wk(+AoW! zo@Cn)D*LrTHbml?rRw3P-YmP4d$CW_su_EaJ^?9s*s9bn;nz1hA=n_V_V-+b99|6j z^4&GdA|#VxaMAYCy?Z?Z)3K*dZgq681eK<)e@pR_VCkn|Z1qRF{-^^L_ITq27+FD7 zMq=$0SQcY0oI82`*#ij9shUiJ4UNYzLXGZGr^LXt8`E!5W%-Q9vT8fV=huS`Q?v%d z)O+geNB<9$Lt1;Py-{1phH#?&sAvj+@s0 zQtGp%Y(TS9r0|Y~YE_h^$qiOWgb(yINtGxCYB`M(OpsI+R($cUa@XD-l6Qj#Bs?fL zMHE3VNmVCh%_j)8hw|pG?~b~y7WF+(rfI#rtAcEITX|>3ECgRi2nKjqmLOGQu4r&A12exhpm<#TFnpBa$UHOMbs^76~=;-fV39ud7Y z<>Qi%#@3|NWkm@F-FiZnQCp65aWie$z~M7W<>?Vp!QB78p?p)o#m5Uqd8ld+Csg;i zGH<@19ctGYI&fvV!X_}(Of_uv%y3D;6sb=AuG;8NnFQt?&rW)t#LDGYz5L3%c!wLU z<+mTJ8gHii@=9W!GFw_QbA`NOr?A2xzCoMeCJf57+l$D~jB?01rS(DbbYTF;Fb1Ne z0j*>QSdpGNMQaUK<#5wTvR(U@BU8V$9QA%8Si<&4;lz|qtpBlBnoD9A?DSI^8vWjT^SsYYnXxu^CAI&>2mv{(HTP=n4TLB+(4;JvniM2Nw+v@RsQMqwcK{1;1F{ zv?)&32c_F7%J(Qtwv>>!!(tm&WwQD+^6tAOqE?Drr(@paH{u_+s-lY(Yi~sn#W5(d z+r!#CX?T+sk@9rXdQ2$tAa0#Aq2ePCA5Gjd-C^JLvZDQg>AHif}tWaX-|u5 zRNmab(BV?J?m-tUZDF}CvMWLT+OM5n_9X;dI`V&n^CKWHf4 zZ0Z$Y(r69uf||>a^;vI@JR=ds(s+^AvjqqJe~$zuEe87i&lAxn#nHa8*(J7V1m`TG zWn&UF)iQ;F&7nJOR1+5^6#NulIjY!R`e3#0l<&c8zy34lc=cG9Dx@iX^nGG2^n^a8 z30g2fd78m7FL)t8Mn`iiqPi2PtJVeHE`R85VCx9A!&Z#Xz&-3n+D9D9YWj1~I{}tV zTWkf@!0M-7YGK>(8zk*fIk)!OfSo-l2es6 z6^h5Luk?v?3f*m17dG(bAx-$BWY1GRDONr+BtMPRJqqy;79y^kMcg|%8)Oi0EZ*@F zbS{yDi5u!-NE!km*vW-@*s}|I&Z#v^-^|^SRtX%7x$49JaDipHCWL(k{H~%#zSfV{ zc;g9#l8tS03#7hm&rQ-OP~ZU92tB~Z!DPau_>N1kY8+aGSx^6|Vmaj-_;x8tzfI@= zLv}xSMSRs8X$dYa;|C?mlS{v%Ulu9~-I=CaM#%s?y8e*%oYC3!{gX|3;h~T9gTVN; z4OTWg+?PnSzgXN&%=hY5ZF_sI$Htht0qcoBAYlltCcr-m#1$yPc9c!pK-)}u22P9yY0V86Q|-WS4XxF>Kp^}VU5-i0 zA0Kf9odTUSzQ*Re0azA0VbOde228Q{cXV90g~*j79L0+r9N!>F46MQ8Dn_Ab28M0R zb8~jyNMRGuVfc=<)-y_OO5xh4_Ni++7#Uw-e&?Y{_s%}drC^bfbbls zQ$)fCzK6(ckdj>TV*SkL+(0N^5SKSvBu;JbcmNGqW~tNfq@^?*fvcMQ3MKO#aB2xp z!N-7wGaT8DIY8j=ReG(H;0RU`1PQnQw}KI2xkw;X`=WdYolt+`7P7d3trbqh<51|& zj;*W=_ke#Tzk}5RoUfh9Xb`;pp8{sAwgv;T00-(g#0R^PjH?PG3p-*H=Bd3~KFDp> zJlvzMD~)O}cwb|71}OM#gNt3P#ukp3ymn^2Q(czXyo+4_zKdq4<(B3@?o5_i<|1bG!2&wL?Z$qN*LU2B*6go9(PGzSAbXp$ zK?MOSbX1LflQA`=*$jeBIg~)iP*2e(#NOo|)e;!<=wA|tq+n-nDVRuKU(8EO`8%dd zz`F&uM9D#uL;@6DicgGw{_=2$)3(IMvWSS@qXUag9?G;@#FaMpii=VXwv=AiN~TdLv<&r z2cSu26S#HWlE;4Y&K`iwm*NUIoxBYjjduae>SK05HriJ7{RqfdvuucHxOXml~P z-@MHKgClqa?L_B7RHySe9GoZKC@grz>p``wOSRpYpZ}5ReSl?nW3dBCIHRK7DCWg1 z4vN;Zk;ad8F&CO#hK3SlArRnBMOPjXMt&yZhhdb*nKz*{isLzhMuU&{n1;Tws_P!2 zjP1ZbN-j_q^TnRfx^p4DHm85KAnq-E->j(;IskBB2F#EBBTH(`s#>k%JJ9fx5&Y2r zAAmqY>iws%26t%*lGMt7gTl!t)o!ir%zW>TlJb(R;kpaTvh%4n`=nzhicOWdqQZU7`i6NkNHVg!@0%}Dt3^R4;9>CtjPbf6M zas@f+f2+0V@a)G}TZKBG^;yqvfM^q@O)=ErWG;s)0Avc325=sMPmDIn)_SAKEg&nj zm~J#b3-}i78L&`ta}KDq|D*yjxrHTmnoC+EHU!v}eEIHT4BesV~%hybTIA80-h25=8;T*(6p2lyid#+o;cFsNf*+HO8F4yt{H< z=t0Xf_GPYws<1*$Z7(6$9;}9Oh%x&c5lQSrX~$<6QTA(crrB)Weq@NG@?z~!f9>Fe zp!o3BV+2!a)lK>JP4Stl~AviU%q4J(Q>7)nJFNhLtkjGH6O2XEM>7EQkV5Wk?Q5_U>4i}bU zl;~9C9vr_Nqg^9tS+aJ+ecb1_J(UF-l#^mJirU8KsbiBZR4|B-$@UQg>F^Ya6eMcB zGr`lNa*4Rk+gvZAg!N$k)6Q-ljn=5I%@OkZGn<=zSX>v#RF&TE2U zD|#m&uid4KcJe)0J%l5ex5teJ`+m!Gm3FT&R^n0CbB1$6!Y;g}0Gt|O0A+|GO$g7! z{UsAmYO-OS4XS(&T#~*Tnyqzuz4N0-@4}n_niLAq;Rk^$3exyi2Sc<>%ZB7EzG#Y# z8=Zi9H^g@s(jI3+fYSK=j3BUB@mKB6&gq0lJ~Ki&7y^C(lCHX2Ao0Wf@F-oj5T>Dv zc=peZZ@i4JAJzA-ymw({3m(4gyS^~$Zv(v`Oyin$)rj8<+Ya@&E2tcV?+s>zYG2vr~On80l{B;n}@Ta zT*CsqR~R?*lA~(gw@`PGXm2@b-xSPRFq;Jf`VHz`;xMNf&IEVQX h)-4H6=t| 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 MignA=zutc2U$Wny+W-In literal 0 HcmV?d00001 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..65a1fe1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3343 @@ +{ + "name": "pi-todo-herdr", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "pi-todo-herdr", + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "@earendil-works/pi-ai": "^0.81.1", + "@earendil-works/pi-coding-agent": "^0.81.1", + "@earendil-works/pi-tui": "^0.81.1", + "typebox": "^1.0.13", + "typescript": "^6.0.2" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@earendil-works/pi-ai": "*", + "@earendil-works/pi-coding-agent": "*", + "@earendil-works/pi-tui": "*", + "typebox": "*" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.91.1", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.91.1.tgz", + "integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.1048.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1048.0.tgz", + "integrity": "sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/credential-provider-node": "^3.972.42", + "@aws-sdk/eventstream-handler-node": "^3.972.16", + "@aws-sdk/middleware-eventstream": "^3.972.12", + "@aws-sdk/middleware-websocket": "^3.972.19", + "@aws-sdk/token-providers": "3.1048.0", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.976.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.976.0.tgz", + "integrity": "sha512-0cjRaEdlVoOrsNb9pP5q1Syyc8pXw5xSj2Np2ryReRTr9FppIIRVSdZK4lbnfmc2Hvgux/xBOUU6baB7z8//uA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.2", + "@aws-sdk/xml-builder": "^3.972.36", + "@aws/lambda-invoke-store": "^0.3.0", + "@smithy/core": "^3.29.4", + "@smithy/signature-v4": "^5.6.5", + "@smithy/types": "^4.16.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.60", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.60.tgz", + "integrity": "sha512-BAkxdoe7tpDDqCghGpuOeHQRbm/2znVvOQm0AvpQbA2tbfMN46doN4zx65fv85ImP3KADwc2zQPmbrlI9MPfMg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.62", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.62.tgz", + "integrity": "sha512-g/0fGqKTb9xpKdd9AtpmV5Eo3DFKbnkpA2+w0peISSlu7NfAoWOuYBFxsu+yWBtxU89ka55ezoZBCbFaS8pjYQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/fetch-http-handler": "^5.6.6", + "@smithy/node-http-handler": "^4.9.6", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler": { + "version": "4.9.9", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.9.tgz", + "integrity": "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.29.7", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.973.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.5.tgz", + "integrity": "sha512-ylubazcRfq2TVus/qXucSXeC42Qdjp5HQxTu68K/BsdMiZlcSLD1zkpoCgApXZX1Y6YJhtGGs7ZHhO/GuIgBlw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/credential-provider-env": "^3.972.60", + "@aws-sdk/credential-provider-http": "^3.972.62", + "@aws-sdk/credential-provider-login": "^3.972.67", + "@aws-sdk/credential-provider-process": "^3.972.60", + "@aws-sdk/credential-provider-sso": "^3.973.4", + "@aws-sdk/credential-provider-web-identity": "^3.972.66", + "@aws-sdk/nested-clients": "^3.997.34", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/credential-provider-imds": "^4.4.9", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.67", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.67.tgz", + "integrity": "sha512-CCygIKJ9YbI3n84OClSaSppkgKKHVj2TGT33c6FRORZrYNZQ1POmD+ip0FLYokiJAK7sSdc3YVkOsBm90oxWMQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/nested-clients": "^3.997.34", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.71", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.71.tgz", + "integrity": "sha512-HIg7Q2osBzajQwL+1Vkyh2E7Gim3eTNb9RHIsOxDGjW0eZg4oEKtRs5sioCnc73ilhaOm4gX2lHVF8J7+nt2rg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.60", + "@aws-sdk/credential-provider-http": "^3.972.62", + "@aws-sdk/credential-provider-ini": "^3.973.5", + "@aws-sdk/credential-provider-process": "^3.972.60", + "@aws-sdk/credential-provider-sso": "^3.973.4", + "@aws-sdk/credential-provider-web-identity": "^3.972.66", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/credential-provider-imds": "^4.4.9", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.60", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.60.tgz", + "integrity": "sha512-YIo3f99hM43QdYG8hDzwGemnR/pU95b0kramqSJUTleCqaB7+HwKf7YZFHqvOgTqZTPx/mRmNIqoDRr3U0Z3Tw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.973.4", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.4.tgz", + "integrity": "sha512-BPdmL8sSBOCv4ngZ+3LHxyc3CNqDCEK37CHioCk7zGrTMY5sUtkH8q+o6qA80nn6w3/fyBPGNE7OIRlmoOxRQA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/nested-clients": "^3.997.34", + "@aws-sdk/token-providers": "3.1092.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { + "version": "3.1092.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1092.0.tgz", + "integrity": "sha512-hBYUAr6iBLNFcsiWTgtBb0stdSw39VOUq4Sp4A5caCNf66BAZplWN4FleKrVpJx5li2YgdnK2DqoFSMWC642FQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/nested-clients": "^3.997.34", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.66", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.66.tgz", + "integrity": "sha512-kSAziJboOmZmsR9/MTbiNjowl2BPes1bQuJpne4qAZ62ubi8fjfr/aupJSQje6udBoYxXTQbsL0e0kby2la3ng==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/nested-clients": "^3.997.34", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/eventstream-handler-node": { + "version": "3.972.29", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.29.tgz", + "integrity": "sha512-t3tKQRTVXsI2QNPE3CaNjHl0wRO9Xi3acZkAyti2RQsiFmZ9Gi0kArX2ighlRJ1BtDVuul413gThAgzyTfgmWA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-eventstream": { + "version": "3.972.24", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.24.tgz", + "integrity": "sha512-oykin4mDWxNOuYQ7SF1cHzgYeuFEkF4cdRwgvjFFbIklkx09qIFBiOgsORafG9sXZFO3TayMmQuAQYgADXhI8w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/middleware-websocket": { + "version": "3.972.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.42.tgz", + "integrity": "sha512-dw+GP8DC7QC2C8tUoK7DI8BnrNAjz8tb+uBHSrD2qJvxkCf58kTtFr98pljSrk+umU4n4HDW4eU2k7C2dWMzsg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/fetch-http-handler": "^5.6.6", + "@smithy/signature-v4": "^5.6.5", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients": { + "version": "3.997.34", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.34.tgz", + "integrity": "sha512-Y9REVrSwmLM+Qy6sZJ7ofMC2S3Hr3tPP/4CzL5U1olPP7OGoF+6+Px0E49cVQBtSxJtyeLJMf0UaBErfeSahAA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.976.0", + "@aws-sdk/signature-v4-multi-region": "^3.996.41", + "@aws-sdk/types": "^3.974.2", + "@smithy/core": "^3.29.4", + "@smithy/fetch-http-handler": "^5.6.6", + "@smithy/node-http-handler": "^4.9.6", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler": { + "version": "4.9.9", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.9.tgz", + "integrity": "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.29.7", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.41", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.41.tgz", + "integrity": "sha512-QMUytg+FQMGouc8gHS00KoYih3+N6cqmVI/pQGOIo7Nr7OpQaiXjSYOuL+vsPZ1tymY4LAQ8MYcHJmws5LRxng==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.974.2", + "@smithy/signature-v4": "^5.6.5", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.1048.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1048.0.tgz", + "integrity": "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.974.2", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.2.tgz", + "integrity": "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.8.tgz", + "integrity": "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.972.36", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.36.tgz", + "integrity": "sha512-RdGmS1GLrtaTOLE1ElSluMldNrpk9Emq6uYs8SS8iHlu5xTAmM9rRkM91o48+rIRryBtyO9t+uLYCoMG6jVMVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws/lambda-invoke-store": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.3.0.tgz", + "integrity": "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@earendil-works/pi-ai": { + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.81.1.tgz", + "integrity": "sha512-hzHE7Z8l5mgJk+ke67Lge0rwS2+wbKJrFKl9o5M1R1rh33+cCT7D1AHz1OAtX5wFs90E1/BTGhyJRTUHaMxGvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "0.91.1", + "@aws-sdk/client-bedrock-runtime": "3.1048.0", + "@google/genai": "1.52.0", + "@mistralai/mistralai": "2.2.6", + "@opentelemetry/api": "1.9.0", + "@smithy/node-http-handler": "4.7.3", + "http-proxy-agent": "7.0.2", + "https-proxy-agent": "7.0.6", + "openai": "6.26.0", + "partial-json": "0.1.7", + "typebox": "1.1.38" + }, + "bin": { + "pi-ai": "dist/cli.js" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@earendil-works/pi-ai/node_modules/typebox": { + "version": "1.1.38", + "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.1.38.tgz", + "integrity": "sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent": { + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.81.1.tgz", + "integrity": "sha512-r6ovAsZOgAqbC/aU6s+/dPnv/sGZBuWyZNvi3pXjpbuX5wvp3XvGkQI7/VLvX2o9XpmpFaPUxKNym1WfkN/P8A==", + "dev": true, + "hasShrinkwrap": true, + "license": "MIT", + "dependencies": { + "@earendil-works/pi-agent-core": "^0.81.1", + "@earendil-works/pi-ai": "^0.81.1", + "@earendil-works/pi-tui": "^0.81.1", + "@silvia-odwyer/photon-node": "0.3.4", + "chalk": "5.6.2", + "cross-spawn": "7.0.6", + "diff": "8.0.4", + "glob": "13.0.6", + "highlight.js": "10.7.3", + "hosted-git-info": "9.0.3", + "ignore": "7.0.5", + "jiti": "2.7.0", + "minimatch": "10.2.5", + "proper-lockfile": "4.1.2", + "semver": "7.8.0", + "typebox": "1.1.38", + "undici": "8.5.0", + "yaml": "2.9.0" + }, + "bin": { + "pi": "dist/cli.js" + }, + "engines": { + "node": ">=22.19.0" + }, + "optionalDependencies": { + "@mariozechner/clipboard": "0.3.9" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@anthropic-ai/sdk": { + "version": "0.91.1", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.91.1.tgz", + "integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/client-bedrock-runtime": { + "version": "3.1048.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1048.0.tgz", + "integrity": "sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/credential-provider-node": "^3.972.42", + "@aws-sdk/eventstream-handler-node": "^3.972.16", + "@aws-sdk/middleware-eventstream": "^3.972.12", + "@aws-sdk/middleware-websocket": "^3.972.19", + "@aws-sdk/token-providers": "3.1048.0", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/core": { + "version": "3.974.11", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.974.11.tgz", + "integrity": "sha512-QpnINq5FZH6EOaDEkmHdT7eUunbvD27pDNQypaWjFyYz7Zl1q3UCMQErBZxpmfGfI7MvI2TlK8KTkgNpv8b1ug==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@aws-sdk/xml-builder": "^3.972.24", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/core": "^3.24.2", + "@smithy/signature-v4": "^5.4.2", + "@smithy/types": "^4.14.1", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.37", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.37.tgz", + "integrity": "sha512-/jpPvEh6f7ntmIzf7dNxoNX6Q8vt8UpesCjbW6mFfk4V1NW6bIy9qxcQ6WbA8As5yQhsZOe+xeNd4xHX8kdY2Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.39", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.39.tgz", + "integrity": "sha512-pIgTpisWyWg7X1bUbzSjuUYosYTD0Ghz2M0hkSTmb3a6i3qV3uU+NYJPI/E2XSC0HcsZh5rsLPzeXrkb2DS0Cg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.972.41", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.41.tgz", + "integrity": "sha512-u2tyjaxJJzW8UtW4SM1ZcPMDwO6y+kV+llvou+Adts0FAKyzes5jG4izQN+KX3yE8ZROpS5y1LJ//xL2iSf76w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/credential-provider-env": "^3.972.37", + "@aws-sdk/credential-provider-http": "^3.972.39", + "@aws-sdk/credential-provider-login": "^3.972.41", + "@aws-sdk/credential-provider-process": "^3.972.37", + "@aws-sdk/credential-provider-sso": "^3.972.41", + "@aws-sdk/credential-provider-web-identity": "^3.972.41", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/credential-provider-imds": "^4.3.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.41", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.41.tgz", + "integrity": "sha512-0LBitxXiAiaE5nlFPfpNIww/8FRY/I7WIndWsc9GmNFOM7cE1wNpVNQEGEk9Outg5l8xl+3vybxFyUy4l9q/LQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.42", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.42.tgz", + "integrity": "sha512-D4oon2zbqqsWOJUM99Gm3/ZyJ0IJvTXVN3PyloGb3kQEyI36fjCZheZj422lAgTWWd6TSHgiImLt3RIaLdv3dQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.37", + "@aws-sdk/credential-provider-http": "^3.972.39", + "@aws-sdk/credential-provider-ini": "^3.972.41", + "@aws-sdk/credential-provider-process": "^3.972.37", + "@aws-sdk/credential-provider-sso": "^3.972.41", + "@aws-sdk/credential-provider-web-identity": "^3.972.41", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/credential-provider-imds": "^4.3.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.37", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.37.tgz", + "integrity": "sha512-7nVaHBUaWIddASYfVaA9O4D5ZVjewU3sCol9WqZPGfW0nR+0WqE0xHZnD/U2L33PlOB8KNXGKZ6wOES/QijKzg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.972.41", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.41.tgz", + "integrity": "sha512-IOWAWEHe5LkjSKkkUUX9ciV6Y1scHTsnfEkdt5yyC4Slrc7AGbkLPrpntjqh18ksJAMOaVhoBsO8p2WyTcY2wQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/token-providers": "3.1048.0", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.41", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.41.tgz", + "integrity": "sha512-mbACk9Yypa8nm4iGZLs0PofOXEcTDOUw6wDnsPXNDNSd2WNXs1tSo+6nc/fh0jLYdfVZThhBL98PHW4aXFsG5A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/eventstream-handler-node": { + "version": "3.972.16", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.16.tgz", + "integrity": "sha512-yedpPgKftqjU5SlPFHfqWpOw6xSCRieWRG1euWOlXn4WJxt2VX92VprCa2PpSOXjVCAeK6dTjW9eJRXVig9yGA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/middleware-eventstream": { + "version": "3.972.12", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.12.tgz", + "integrity": "sha512-tHTHHCHNrq6XklQvlzHBDJG4Iuhh7NVPRdtmvP+nHFA+5sxPlIDzlAHHgfoYHGvT3NXP1yVP/L5c3opUn6T3Qg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/middleware-websocket": { + "version": "3.972.19", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.19.tgz", + "integrity": "sha512-mkEhOGYozqKQkbFaVrjwr0faiwwZza1v5/jSY6Tucm3bD+uKTazIUH/4Yo6aMnQD2ua2W9cMP6s8mvwTcjtqHw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/signature-v4": "^5.4.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/nested-clients": { + "version": "3.997.9", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.9.tgz", + "integrity": "sha512-jPR3rnmRI4hWYyzfmTGBr7NblMp8QYYeflHXba1H6+7CGrWVqWKQzaXFQ4qbExqPRsXN3T3L3JxFhr6aouXUGQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/signature-v4-multi-region": "^3.996.27", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/fetch-http-handler": "^5.4.2", + "@smithy/node-http-handler": "^4.7.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.996.27", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.27.tgz", + "integrity": "sha512-0Phbz4t6HI3D3skxvG2uI+VWU034/nSIw1T8d+FPzzQG9EQTrw94o9mOKO2Gv3n3Oc8P7JD7RAUxkoneLWv5Eg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/signature-v4": "^5.4.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/token-providers": { + "version": "3.1048.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1048.0.tgz", + "integrity": "sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.974.11", + "@aws-sdk/nested-clients": "^3.997.9", + "@aws-sdk/types": "^3.973.8", + "@smithy/core": "^3.24.2", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/types": { + "version": "3.973.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.8.tgz", + "integrity": "sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/util-locate-window": { + "version": "3.965.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.5.tgz", + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws-sdk/xml-builder": { + "version": "3.972.24", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.24.tgz", + "integrity": "sha512-V8z5YcDPfsvzrBlj0xR1vhRtocblhYbqdreCJB/voGd4Sr5zjNAeWxexbnqVtskTJe0vFb5KMqbSL++ePl+zRw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@nodable/entities": "2.1.0", + "@smithy/types": "^4.14.1", + "fast-xml-parser": "5.7.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@aws/lambda-invoke-store": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.4.tgz", + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-agent-core": { + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.81.1.tgz", + "dev": true, + "license": "MIT", + "dependencies": { + "@earendil-works/pi-ai": "^0.81.1", + "ignore": "7.0.5", + "typebox": "1.1.38", + "yaml": "2.9.0" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-ai": { + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.81.1.tgz", + "dev": true, + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "0.91.1", + "@aws-sdk/client-bedrock-runtime": "3.1048.0", + "@google/genai": "1.52.0", + "@mistralai/mistralai": "2.2.6", + "@opentelemetry/api": "1.9.0", + "@smithy/node-http-handler": "4.7.3", + "http-proxy-agent": "7.0.2", + "https-proxy-agent": "7.0.6", + "openai": "6.26.0", + "partial-json": "0.1.7", + "typebox": "1.1.38" + }, + "bin": { + "pi-ai": "dist/cli.js" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@earendil-works/pi-tui": { + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.81.1.tgz", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "1.6.0", + "marked": "18.0.5" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@google/genai": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz", + "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard/-/clipboard-0.3.9.tgz", + "integrity": "sha512-ABnA53mdfkGZwOFUdZNv2S0CWGO/EIuPj8Vv9xmBFmSYg/qFc7ihO6q5FcQjvoE67kZpWkEc4AhD6B/os04yuA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@mariozechner/clipboard-darwin-arm64": "0.3.9", + "@mariozechner/clipboard-darwin-universal": "0.3.9", + "@mariozechner/clipboard-darwin-x64": "0.3.9", + "@mariozechner/clipboard-linux-arm64-gnu": "0.3.9", + "@mariozechner/clipboard-linux-arm64-musl": "0.3.9", + "@mariozechner/clipboard-linux-riscv64-gnu": "0.3.9", + "@mariozechner/clipboard-linux-x64-gnu": "0.3.9", + "@mariozechner/clipboard-linux-x64-musl": "0.3.9", + "@mariozechner/clipboard-win32-arm64-msvc": "0.3.9", + "@mariozechner/clipboard-win32-x64-msvc": "0.3.9" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-darwin-arm64": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-arm64/-/clipboard-darwin-arm64-0.3.9.tgz", + "integrity": "sha512-BfgV7vCEWZwJwZJw03r6bP5+tf0iI/ANuQYCxi9RNn7FrWB3yzGuMKCrNLRl6V761vXRdL8+OqZ0wd4TqlsNOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-darwin-universal": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-universal/-/clipboard-darwin-universal-0.3.9.tgz", + "integrity": "sha512-BGGR4iA9Z2shAjI65eI5xtyb3LYNlDW9X3gxKxDbqtbnREohsrqznov6zpKoIrsRWpzlYVEdKphS7ksJ0/ndSQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-darwin-x64": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-darwin-x64/-/clipboard-darwin-x64-0.3.9.tgz", + "integrity": "sha512-4kURmCbS6nt8uYhtmWpUcJWyPHfmAr5dTpXD1nO3pIfa+TSQ9DbrGOYCKH+aEFW47XhQ4Vp8ZTszie+wfFvDKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-arm64-gnu": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-gnu/-/clipboard-linux-arm64-gnu-0.3.9.tgz", + "integrity": "sha512-g59OkUGP2DDfCOIKypHeYgv2M55u/cKvXa5dSxFbEJ34XvIQMdcVmpKCkGUro3ZgefXiGVdwguvTMQGpHWzIXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-arm64-musl": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-arm64-musl/-/clipboard-linux-arm64-musl-0.3.9.tgz", + "integrity": "sha512-AGuJdgKsmJdm4Pych7kv3sqe591ERRaAHW3xjLooiFzn8J+PxUyof++7YZrB5Y5tpnTO+K18Og3taj2NpluCRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-riscv64-gnu": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-riscv64-gnu/-/clipboard-linux-riscv64-gnu-0.3.9.tgz", + "integrity": "sha512-DXBEAiuMpk7dhS1a9NzNxVAFi1vaKoPu7rQNgY8LIDLGrK3lnIp3nT10DUum+PKVJoJppIP+NAA8IZe4DMNDPw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-x64-gnu": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-gnu/-/clipboard-linux-x64-gnu-0.3.9.tgz", + "integrity": "sha512-WORrMLd6EpElEME7JRKfSaY34nW1P5LbdgK5YNCS1ncG2LqmITsSMEJ8nh2mpvxb3TxqbOOKgY7k9eMJYlW9Mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-linux-x64-musl": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-linux-x64-musl/-/clipboard-linux-x64-musl-0.3.9.tgz", + "integrity": "sha512-/DHn+1DrfL6oRaPPWXaOKvonFFrni666fxd+zFqiQEfvBH0tsHVWjq9iqBk0oDp0qaPA72lIMy5BptxISBEhZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-win32-arm64-msvc": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-arm64-msvc/-/clipboard-win32-arm64-msvc-0.3.9.tgz", + "integrity": "sha512-O5FHD3ErkMwMhNzAfu3ggy0ug4z7btZuoQgwwxlzPrwV2bxlD6WDpqBY4NCgICAgZdDKdp+loUEKVAVt8aYnhQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mariozechner/clipboard-win32-x64-msvc": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@mariozechner/clipboard-win32-x64-msvc/-/clipboard-win32-x64-msvc-0.3.9.tgz", + "integrity": "sha512-ihQC3EufqEY81vhXBgVBtK4prL+wc62zJsSvxrgz7K1hsdt6OObz6v9p3Rn1OG3GJksTTKMJF0u/guMISHPhSA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@mistralai/mistralai": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-2.2.6.tgz", + "integrity": "sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.40.0", + "ws": "^8.18.0", + "zod": "^3.25.0 || ^4.0.0", + "zod-to-json-schema": "^3.25.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@nodable/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/nodable" + } + ], + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.41.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.41.1.tgz", + "integrity": "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@silvia-odwyer/photon-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@silvia-odwyer/photon-node/-/photon-node-0.3.4.tgz", + "integrity": "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/core": { + "version": "3.24.3", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.24.3.tgz", + "integrity": "sha512-Ep/7tPamGY8mgESE3LyLKtxJyy6U52WWAqr/3wial47Sj4u3PiIF73AOGI27UyLy9duTkhZbgzodOfLV4TduZg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/credential-provider-imds": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.3.3.tgz", + "integrity": "sha512-I2Bti0DKFo2IJyN28ijCsx51BAumEYR4/1yZ1FXyBygy9MqbnMqCev4JPth/MbpRfBSRAX35hITSnAdJRo1u5w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/fetch-http-handler": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.4.3.tgz", + "integrity": "sha512-F+DRf8IJazRJgYog2A/yJK7eYVc0rqTlRzO+5ZxjJd4WkZoKz0IJRncf7G6t1pdVT3kryJcwuTFhN1c5m6N47A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/node-http-handler": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.3.tgz", + "integrity": "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/signature-v4": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.4.3.tgz", + "integrity": "sha512-53+75QuPl6DL+ct6vVEB51FDO5oulXr20TPV46VvJZg76lIlXNWfxi8j+G2V/t0I2qxCBOa3vX/8bmjrpFVo9g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/types": { + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.14.2.tgz", + "integrity": "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/@types/node": { + "version": "22.19.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", + "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/diff": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/fast-xml-builder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz", + "integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "path-expression-matcher": "^1.5.0", + "xml-naming": "^0.1.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/fast-xml-parser": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.7.3.tgz", + "integrity": "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "@nodable/entities": "^2.1.0", + "fast-xml-builder": "^1.1.7", + "path-expression-matcher": "^1.5.0", + "strnum": "^2.2.3" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/gaxios": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.1.4.tgz", + "integrity": "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/glob": { + "version": "13.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.6.tgz", + "integrity": "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.2.2", + "minipass": "^7.1.3", + "path-scurry": "^2.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/google-auth-library": { + "version": "10.6.2", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.6.2.tgz", + "integrity": "sha512-e27Z6EThmVNNvtYASwQxose/G57rkRuaRbQyxM2bvYLLX/GqWZ5chWq2EBoUchJbCc57eC9ArzO5wMsEmWftCw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/hosted-git-info": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/lru-cache": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.4.0.tgz", + "integrity": "sha512-W+R+kFL4HgVxONq2bhXPi3bGpzGe/yEhVOp233qw9wCRtgncJ15P3bC+e4zZMu4Cq7d+WAJjXGW0uUkifhcatA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/marked": { + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.5.tgz", + "integrity": "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/openai": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.26.0.tgz", + "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/p-retry/node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/partial-json": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/partial-json/-/partial-json-0.1.7.tgz", + "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/path-expression-matcher": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz", + "integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/proper-lockfile/node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/protobufjs": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/strnum": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz", + "integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/typebox": { + "version": "1.1.38", + "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.1.38.tgz", + "integrity": "sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/undici": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.5.0.tgz", + "integrity": "sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/xml-naming": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", + "integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@earendil-works/pi-coding-agent/node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + }, + "node_modules/@earendil-works/pi-tui": { + "version": "0.81.1", + "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.81.1.tgz", + "integrity": "sha512-OMEe+Zt8oQYi/rCq3upxsTlIScWL0FPhXwQus34TbQb3EmTx88S7Uzx32JxvQiEeWOw8eDCdJf2PBUBE9r6wIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "1.6.0", + "marked": "18.0.5" + }, + "engines": { + "node": ">=22.19.0" + } + }, + "node_modules/@google/genai": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz", + "integrity": "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "google-auth-library": "^10.3.0", + "p-retry": "^4.6.2", + "protobufjs": "^7.5.4", + "ws": "^8.18.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@modelcontextprotocol/sdk": "^1.25.2" + }, + "peerDependenciesMeta": { + "@modelcontextprotocol/sdk": { + "optional": true + } + } + }, + "node_modules/@mistralai/mistralai": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-2.2.6.tgz", + "integrity": "sha512-W8pX7zHxjJvMIpw8JMxeJEleapXX0Q9NPszdNzqkM3MIEoIGPObdodujj+WHteXEvGfaP/AMwlNyRfEzSY6dQQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.40.0", + "ws": "^8.18.0", + "zod": "^3.25.0 || ^4.0.0", + "zod-to-json-schema": "^3.25.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.43.0.tgz", + "integrity": "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", + "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", + "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz", + "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@smithy/core": { + "version": "3.29.7", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.29.7.tgz", + "integrity": "sha512-BiEE2bnnGoPKdlGe3L+gOYORDHFGPuYVRLP7iUow/Sflm0B4hC4XY3FC1MRuc7ltzpW2xNnXopKi34TTkULlKQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.12.tgz", + "integrity": "sha512-ZZPDbl/aRp77aycuoMlo3BTayT4CE2a3uoqETYZU5ySnVbhpl5IJiY7dCZedn+ZusyDLqVv44IvKBiXd2/nK0Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.29.7", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "5.6.9", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.9.tgz", + "integrity": "sha512-EJktha5m5MXCwzdXrlWyqb9UCNHNFKlg+PmTpRsdX3dncJPTiqYleM9OKj2mLgdVJHR01d2tU4alG+z2NdH5rQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.29.7", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.7.3.tgz", + "integrity": "sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.24.3", + "@smithy/types": "^4.14.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.8.tgz", + "integrity": "sha512-iGBm6hIwD2MGvVRSgrjVWa4FXtXDq3akxu0DCpnkmBo0xtEHZ/siMRt7ycfZAefYr2UdywUgmGtoRLaq5u56pg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/core": "^3.29.7", + "@smithy/types": "^4.16.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", + "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@types/node": { + "version": "26.1.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", + "integrity": "sha512-nxAkRSVkN1Y0JC1W8ky/fTfkGsMmcrRsbx+3XoZE+rMOX71kLYTV7fLXpqud1GpbpP5TuffXFqfX7fH2GgZREw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~8.3.0" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bowser": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.14.1.tgz", + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/gaxios": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-7.2.0.tgz", + "integrity": "sha512-CUVb4wcYe+771XevyH6HtGmXFAGGKkIC3kswAP8Z1JCe0j80JMaTPZH930DWFrvo0atjh18Arc0pEyUCWa5bfg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^7.0.1", + "node-fetch": "^3.3.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/gcp-metadata": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-8.1.2.tgz", + "integrity": "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "gaxios": "^7.0.0", + "google-logging-utils": "^1.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/google-auth-library": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-10.9.0.tgz", + "integrity": "sha512-xtvUqvINPhTaBm7nXqlYPcrMHJPm1lCNdSovxnKKhTm+4JsvQ+KGVYJViLoH9Yxu8w+T0Qv5HubzYT9BLrppJg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "gaxios": "^7.1.4", + "gcp-metadata": "8.1.2", + "google-logging-utils": "1.1.3", + "jws": "^4.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/google-logging-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-1.1.3.tgz", + "integrity": "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/marked": { + "version": "18.0.5", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.5.tgz", + "integrity": "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/openai": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.26.0.tgz", + "integrity": "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/partial-json": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/partial-json/-/partial-json-0.1.7.tgz", + "integrity": "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA==", + "dev": true, + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", + "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.1", + "@protobufjs/fetch": "^1.1.1", + "@protobufjs/float": "^1.0.2", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.3.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typebox": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.3.6.tgz", + "integrity": "sha512-Sc8RA0NCMEFmApHNU9ZMzqcpQj46She44J8ffpLM/bdhLNUZKq7DJumcLcsFx1gRmDfQPgCgOmFFJ7rcnfWNyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz", + "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.21.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "dev": true, + "license": "ISC", + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..624de4c --- /dev/null +++ b/package.json @@ -0,0 +1,66 @@ +{ + "name": "pi-todo-herdr", + "version": "0.1.0", + "description": "Hierarchical task tools for Pi with a live widget and Herdr sidebar integration.", + "type": "module", + "main": "./index.ts", + "files": [ + "index.ts", + "src/**/*", + "README.md", + "LICENSE" + ], + "keywords": [ + "pi-package", + "pi", + "pi-extension", + "todo", + "task-management", + "herdr", + "productivity" + ], + "author": { + "name": "lesetong", + "email": "oscarlbw@qq.com", + "url": "https://github.com/leset0ng" + }, + "license": "MIT", + "homepage": "https://github.com/leset0ng/pi-todo-herdr#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/leset0ng/pi-todo-herdr.git" + }, + "bugs": { + "url": "https://github.com/leset0ng/pi-todo-herdr/issues" + }, + "engines": { + "node": ">=20" + }, + "publishConfig": { + "access": "public" + }, + "scripts": { + "test": "node --experimental-transform-types --test tests/*.test.ts", + "typecheck": "tsc --noEmit", + "prepublishOnly": "npm run typecheck && npm test" + }, + "peerDependencies": { + "@earendil-works/pi-ai": "*", + "@earendil-works/pi-coding-agent": "*", + "@earendil-works/pi-tui": "*", + "typebox": "*" + }, + "devDependencies": { + "@earendil-works/pi-ai": "^0.81.1", + "@earendil-works/pi-coding-agent": "^0.81.1", + "@earendil-works/pi-tui": "^0.81.1", + "typebox": "^1.0.13", + "typescript": "^6.0.2" + }, + "pi": { + "extensions": [ + "./index.ts" + ], + "image": "https://github.com/leset0ng/pi-todo-herdr/raw/main/media/screenshot.png" + } +} diff --git a/src/herdr.ts b/src/herdr.ts new file mode 100644 index 0000000..ebe80e0 --- /dev/null +++ b/src/herdr.ts @@ -0,0 +1,92 @@ +import net from "node:net"; +import type { Task } from "./types.ts"; +import { orderedTreeRows } from "./ui.ts"; + +const SOURCE = "pi-todo-herdr"; +const TOKEN = "task"; +let reportSeq = Date.now() * 1000; + +function nextSeq(): number { + reportSeq += 1; + return reportSeq; +} + +export function isHerdrEnvironment(): boolean { + return process.env.HERDR_ENV === "1" && !!process.env.HERDR_SOCKET_PATH && !!process.env.HERDR_PANE_ID; +} + +function hasDescendantWithStatus(task: Task, status: Task["status"], byId: Map): boolean { + for (const childId of task.childrenIds) { + const child = byId.get(childId); + if (!child) continue; + if (child.status === status || hasDescendantWithStatus(child, status, byId)) return true; + } + return false; +} + +export function currentTaskLabel(tasks: Task[]): string | null { + const byId = new Map(tasks.map((task) => [task.id, task])); + const ordered = orderedTreeRows(tasks).map(({ task }) => task); + const inProgress = ordered.filter( + (task) => task.status === "in-progress" && !hasDescendantWithStatus(task, "in-progress", byId), + ); + const candidates = + inProgress.length > 0 + ? inProgress + : ordered.filter((task) => task.status === "blocked" && !hasDescendantWithStatus(task, "blocked", byId)); + if (candidates.length === 0) return null; + const suffix = candidates.length > 1 ? ` +${candidates.length - 1}` : ""; + return `#${candidates[0]!.id} ${candidates[0]!.name}${suffix}`; +} + +function sendAttempt(request: unknown, timeoutMs: number): Promise { + if (!isHerdrEnvironment()) return Promise.resolve(true); + const socketPath = process.env.HERDR_SOCKET_PATH!; + const endpoint = process.platform === "win32" ? `\\\\.\\pipe\\${socketPath}` : socketPath; + + return new Promise((resolve) => { + let settled = false; + let timer: ReturnType | undefined; + const socket = net.createConnection(endpoint); + const finish = (delivered: boolean) => { + if (settled) return; + settled = true; + if (timer) clearTimeout(timer); + socket.destroy(); + resolve(delivered); + }; + socket.on("error", () => finish(false)); + socket.on("connect", () => socket.write(`${JSON.stringify(request)}\n`)); + socket.on("data", () => finish(true)); + socket.on("end", () => finish(false)); + timer = setTimeout(() => finish(false), timeoutMs); + timer.unref?.(); + }); +} + +async function send(request: unknown): Promise { + if (await sendAttempt(request, 500)) return; + await sendAttempt(request, 1500); +} + +async function reportToken(value: string | null): Promise { + if (!isHerdrEnvironment()) return; + await send({ + id: `${SOURCE}:${Date.now()}:${Math.random().toString(36).slice(2)}`, + method: "pane.report_metadata", + params: { + pane_id: process.env.HERDR_PANE_ID, + source: SOURCE, + tokens: { [TOKEN]: value }, + seq: nextSeq(), + }, + }); +} + +export function reportCurrentTask(tasks: Task[]): Promise { + return reportToken(currentTaskLabel(tasks)); +} + +export function clearCurrentTask(): Promise { + return reportToken(null); +} diff --git a/src/state.ts b/src/state.ts new file mode 100644 index 0000000..f76b148 --- /dev/null +++ b/src/state.ts @@ -0,0 +1,343 @@ +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { + AddTaskDraft, + Task, + TaskPatch, + TaskSnapshot, + TaskStats, + TaskStatus, + TaskToolDetails, +} from "./types.ts"; +import { TaskValidationError } from "./types.ts"; + +const MUTATION_TOOLS = new Set(["add_task", "update_task", "rm_task"]); +const VALID_STATUSES = new Set(["pending", "in-progress", "blocked", "done"]); + +interface TaskRecord { + id: number; + name: string; + description: string; + status: TaskStatus; + parentId: number | null; +} + +function cloneRecords(records: TaskRecord[]): TaskRecord[] { + return records.map((task) => ({ ...task })); +} + +function indexRecords(records: TaskRecord[]): Map { + return new Map(records.map((task) => [task.id, task])); +} + +function childIds(records: TaskRecord[], parentId: number | null): number[] { + return records.filter((task) => task.parentId === parentId).map((task) => task.id); +} + +function publicTasks(records: TaskRecord[]): Task[] { + return records.map((task) => ({ + ...task, + childrenIds: childIds(records, task.id), + })); +} + +function collectDescendantIds(records: TaskRecord[], rootId: number): number[] { + const result: number[] = []; + const visit = (id: number) => { + for (const childId of childIds(records, id)) { + result.push(childId); + visit(childId); + } + }; + visit(rootId); + return result; +} + +function validateGraph(records: TaskRecord[]): string[] { + const errors: string[] = []; + const byId = indexRecords(records); + const ids = new Set(); + + for (const task of records) { + if (!Number.isInteger(task.id) || task.id < 1) errors.push(`task ${task.id}: id must be a positive integer`); + if (ids.has(task.id)) errors.push(`task ${task.id}: duplicate id`); + ids.add(task.id); + if (!task.name.trim()) errors.push(`task ${task.id}: name must not be empty`); + if (/[\r\n]/.test(task.name)) errors.push(`task ${task.id}: name must be a single line`); + if (!task.description.trim()) errors.push(`task ${task.id}: description must not be empty`); + if (!VALID_STATUSES.has(task.status)) errors.push(`task ${task.id}: invalid status '${task.status}'`); + if (task.parentId !== null && !byId.has(task.parentId)) { + errors.push(`task ${task.id}: parent ${task.parentId} does not exist`); + } + } + + const visiting = new Set(); + const visited = new Set(); + const visit = (id: number): boolean => { + if (visiting.has(id)) return true; + if (visited.has(id)) return false; + visiting.add(id); + const parentId = byId.get(id)?.parentId; + if (parentId !== null && parentId !== undefined && visit(parentId)) return true; + visiting.delete(id); + visited.add(id); + return false; + }; + + for (const task of records) { + if (visit(task.id)) { + errors.push(`task ${task.id}: parentId creates a cycle`); + break; + } + } + + if (errors.length > 0) return errors; + + for (const task of records) { + if (task.status !== "done") continue; + const unfinished = collectDescendantIds(records, task.id).filter((id) => byId.get(id)?.status !== "done"); + if (unfinished.length > 0) { + errors.push(`task ${task.id}: done task has unfinished descendants ${unfinished.join(", ")}`); + } + } + + return errors; +} + +function insertAtSiblingPosition(records: TaskRecord[], id: number, position: number): string | undefined { + const byId = indexRecords(records); + const task = byId.get(id); + if (!task) return `task ${id}: does not exist`; + + const siblings = childIds(records, task.parentId).filter((siblingId) => siblingId !== id); + if (!Number.isInteger(position) || position < 0 || position > siblings.length) { + return `task ${id}: position must be between 0 and ${siblings.length}`; + } + + const recordIndex = records.findIndex((record) => record.id === id); + const [record] = records.splice(recordIndex, 1); + if (!record) return `task ${id}: does not exist`; + + if (position < siblings.length) { + const targetIndex = records.findIndex((candidate) => candidate.id === siblings[position]); + records.splice(targetIndex, 0, record); + return; + } + + if (siblings.length === 0) { + records.push(record); + return; + } + + const lastSiblingIndex = records.findIndex((candidate) => candidate.id === siblings[siblings.length - 1]); + records.splice(lastSiblingIndex + 1, 0, record); +} + +function moveToSiblingEnd(records: TaskRecord[], id: number): void { + const task = records.find((candidate) => candidate.id === id); + if (!task) return; + const siblings = childIds(records, task.parentId).filter((siblingId) => siblingId !== id); + const currentIndex = records.findIndex((candidate) => candidate.id === id); + const [record] = records.splice(currentIndex, 1); + if (!record) return; + if (siblings.length === 0) { + records.push(record); + return; + } + const lastSiblingIndex = records.findIndex((candidate) => candidate.id === siblings[siblings.length - 1]); + records.splice(lastSiblingIndex + 1, 0, record); +} + +export class TaskState { + private records: TaskRecord[] = []; + private nextId = 1; + + list(): Task[] { + return publicTasks(this.records); + } + + get(ids: number[]): Task[] { + const byId = new Map(this.list().map((task) => [task.id, task])); + return ids.map((id) => byId.get(id)).filter((task): task is Task => task !== undefined); + } + + snapshot(): TaskSnapshot { + return { tasks: this.list(), nextId: this.nextId }; + } + + stats(): TaskStats { + const tasks = this.records; + return { + total: tasks.length, + pending: tasks.filter((task) => task.status === "pending").length, + inProgress: tasks.filter((task) => task.status === "in-progress").length, + blocked: tasks.filter((task) => task.status === "blocked").length, + done: tasks.filter((task) => task.status === "done").length, + }; + } + + add(drafts: AddTaskDraft[]): Task[] { + const errors: string[] = []; + if (!Array.isArray(drafts) || drafts.length === 0) throw new TaskValidationError(["tasks must not be empty"]); + + const working = cloneRecords(this.records); + const existingIds = new Set(working.map((task) => task.id)); + let nextId = this.nextId; + const addedIds: number[] = []; + + const append = (draft: AddTaskDraft, implicitParentId: number | null, path: string, nested: boolean) => { + if (!draft || typeof draft !== "object") { + errors.push(`${path}: task must be an object`); + return; + } + if (typeof draft.name !== "string" || !draft.name.trim()) errors.push(`${path}.name must not be empty`); + if (typeof draft.name === "string" && /[\r\n]/.test(draft.name)) errors.push(`${path}.name must be a single line`); + if (typeof draft.description !== "string" || !draft.description.trim()) { + errors.push(`${path}.description must not be empty`); + } + if (draft.status !== undefined && !VALID_STATUSES.has(draft.status)) { + errors.push(`${path}.status is invalid`); + } + if (nested && draft.parentId !== undefined) errors.push(`${path}.parentId is not allowed inside children`); + if (draft.children !== undefined && !Array.isArray(draft.children)) errors.push(`${path}.children must be an array`); + + let parentId = implicitParentId; + if (!nested && draft.parentId !== undefined) { + if (!Number.isInteger(draft.parentId) || !existingIds.has(draft.parentId)) { + errors.push(`${path}.parentId ${draft.parentId} does not exist`); + } else { + parentId = draft.parentId; + } + } + + const id = nextId++; + addedIds.push(id); + working.push({ + id, + name: typeof draft.name === "string" ? draft.name.trim() : "", + description: typeof draft.description === "string" ? draft.description.trim() : "", + status: draft.status ?? "pending", + parentId, + }); + + for (const [index, child] of (draft.children ?? []).entries()) { + append(child, id, `${path}.children[${index}]`, true); + } + }; + + drafts.forEach((draft, index) => append(draft, null, `tasks[${index}]`, false)); + errors.push(...validateGraph(working)); + if (errors.length > 0) throw new TaskValidationError([...new Set(errors)]); + + this.records = working; + this.nextId = nextId; + return this.get(addedIds); + } + + update(patches: TaskPatch[]): Task[] { + const errors: string[] = []; + if (!Array.isArray(patches) || patches.length === 0) throw new TaskValidationError(["tasks must not be empty"]); + + const duplicateIds = patches + .map((patch) => patch.id) + .filter((id, index, ids) => ids.indexOf(id) !== index); + if (duplicateIds.length > 0) errors.push(`duplicate task patches: ${[...new Set(duplicateIds)].join(", ")}`); + + const working = cloneRecords(this.records); + for (const [index, patch] of patches.entries()) { + const path = `tasks[${index}]`; + const task = working.find((candidate) => candidate.id === patch.id); + if (!task) { + errors.push(`${path}.id ${patch.id} does not exist`); + continue; + } + + const hasChange = ["name", "description", "status", "parentId", "position"].some((key) => + Object.prototype.hasOwnProperty.call(patch, key), + ); + if (!hasChange) errors.push(`${path} must include at least one field to update`); + if (patch.name !== undefined && (typeof patch.name !== "string" || !patch.name.trim())) { + errors.push(`${path}.name must not be empty`); + } + if (typeof patch.name === "string" && /[\r\n]/.test(patch.name)) errors.push(`${path}.name must be a single line`); + if (patch.description !== undefined && (typeof patch.description !== "string" || !patch.description.trim())) { + errors.push(`${path}.description must not be empty`); + } + if (patch.status !== undefined && !VALID_STATUSES.has(patch.status)) errors.push(`${path}.status is invalid`); + if (patch.parentId !== undefined && patch.parentId !== null) { + if (!Number.isInteger(patch.parentId) || !working.some((candidate) => candidate.id === patch.parentId)) { + errors.push(`${path}.parentId ${patch.parentId} does not exist`); + } + } + + if (patch.name !== undefined) task.name = patch.name.trim(); + if (patch.description !== undefined) task.description = patch.description.trim(); + if (patch.status !== undefined) task.status = patch.status; + if (patch.parentId !== undefined && (patch.parentId === null || working.some((item) => item.id === patch.parentId))) { + task.parentId = patch.parentId; + moveToSiblingEnd(working, task.id); + } + if (patch.position !== undefined) { + const positionError = insertAtSiblingPosition(working, task.id, patch.position); + if (positionError) errors.push(`${path}.position: ${positionError}`); + } + } + + errors.push(...validateGraph(working)); + if (errors.length > 0) throw new TaskValidationError([...new Set(errors)]); + + this.records = working; + return this.get(patches.map((patch) => patch.id)); + } + + remove(ids: number[]): Task[] { + if (!Array.isArray(ids) || ids.length === 0) throw new TaskValidationError(["ids must not be empty"]); + const uniqueIds = [...new Set(ids)]; + const missing = uniqueIds.filter((id) => !this.records.some((task) => task.id === id)); + if (missing.length > 0) throw new TaskValidationError([`task ids do not exist: ${missing.join(", ")}`]); + + const removedIds = new Set(); + for (const id of uniqueIds) { + removedIds.add(id); + for (const descendantId of collectDescendantIds(this.records, id)) removedIds.add(descendantId); + } + const removed = this.list().filter((task) => removedIds.has(task.id)); + this.records = this.records.filter((task) => !removedIds.has(task.id)); + return removed; + } + + restore(snapshot: TaskSnapshot): void { + if (!snapshot || !Array.isArray(snapshot.tasks) || !Number.isInteger(snapshot.nextId)) { + throw new TaskValidationError(["invalid task snapshot"]); + } + const records = snapshot.tasks.map(({ id, name, description, status, parentId }) => ({ + id, + name, + description, + status, + parentId, + })); + const errors = validateGraph(records); + const maxId = records.reduce((max, task) => Math.max(max, task.id), 0); + if (snapshot.nextId <= maxId) errors.push(`nextId must be greater than ${maxId}`); + if (errors.length > 0) throw new TaskValidationError(errors); + this.records = cloneRecords(records); + this.nextId = snapshot.nextId; + } + + loadFromSession(ctx: ExtensionContext): void { + this.records = []; + this.nextId = 1; + for (const entry of ctx.sessionManager.getBranch()) { + if (entry.type !== "message") continue; + const message = entry.message; + if (message.role !== "toolResult" || !MUTATION_TOOLS.has(message.toolName)) continue; + const details = message.details as TaskToolDetails | undefined; + if (!details?.snapshot) continue; + try { + this.restore(details.snapshot); + } catch { + // Ignore corrupt historical snapshots and keep the latest valid state. + } + } + } +} diff --git a/src/tools.ts b/src/tools.ts new file mode 100644 index 0000000..4dba867 --- /dev/null +++ b/src/tools.ts @@ -0,0 +1,259 @@ +import { StringEnum } from "@earendil-works/pi-ai"; +import type { ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent"; +import { Text } from "@earendil-works/pi-tui"; +import { Type } from "typebox"; +import type { TaskState } from "./state.ts"; +import type { AddTaskDraft, Task, TaskPatch, TaskToolDetails } from "./types.ts"; +import { TaskValidationError } from "./types.ts"; +import { orderedTreeRows, renderToolResult } from "./ui.ts"; + +const TaskStatusSchema = StringEnum(["pending", "in-progress", "blocked", "done"] as const, { + description: "Task status. Defaults to pending when omitted during add.", +}); + +const AddTaskSchema = Type.Cyclic( + { + AddTask: Type.Object( + { + name: Type.String({ minLength: 1 }), + description: Type.String({ minLength: 1 }), + status: Type.Optional(TaskStatusSchema), + parentId: Type.Optional( + Type.Integer({ minimum: 1, description: "Existing parent ID. Allowed only on top-level tasks." }), + ), + children: Type.Optional(Type.Array(Type.Ref("AddTask"))), + }, + { additionalProperties: false }, + ), + }, + "AddTask", +); + +export const AddTaskParams = Type.Object( + { + tasks: Type.Array(AddTaskSchema, { minItems: 1, description: "Tasks to add in one atomic batch." }), + }, + { additionalProperties: false }, +); + +const TaskPatchSchema = Type.Object( + { + id: Type.Integer({ minimum: 1 }), + name: Type.Optional(Type.String({ minLength: 1 })), + description: Type.Optional(Type.String({ minLength: 1 })), + status: Type.Optional(TaskStatusSchema), + parentId: Type.Optional( + Type.Union([Type.Integer({ minimum: 1 }), Type.Null()], { + description: "New parent ID, or null to move the task to the root.", + }), + ), + position: Type.Optional( + Type.Integer({ minimum: 0, description: "Zero-based insertion index among the task's final siblings." }), + ), + }, + { additionalProperties: false }, +); + +export const UpdateTaskParams = Type.Object( + { + tasks: Type.Array(TaskPatchSchema, { minItems: 1, description: "Task patches applied atomically in array order." }), + }, + { additionalProperties: false }, +); + +export const IdsParams = Type.Object( + { + ids: Type.Array(Type.Integer({ minimum: 1 }), { + minItems: 1, + description: "Task IDs to process in one call. Duplicate IDs are deduplicated.", + }), + }, + { additionalProperties: false }, +); + +export const ListTaskParams = Type.Object({}, { additionalProperties: false }); + +interface AddTaskInput { + tasks: AddTaskDraft[]; +} + +interface UpdateTaskInput { + tasks: TaskPatch[]; +} + +interface IdsInput { + ids: number[]; +} + +type ChangeHandler = (ctx: ExtensionContext) => void; + +function taskIds(tasks: Task[]): string { + return tasks.map((task) => task.id).join(", "); +} + +function compactTree(tasks: Task[]): string { + if (tasks.length === 0) return "No tasks."; + return orderedTreeRows(tasks) + .map(({ task, prefix }) => `${prefix}${task.id} [${task.status}] ${task.name}`) + .join("\n"); +} + +function details(action: TaskToolDetails["action"], state: TaskState, affected: Task[]): TaskToolDetails { + return { action, snapshot: state.snapshot(), affected }; +} + +function mutationText(verb: string, affected: Task[], state: TaskState): string { + const stats = state.stats(); + return `${verb} ${affected.length} task${affected.length === 1 ? "" : "s"}: ${taskIds(affected)}. ${stats.done}/${stats.total} done.`; +} + +function throwToolError(label: string, error: unknown): never { + if (error instanceof TaskValidationError) { + const count = error.errors.length; + throw new Error( + `${label} failed · ${count} validation error${count === 1 ? "" : "s"}\n${error.errors.map((item) => `- ${item}`).join("\n")}`, + ); + } + throw error; +} + +function renderCall(title: string, count: number | undefined, theme: Theme): Text { + const suffix = count === undefined ? "" : theme.fg("dim", ` (${count})`); + return new Text(theme.fg("toolTitle", theme.bold(title)) + suffix, 0, 0); +} + +function notifyChange(onChange: ChangeHandler, ctx: ExtensionContext): void { + try { + onChange(ctx); + } catch (error) { + console.error("[pi-todo-herdr] failed to refresh task UI:", error); + } +} + +export function registerTaskTools(pi: ExtensionAPI, state: TaskState, onChange: ChangeHandler): void { + pi.registerTool({ + name: "add_task", + label: "Add Tasks", + description: + "Atomically add one or more tasks. Use nested children for new descendants and parentId on top-level items for an existing parent.", + promptGuidelines: [ + "Use add_task for complex multi-step work; use update_task immediately when tasks start, block, resume, or finish; skip task tracking for simple one-step work.", + ], + parameters: AddTaskParams, + async execute(_toolCallId, params: AddTaskInput, _signal, _onUpdate, ctx) { + try { + const affected = state.add(params.tasks); + notifyChange(onChange, ctx); + return { + content: [{ type: "text" as const, text: mutationText("Added", affected, state) }], + details: details("add", state, affected), + }; + } catch (error) { + throwToolError("Add", error); + } + }, + renderCall(args: AddTaskInput, theme: Theme) { + return renderCall("Add Tasks", args.tasks?.length, theme); + }, + renderResult(result, { expanded }, theme) { + return renderToolResult(result, expanded, theme); + }, + }); + + pi.registerTool({ + name: "update_task", + label: "Update Tasks", + description: + "Atomically patch one or more tasks. Fields are optional except id; parentId null moves to root and position is a zero-based sibling index.", + parameters: UpdateTaskParams, + async execute(_toolCallId, params: UpdateTaskInput, _signal, _onUpdate, ctx) { + try { + const affected = state.update(params.tasks); + notifyChange(onChange, ctx); + return { + content: [{ type: "text" as const, text: mutationText("Updated", affected, state) }], + details: details("update", state, affected), + }; + } catch (error) { + throwToolError("Update", error); + } + }, + renderCall(args: UpdateTaskInput, theme: Theme) { + return renderCall("Update Tasks", args.tasks?.length, theme); + }, + renderResult(result, { expanded }, theme) { + return renderToolResult(result, expanded, theme); + }, + }); + + pi.registerTool({ + name: "rm_task", + label: "Remove Tasks", + description: "Atomically remove multiple task IDs. Removing a parent also removes its entire descendant subtree.", + parameters: IdsParams, + async execute(_toolCallId, params: IdsInput, _signal, _onUpdate, ctx) { + try { + const affected = state.remove(params.ids); + notifyChange(onChange, ctx); + return { + content: [{ type: "text" as const, text: mutationText("Removed", affected, state) }], + details: details("remove", state, affected), + }; + } catch (error) { + throwToolError("Remove", error); + } + }, + renderCall(args: IdsInput, theme: Theme) { + return renderCall("Remove Tasks", args.ids?.length, theme); + }, + renderResult(result, { expanded }, theme) { + return renderToolResult(result, expanded, theme); + }, + }); + + pi.registerTool({ + name: "list_task", + label: "List Tasks", + description: "List the full task tree compactly with id, name, and status.", + parameters: ListTaskParams, + async execute() { + const affected = state.list(); + return { + content: [{ type: "text" as const, text: compactTree(affected) }], + details: details("list", state, affected), + }; + }, + renderCall(_args, theme: Theme) { + return renderCall("List Tasks", undefined, theme); + }, + renderResult(result, { expanded }, theme) { + return renderToolResult(result, expanded, theme); + }, + }); + + pi.registerTool({ + name: "get_task", + label: "Get Tasks", + description: "Get complete details for one or more task IDs, including parent and child IDs.", + parameters: IdsParams, + async execute(_toolCallId, params: IdsInput) { + const uniqueIds = [...new Set(params.ids)]; + const affected = state.get(uniqueIds); + const found = new Set(affected.map((task) => task.id)); + const missing = uniqueIds.filter((id) => !found.has(id)); + if (missing.length > 0) { + throwToolError("Get", new TaskValidationError([`task ids do not exist: ${missing.join(", ")}`])); + } + return { + content: [{ type: "text" as const, text: JSON.stringify(affected) }], + details: details("get", state, affected), + }; + }, + renderCall(args: IdsInput, theme: Theme) { + return renderCall("Get Tasks", args.ids?.length, theme); + }, + renderResult(result, { expanded }, theme) { + return renderToolResult(result, expanded, theme); + }, + }); +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..71c1ff3 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,57 @@ +export type TaskStatus = "pending" | "in-progress" | "blocked" | "done"; + +export interface Task { + id: number; + name: string; + description: string; + status: TaskStatus; + parentId: number | null; + childrenIds: number[]; +} + +export interface TaskSnapshot { + tasks: Task[]; + nextId: number; +} + +export interface AddTaskDraft { + name: string; + description: string; + status?: TaskStatus; + parentId?: number; + children?: AddTaskDraft[]; +} + +export interface TaskPatch { + id: number; + name?: string; + description?: string; + status?: TaskStatus; + parentId?: number | null; + position?: number; +} + +export interface TaskStats { + total: number; + pending: number; + inProgress: number; + blocked: number; + done: number; +} + +export interface TaskToolDetails { + action: "add" | "update" | "remove" | "list" | "get"; + snapshot: TaskSnapshot; + affected: Task[]; + errors?: string[]; +} + +export class TaskValidationError extends Error { + readonly errors: string[]; + + constructor(errors: string[]) { + super(errors.join("\n")); + this.name = "TaskValidationError"; + this.errors = errors; + } +} diff --git a/src/ui.ts b/src/ui.ts new file mode 100644 index 0000000..2c88393 --- /dev/null +++ b/src/ui.ts @@ -0,0 +1,174 @@ +import type { Component } from "@earendil-works/pi-tui"; +import { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui"; +import type { Theme } from "@earendil-works/pi-coding-agent"; +import type { Task, TaskStats, TaskToolDetails } from "./types.ts"; + +export const STATUS_ICONS = { + pending: "○", + "in-progress": "◉", + blocked: "!", + done: "✓", +} as const; + +interface TreeRow { + task: Task; + prefix: string; +} + +export function orderedTreeRows(tasks: Task[]): TreeRow[] { + const byId = new Map(tasks.map((task) => [task.id, task])); + const rows: TreeRow[] = []; + + const visit = (task: Task, ancestorHasNext: boolean[], isLast: boolean, depth: number) => { + const ancestors = ancestorHasNext.map((hasNext) => (hasNext ? "│ " : " ")).join(""); + const connector = depth === 0 ? "" : isLast ? "└─ " : "├─ "; + rows.push({ task, prefix: `${ancestors}${connector}` }); + const children = task.childrenIds.map((id) => byId.get(id)).filter((child): child is Task => child !== undefined); + children.forEach((child, index) => { + const childAncestors = depth === 0 ? [] : [...ancestorHasNext, !isLast]; + visit(child, childAncestors, index === children.length - 1, depth + 1); + }); + }; + + const roots = tasks.filter((task) => task.parentId === null); + roots.forEach((root, index) => visit(root, [], index === roots.length - 1, 0)); + return rows; +} + +function styleTaskName(task: Task, theme: Theme): string { + if (task.status === "done") return theme.fg("dim", theme.strikethrough(task.name)); + if (task.status === "in-progress") return theme.fg("warning", task.name); + return task.name; +} + +function styleStatusIcon(task: Task, theme: Theme): string { + const icon = STATUS_ICONS[task.status]; + if (task.status === "done") return theme.fg("success", icon); + if (task.status === "in-progress") return theme.fg("warning", icon); + if (task.status === "blocked") return theme.fg("error", icon); + return theme.fg("dim", icon); +} + +export function renderTaskLine(task: Task, prefix: string, theme: Theme, width: number): string { + const line = + theme.fg("dim", prefix) + + styleStatusIcon(task, theme) + + " " + + theme.fg("accent", `${task.id}.`) + + " " + + styleTaskName(task, theme); + return truncateToWidth(line, Math.max(1, width)); +} + +export function renderTree(tasks: Task[], theme: Theme, width: number, padding = " "): string[] { + return orderedTreeRows(tasks).map(({ task, prefix }) => renderTaskLine(task, `${padding}${prefix}`, theme, width)); +} + +export function progressLabel(stats: TaskStats): string { + const blocked = stats.blocked > 0 ? ` · !${stats.blocked}` : ""; + return ` Tasks ${stats.done}/${stats.total}${blocked}`; +} + +export function renderProgressHeader(stats: TaskStats, theme: Theme, width: number): string { + const label = progressLabel(stats); + const available = width - visibleWidth(label) - 2; + if (available < 5) return truncateToWidth(theme.fg("accent", label), Math.max(1, width)); + + const barWidth = Math.min(20, available); + const filled = stats.total === 0 ? 0 : Math.round((stats.done / stats.total) * barWidth); + const filledColor = stats.done === stats.total ? "success" : "accent"; + const bar = + theme.fg(filledColor, theme.bold("━".repeat(filled))) + theme.fg("dim", "─".repeat(barWidth - filled)); + return truncateToWidth(`${theme.fg("accent", label)} ${bar}`, Math.max(1, width)); +} + +class TaskResultComponent implements Component { + constructor( + private readonly build: (width: number) => string[], + ) {} + + render(width: number): string[] { + return this.build(Math.max(1, width)).map((line) => truncateToWidth(line, Math.max(1, width))); + } + + invalidate(): void {} +} + +function firstText(content: Array<{ type: string; text?: string }>): string { + return content.find((item) => item.type === "text")?.text ?? ""; +} + +function summaryFor(details: TaskToolDetails): string { + const stats = snapshotStats(details.snapshot.tasks); + const progress = `${stats.done}/${stats.total} done`; + switch (details.action) { + case "add": + return `${details.affected.length} added · ${progress}`; + case "update": + return `${details.affected.length} updated · ${progress}`; + case "remove": + return `${details.affected.length} removed · ${progress}`; + case "list": + return `${stats.total} task${stats.total === 1 ? "" : "s"} · ${progress}`; + case "get": + return `${details.affected.length} task${details.affected.length === 1 ? "" : "s"}`; + } +} + +export function snapshotStats(tasks: Task[]): TaskStats { + return { + total: tasks.length, + pending: tasks.filter((task) => task.status === "pending").length, + inProgress: tasks.filter((task) => task.status === "in-progress").length, + blocked: tasks.filter((task) => task.status === "blocked").length, + done: tasks.filter((task) => task.status === "done").length, + }; +} + +function renderFlatTasks(tasks: Task[], theme: Theme, width: number): string[] { + return tasks.map((task) => renderTaskLine(task, " ", theme, width)); +} + +function renderTaskDetails(tasks: Task[], theme: Theme, width: number): string[] { + const lines: string[] = []; + for (const [index, task] of tasks.entries()) { + if (index > 0) lines.push(""); + lines.push(renderTaskLine(task, " ", theme, width)); + const parent = task.parentId === null ? "root" : `#${task.parentId}`; + const children = task.childrenIds.length === 0 ? "none" : task.childrenIds.map((id) => `#${id}`).join(", "); + lines.push(truncateToWidth(theme.fg("dim", ` Parent ${parent} · Children ${children}`), width)); + const prefix = " "; + const descriptionWidth = Math.max(1, width - visibleWidth(prefix)); + for (const sourceLine of task.description.split("\n")) { + const wrapped = wrapTextWithAnsi(theme.fg("muted", sourceLine), descriptionWidth); + if (wrapped.length === 0) lines.push(prefix); + else lines.push(...wrapped.map((line) => `${prefix}${line}`)); + } + } + return lines; +} + +export function renderToolResult( + result: { content: Array<{ type: string; text?: string }>; details?: unknown; isError?: boolean }, + expanded: boolean, + theme: Theme, +): Component { + const raw = firstText(result.content); + const details = result.details as TaskToolDetails | undefined; + + if (result.isError || !details) { + const rawLines = raw.split("\n").filter(Boolean); + return new TaskResultComponent((width) => { + const lines = expanded ? rawLines : rawLines.slice(0, 1); + return lines.map((line, index) => theme.fg("error", `${index === 0 ? "✗ " : " "}${line}`)); + }); + } + + return new TaskResultComponent((width) => { + const lines = [theme.fg("success", "✓ ") + theme.fg("muted", summaryFor(details))]; + if (!expanded || details.affected.length === 0) return lines; + if (details.action === "list") return [...lines, ...renderTree(details.snapshot.tasks, theme, width)]; + if (details.action === "get") return [...lines, ...renderTaskDetails(details.affected, theme, width)]; + return [...lines, ...renderFlatTasks(details.affected, theme, width)]; + }); +} diff --git a/src/widget.ts b/src/widget.ts new file mode 100644 index 0000000..51b6c89 --- /dev/null +++ b/src/widget.ts @@ -0,0 +1,25 @@ +import type { ExtensionContext } from "@earendil-works/pi-coding-agent"; +import type { TaskState } from "./state.ts"; +import { renderProgressHeader, renderTree } from "./ui.ts"; + +const WIDGET_ID = "pi-todo-herdr"; + +export function clearTaskWidget(ctx: ExtensionContext): void { + ctx.ui.setWidget(WIDGET_ID, undefined); +} + +export function updateTaskWidget(state: TaskState, ctx: ExtensionContext, visible: boolean): void { + const tasks = state.list(); + if (!visible || tasks.length === 0) { + clearTaskWidget(ctx); + return; + } + + const stats = state.stats(); + ctx.ui.setWidget(WIDGET_ID, (_tui, theme) => ({ + render(width: number): string[] { + return [renderProgressHeader(stats, theme, width), ...renderTree(tasks, theme, width)]; + }, + invalidate(): void {}, + })); +} diff --git a/tests/state.test.ts b/tests/state.test.ts new file mode 100644 index 0000000..7c5dcfe --- /dev/null +++ b/tests/state.test.ts @@ -0,0 +1,178 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { TaskState } from "../src/state.ts"; +import { TaskValidationError } from "../src/types.ts"; + +function names(state: TaskState): string[] { + return state.list().filter((task) => task.parentId === null).map((task) => task.name); +} + +test("adds a nested batch with generated preorder IDs and derived relations", () => { + const state = new TaskState(); + const added = state.add([ + { + name: "Parent", + description: "Parent description", + children: [ + { name: "First child", description: "First" }, + { name: "Second child", description: "Second", status: "blocked" }, + ], + }, + ]); + + assert.deepEqual(added.map((task) => task.id), [1, 2, 3]); + assert.deepEqual(state.get([1])[0]?.childrenIds, [2, 3]); + assert.equal(state.get([2])[0]?.parentId, 1); + assert.equal(state.get([2])[0]?.status, "pending"); + assert.equal(state.snapshot().nextId, 4); +}); + +test("rejects invalid nested parentId atomically", () => { + const state = new TaskState(); + state.add([{ name: "Existing", description: "Existing" }]); + const before = state.snapshot(); + + assert.throws( + () => + state.add([ + { + name: "Parent", + description: "Parent", + children: [{ name: "Child", description: "Child", parentId: 1 }], + }, + ]), + TaskValidationError, + ); + assert.deepEqual(state.snapshot(), before); +}); + +test("enforces done descendants against the final atomic update state", () => { + const state = new TaskState(); + state.add([{ name: "Parent", description: "Parent", children: [{ name: "Child", description: "Child" }] }]); + const before = state.snapshot(); + + assert.throws(() => state.update([{ id: 1, status: "done" }]), /unfinished descendants/); + assert.deepEqual(state.snapshot(), before); + + state.update([ + { id: 2, status: "done" }, + { id: 1, status: "done" }, + ]); + assert.deepEqual(state.list().map((task) => task.status), ["done", "done"]); + + assert.throws(() => state.update([{ id: 2, status: "in-progress" }]), /unfinished descendants/); + state.update([ + { id: 1, status: "in-progress" }, + { id: 2, status: "in-progress" }, + ]); + assert.deepEqual(state.list().map((task) => task.status), ["in-progress", "in-progress"]); +}); + +test("rejects cycles and duplicate patches without partial changes", () => { + const state = new TaskState(); + state.add([{ name: "Root", description: "Root", children: [{ name: "Child", description: "Child" }] }]); + const before = state.snapshot(); + + assert.throws(() => state.update([{ id: 1, parentId: 2 }, { id: 2, name: "Changed" }]), /cycle/); + assert.deepEqual(state.snapshot(), before); + + assert.throws(() => state.update([{ id: 2, name: "One" }, { id: 2, name: "Two" }]), /duplicate task patches/); + assert.deepEqual(state.snapshot(), before); +}); + +test("reorders roots with zero-based sequential positions", () => { + const state = new TaskState(); + state.add([ + { name: "A", description: "A" }, + { name: "B", description: "B" }, + { name: "C", description: "C" }, + ]); + + state.update([{ id: 1, position: 2 }]); + assert.deepEqual(names(state), ["B", "C", "A"]); + + state.update([ + { id: 1, position: 0 }, + { id: 2, position: 2 }, + ]); + assert.deepEqual(names(state), ["A", "C", "B"]); +}); + +test("reparents and positions tasks among their final siblings", () => { + const state = new TaskState(); + state.add([ + { + name: "One", + description: "One", + children: [ + { name: "A", description: "A" }, + { name: "B", description: "B" }, + ], + }, + { name: "Two", description: "Two", children: [{ name: "C", description: "C" }] }, + ]); + + state.update([{ id: 3, parentId: 4, position: 0 }]); + assert.deepEqual(state.get([4])[0]?.childrenIds, [3, 5]); + assert.deepEqual(state.get([1])[0]?.childrenIds, [2]); +}); + +test("removes overlapping parent and child IDs as one cascade", () => { + const state = new TaskState(); + state.add([ + { + name: "Root", + description: "Root", + children: [{ name: "Child", description: "Child", children: [{ name: "Leaf", description: "Leaf" }] }], + }, + { name: "Keep", description: "Keep" }, + ]); + + const removed = state.remove([1, 2, 1]); + assert.deepEqual(removed.map((task) => task.id), [1, 2, 3]); + assert.deepEqual(state.list().map((task) => task.id), [4]); + assert.equal(state.snapshot().nextId, 5); + + const before = state.snapshot(); + assert.throws(() => state.remove([999]), /do not exist/); + assert.deepEqual(state.snapshot(), before); +}); + +test("restores snapshots and never reuses deleted IDs", () => { + const state = new TaskState(); + state.add([{ name: "One", description: "One" }, { name: "Two", description: "Two" }]); + state.remove([2]); + const snapshot = state.snapshot(); + + const restored = new TaskState(); + restored.restore(snapshot); + const added = restored.add([{ name: "Three", description: "Three" }]); + assert.equal(added[0]?.id, 3); +}); + +test("loads the latest valid mutation snapshot from a session branch", () => { + const first = new TaskState(); + first.add([{ name: "First", description: "First" }]); + const second = new TaskState(); + second.restore(first.snapshot()); + second.add([{ name: "Second", description: "Second" }]); + + const branch = [first.snapshot(), second.snapshot()].map((snapshot, index) => ({ + type: "message", + message: { + role: "toolResult", + toolName: index === 0 ? "add_task" : "update_task", + details: { action: "add", snapshot, affected: [] }, + }, + })); + const state = new TaskState(); + state.loadFromSession({ sessionManager: { getBranch: () => branch } } as never); + assert.deepEqual(state.list().map((task) => task.name), ["First", "Second"]); +}); + +test("rejects multiline names while allowing multiline descriptions", () => { + const state = new TaskState(); + assert.throws(() => state.add([{ name: "Bad\nname", description: "Valid" }]), /single line/); + state.add([{ name: "Valid", description: "Line one\nLine two" }]); + assert.equal(state.list()[0]?.description, "Line one\nLine two"); +}); diff --git a/tests/tools.test.ts b/tests/tools.test.ts new file mode 100644 index 0000000..b0185bb --- /dev/null +++ b/tests/tools.test.ts @@ -0,0 +1,75 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { TaskState } from "../src/state.ts"; +import { registerTaskTools } from "../src/tools.ts"; + +function registeredTools(state = new TaskState()) { + const tools = new Map(); + let changes = 0; + const pi = { + registerTool(tool: any) { + tools.set(tool.name, tool); + }, + }; + registerTaskTools(pi as never, state, () => { + changes += 1; + }); + return { tools, state, changes: () => changes }; +} + +async function execute(tool: any, params: unknown) { + return tool.execute("call", params, undefined, undefined, {}); +} + +test("registers the five requested tools with minimal top-level parameters", () => { + const { tools } = registeredTools(); + assert.deepEqual([...tools.keys()], ["add_task", "update_task", "rm_task", "list_task", "get_task"]); + assert.deepEqual(Object.keys(tools.get("add_task").parameters.properties), ["tasks"]); + assert.deepEqual(Object.keys(tools.get("update_task").parameters.properties), ["tasks"]); + assert.deepEqual(Object.keys(tools.get("rm_task").parameters.properties), ["ids"]); + assert.deepEqual(Object.keys(tools.get("list_task").parameters.properties), []); + assert.deepEqual(Object.keys(tools.get("get_task").parameters.properties), ["ids"]); +}); + +test("mutations return compact content and complete persistence snapshots", async () => { + const harness = registeredTools(); + const result = await execute(harness.tools.get("add_task"), { + tasks: [{ name: "Parent", description: "Parent", children: [{ name: "Child", description: "Child" }] }], + }); + + assert.equal(result.content[0].text, "Added 2 tasks: 1, 2. 0/2 done."); + assert.equal(result.details.snapshot.tasks.length, 2); + assert.equal(result.details.snapshot.nextId, 3); + assert.equal(harness.changes(), 1); +}); + +test("tool validation errors are summarized while preserving atomic state", async () => { + const harness = registeredTools(); + await execute(harness.tools.get("add_task"), { + tasks: [{ name: "Parent", description: "Parent", children: [{ name: "Child", description: "Child" }] }], + }); + const before = harness.state.snapshot(); + + await assert.rejects( + execute(harness.tools.get("update_task"), { tasks: [{ id: 1, parentId: 2 }] }), + /Update failed · 1 validation error\n- task [12]: parentId creates a cycle/, + ); + assert.deepEqual(harness.state.snapshot(), before); + assert.equal(harness.changes(), 1); +}); + +test("list is compact and get returns full JSON for multiple IDs", async () => { + const harness = registeredTools(); + await execute(harness.tools.get("add_task"), { + tasks: [{ name: "Parent", description: "Detailed", children: [{ name: "Child", description: "Child detail" }] }], + }); + + const list = await execute(harness.tools.get("list_task"), {}); + assert.equal(list.content[0].text, "1 [pending] Parent\n└─ 2 [pending] Child"); + + const get = await execute(harness.tools.get("get_task"), { ids: [1, 2] }); + const parsed = JSON.parse(get.content[0].text); + assert.equal(parsed[0].description, "Detailed"); + assert.deepEqual(parsed[0].childrenIds, [2]); + assert.equal(parsed[1].parentId, 1); +}); diff --git a/tests/ui.test.ts b/tests/ui.test.ts new file mode 100644 index 0000000..2da4e23 --- /dev/null +++ b/tests/ui.test.ts @@ -0,0 +1,178 @@ +import assert from "node:assert/strict"; +import test from "node:test"; +import { visibleWidth } from "@earendil-works/pi-tui"; +import { currentTaskLabel } from "../src/herdr.ts"; +import { TaskState } from "../src/state.ts"; +import { + renderProgressHeader, + renderTaskLine, + renderToolResult, + renderTree, + snapshotStats, +} from "../src/ui.ts"; +import { updateTaskWidget } from "../src/widget.ts"; + +const plainTheme = { + fg: (_color: string, text: string) => text, + bold: (text: string) => text, + strikethrough: (text: string) => `~${text}~`, +}; + +function stripAnsi(text: string): string { + return text.replace(/\x1b\[[0-9;]*m/g, ""); +} + +function fixture(): TaskState { + const state = new TaskState(); + state.add([ + { + name: "Build auth", + description: "Auth work", + status: "in-progress", + children: [ + { + name: "Resolve token issue", + description: "Investigate token validation and provider behavior.", + status: "blocked", + children: [{ name: "Inspect provider response", description: "Inspect response" }], + }, + { name: "Add middleware", description: "Middleware" }, + ], + }, + { name: "Define schema", description: "Schema", status: "done" }, + ]); + return state; +} + +test("renders an adaptive progress bar and stays within width", () => { + const stats = fixture().stats(); + const wide = stripAnsi(renderProgressHeader(stats, plainTheme as never, 40)); + assert.match(wide, /^ Tasks 1\/5 · !1 ━{4}─{16}$/); + assert.ok(visibleWidth(wide) <= 40); + + const narrow = renderProgressHeader(stats, plainTheme as never, 12); + assert.ok(visibleWidth(narrow) <= 12); + assert.doesNotMatch(stripAnsi(narrow), /━|─/); +}); + +test("renders lightweight connectors without a detached root continuation", () => { + const output = renderTree(fixture().list(), plainTheme as never, 80).map(stripAnsi); + assert.deepEqual(output, [ + " ◉ 1. Build auth", + " ├─ ! 2. Resolve token issue", + " │ └─ ○ 3. Inspect provider response", + " └─ ○ 4. Add middleware", + " ✓ 5. ~Define schema~", + ]); +}); + +test("truncates every task row at narrow widths", () => { + const lines = renderTree(fixture().list(), plainTheme as never, 20); + assert.ok(lines.every((line) => visibleWidth(line) <= 20)); + assert.ok(lines.some((line) => stripAnsi(line).includes("..."))); +}); + +test("uses semantic icon colors and old-plugin text styling", () => { + const calls: Array<{ color: string; text: string }> = []; + const theme = { + fg: (color: string, text: string) => { + calls.push({ color, text }); + return text; + }, + bold: (text: string) => text, + strikethrough: (text: string) => `~${text}~`, + }; + const tasks = fixture().list(); + for (const task of tasks) renderTaskLine(task, "", theme as never, 80); + + assert.ok(calls.some((call) => call.color === "dim" && call.text === "○")); + assert.ok(calls.some((call) => call.color === "warning" && call.text === "◉")); + assert.ok(calls.some((call) => call.color === "error" && call.text === "!")); + assert.ok(calls.some((call) => call.color === "success" && call.text === "✓")); + assert.ok(calls.some((call) => call.color === "warning" && call.text === "Build auth")); + assert.ok(calls.some((call) => call.color === "dim" && call.text === "~Define schema~")); + assert.ok(!calls.some((call) => call.color === "error" && call.text === "Resolve token issue")); +}); + +test("selects the most specific in-progress task and compresses parallel leaves", () => { + const state = new TaskState(); + state.add([ + { + name: "Parent", + description: "Parent", + status: "in-progress", + children: [{ name: "Child", description: "Child", status: "in-progress" }], + }, + { name: "Parallel", description: "Parallel", status: "in-progress" }, + ]); + assert.equal(currentTaskLabel(state.list()), "#2 Child +1"); +}); + +test("uses blocked tasks only when nothing is in progress", () => { + const state = new TaskState(); + state.add([ + { name: "Blocked one", description: "One", status: "blocked" }, + { name: "Blocked two", description: "Two", status: "blocked" }, + ]); + assert.equal(currentTaskLabel(state.list()), "#1 Blocked one +1"); + state.update([{ id: 1, status: "done" }, { id: 2, status: "done" }]); + assert.equal(currentTaskLabel(state.list()), null); +}); + +test("hides an empty widget and renders a populated one", () => { + let widget: unknown = "unset"; + const ctx = { + ui: { + setWidget: (_id: string, content: unknown) => { + widget = content; + }, + }, + }; + const state = new TaskState(); + updateTaskWidget(state, ctx as never, true); + assert.equal(widget, undefined); + + state.add([{ name: "Task", description: "Task" }]); + updateTaskWidget(state, ctx as never, true); + assert.equal(typeof widget, "function"); + const component = (widget as unknown as (tui: unknown, theme: unknown) => { render(width: number): string[] })( + {}, + plainTheme, + ); + const lines = component.render(30); + assert.equal(lines.length, 2); + assert.ok(lines.every((line) => visibleWidth(line) <= 30)); +}); + +test("tool results collapse summaries and expand themed details", () => { + const state = fixture(); + const details = { action: "list" as const, snapshot: state.snapshot(), affected: state.list() }; + const result = { content: [{ type: "text", text: "list" }], details }; + const collapsed = renderToolResult(result, false, plainTheme as never).render(80).map(stripAnsi); + assert.deepEqual(collapsed, ["✓ 5 tasks · 1/5 done"]); + + const expanded = renderToolResult(result, true, plainTheme as never).render(80).map(stripAnsi); + assert.equal(expanded.length, 6); + assert.match(expanded[1] ?? "", /Build auth/); +}); + +test("tool errors show one summary line until expanded", () => { + const result = { + content: [{ type: "text", text: "Update failed · 2 validation errors\n- first\n- second" }], + isError: true, + }; + const collapsed = renderToolResult(result, false, plainTheme as never).render(80).map(stripAnsi); + assert.deepEqual(collapsed, ["✗ Update failed · 2 validation errors"]); + const expanded = renderToolResult(result, true, plainTheme as never).render(80).map(stripAnsi); + assert.deepEqual(expanded, ["✗ Update failed · 2 validation errors", " - first", " - second"]); +}); + +test("snapshot stats count every task node", () => { + assert.deepEqual(snapshotStats(fixture().list()), { + total: 5, + pending: 2, + inProgress: 1, + blocked: 1, + done: 1, + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..47f429e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "allowImportingTsExtensions": true, + "strict": true, + "noEmit": true, + "skipLibCheck": true, + "types": ["node"] + }, + "include": ["index.ts", "src/**/*.ts", "tests/**/*.ts"] +}