diff --git a/.gitignore b/.gitignore index 90bbf09..eaa5485 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ dist server/public vite.config.ts.* *.tar.gz.git.backup +.local +.git.backup diff --git a/.local/state/replit/agent/.agent_state_00050df292f86812397c11c52cb208704fdbf55c.bin b/.local/state/replit/agent/.agent_state_00050df292f86812397c11c52cb208704fdbf55c.bin deleted file mode 100644 index 8db1bb1..0000000 Binary files a/.local/state/replit/agent/.agent_state_00050df292f86812397c11c52cb208704fdbf55c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_00bdaafae92ddfe575a1f0ded8330f069ecab7b9.bin b/.local/state/replit/agent/.agent_state_00bdaafae92ddfe575a1f0ded8330f069ecab7b9.bin deleted file mode 100644 index 5cf16c9..0000000 Binary files a/.local/state/replit/agent/.agent_state_00bdaafae92ddfe575a1f0ded8330f069ecab7b9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0145f82ed26003324dee86aa9624e7bae8e906b1.bin b/.local/state/replit/agent/.agent_state_0145f82ed26003324dee86aa9624e7bae8e906b1.bin deleted file mode 100644 index cfb62a2..0000000 Binary files a/.local/state/replit/agent/.agent_state_0145f82ed26003324dee86aa9624e7bae8e906b1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_033cf9b53457b5dd191774dddb04129013a85b9f.bin b/.local/state/replit/agent/.agent_state_033cf9b53457b5dd191774dddb04129013a85b9f.bin deleted file mode 100644 index c07262c..0000000 Binary files a/.local/state/replit/agent/.agent_state_033cf9b53457b5dd191774dddb04129013a85b9f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_04e52bfabade8daf03564c382d97b9768b38cc48.bin b/.local/state/replit/agent/.agent_state_04e52bfabade8daf03564c382d97b9768b38cc48.bin deleted file mode 100644 index 16ddb7f..0000000 Binary files a/.local/state/replit/agent/.agent_state_04e52bfabade8daf03564c382d97b9768b38cc48.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_050fb6702488c4e98740973891e92cf6090f9eb0.bin b/.local/state/replit/agent/.agent_state_050fb6702488c4e98740973891e92cf6090f9eb0.bin deleted file mode 100644 index c1e4c60..0000000 Binary files a/.local/state/replit/agent/.agent_state_050fb6702488c4e98740973891e92cf6090f9eb0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0531bea0bf3d0770bb1aae3ce2311bfd03f394ff.bin b/.local/state/replit/agent/.agent_state_0531bea0bf3d0770bb1aae3ce2311bfd03f394ff.bin deleted file mode 100644 index 23f5e65..0000000 Binary files a/.local/state/replit/agent/.agent_state_0531bea0bf3d0770bb1aae3ce2311bfd03f394ff.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_060b372acfede5a72aff107957f53c38fec1b887.bin b/.local/state/replit/agent/.agent_state_060b372acfede5a72aff107957f53c38fec1b887.bin deleted file mode 100644 index dac2ae8..0000000 Binary files a/.local/state/replit/agent/.agent_state_060b372acfede5a72aff107957f53c38fec1b887.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_06cb1783fcff17a9f58082954e49acba060d2997.bin b/.local/state/replit/agent/.agent_state_06cb1783fcff17a9f58082954e49acba060d2997.bin deleted file mode 100644 index 5308bea..0000000 Binary files a/.local/state/replit/agent/.agent_state_06cb1783fcff17a9f58082954e49acba060d2997.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_072c2cb7f5e293ea98f51df796e70b6f01b07a34.bin b/.local/state/replit/agent/.agent_state_072c2cb7f5e293ea98f51df796e70b6f01b07a34.bin deleted file mode 100644 index e1ff463..0000000 Binary files a/.local/state/replit/agent/.agent_state_072c2cb7f5e293ea98f51df796e70b6f01b07a34.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_074e6aba06ecb578004d23f995fea1fca24c3641.bin b/.local/state/replit/agent/.agent_state_074e6aba06ecb578004d23f995fea1fca24c3641.bin deleted file mode 100644 index 1e1a072..0000000 Binary files a/.local/state/replit/agent/.agent_state_074e6aba06ecb578004d23f995fea1fca24c3641.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_077e23af609948534efe2d61d7e50efaab84488d.bin b/.local/state/replit/agent/.agent_state_077e23af609948534efe2d61d7e50efaab84488d.bin deleted file mode 100644 index 7c7a51b..0000000 Binary files a/.local/state/replit/agent/.agent_state_077e23af609948534efe2d61d7e50efaab84488d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_07b2728d0ff17ce208276463aec3bd4451fffa2a.bin b/.local/state/replit/agent/.agent_state_07b2728d0ff17ce208276463aec3bd4451fffa2a.bin deleted file mode 100644 index c30d0cc..0000000 Binary files a/.local/state/replit/agent/.agent_state_07b2728d0ff17ce208276463aec3bd4451fffa2a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0820176d7dfc6a8c9bc5da14ace99016b12a8b32.bin b/.local/state/replit/agent/.agent_state_0820176d7dfc6a8c9bc5da14ace99016b12a8b32.bin deleted file mode 100644 index 749b771..0000000 Binary files a/.local/state/replit/agent/.agent_state_0820176d7dfc6a8c9bc5da14ace99016b12a8b32.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_08b0d0744aadc701ca42a502937a9403a52c4838.bin b/.local/state/replit/agent/.agent_state_08b0d0744aadc701ca42a502937a9403a52c4838.bin deleted file mode 100644 index 3cca853..0000000 Binary files a/.local/state/replit/agent/.agent_state_08b0d0744aadc701ca42a502937a9403a52c4838.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0906d05270c61750a616da07ed58060f5ed014d4.bin b/.local/state/replit/agent/.agent_state_0906d05270c61750a616da07ed58060f5ed014d4.bin deleted file mode 100644 index 8d7b052..0000000 Binary files a/.local/state/replit/agent/.agent_state_0906d05270c61750a616da07ed58060f5ed014d4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0a1c9548fdd2191f6722d9fe69f78c179651bec6.bin b/.local/state/replit/agent/.agent_state_0a1c9548fdd2191f6722d9fe69f78c179651bec6.bin deleted file mode 100644 index 1761c60..0000000 Binary files a/.local/state/replit/agent/.agent_state_0a1c9548fdd2191f6722d9fe69f78c179651bec6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0a4fcd94a3758c2b10a6c46ab090f7d9137bed7f.bin b/.local/state/replit/agent/.agent_state_0a4fcd94a3758c2b10a6c46ab090f7d9137bed7f.bin deleted file mode 100644 index 0b734f1..0000000 Binary files a/.local/state/replit/agent/.agent_state_0a4fcd94a3758c2b10a6c46ab090f7d9137bed7f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0becef10518a6e7893ec96226c89c520a20dc873.bin b/.local/state/replit/agent/.agent_state_0becef10518a6e7893ec96226c89c520a20dc873.bin deleted file mode 100644 index f0a6b47..0000000 Binary files a/.local/state/replit/agent/.agent_state_0becef10518a6e7893ec96226c89c520a20dc873.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0e58449e48d4e78fe19d2c389a439af60a8cfaab.bin b/.local/state/replit/agent/.agent_state_0e58449e48d4e78fe19d2c389a439af60a8cfaab.bin deleted file mode 100644 index e0d376c..0000000 Binary files a/.local/state/replit/agent/.agent_state_0e58449e48d4e78fe19d2c389a439af60a8cfaab.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0ef56c56d63b2111a56ade336a316879792fe0a6.bin b/.local/state/replit/agent/.agent_state_0ef56c56d63b2111a56ade336a316879792fe0a6.bin deleted file mode 100644 index a3d64ed..0000000 Binary files a/.local/state/replit/agent/.agent_state_0ef56c56d63b2111a56ade336a316879792fe0a6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0f6a9f113e2503e1a43cc52da914c8cc26ee27f5.bin b/.local/state/replit/agent/.agent_state_0f6a9f113e2503e1a43cc52da914c8cc26ee27f5.bin deleted file mode 100644 index d7d0220..0000000 Binary files a/.local/state/replit/agent/.agent_state_0f6a9f113e2503e1a43cc52da914c8cc26ee27f5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_0f90b63c71245dcaaef1de21bc15034c42fc1d07.bin b/.local/state/replit/agent/.agent_state_0f90b63c71245dcaaef1de21bc15034c42fc1d07.bin deleted file mode 100644 index 7ac00cc..0000000 Binary files a/.local/state/replit/agent/.agent_state_0f90b63c71245dcaaef1de21bc15034c42fc1d07.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_101ff4ba92725d3c0d9eb61986b5d258e6308f70.bin b/.local/state/replit/agent/.agent_state_101ff4ba92725d3c0d9eb61986b5d258e6308f70.bin deleted file mode 100644 index 54ff31e..0000000 Binary files a/.local/state/replit/agent/.agent_state_101ff4ba92725d3c0d9eb61986b5d258e6308f70.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_10226bd99f18a915b1fa60edba8079bc2d3394a6.bin b/.local/state/replit/agent/.agent_state_10226bd99f18a915b1fa60edba8079bc2d3394a6.bin deleted file mode 100644 index 137dbf6..0000000 Binary files a/.local/state/replit/agent/.agent_state_10226bd99f18a915b1fa60edba8079bc2d3394a6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_105818a9aa21ca2378c55672ea7f8fda478db719.bin b/.local/state/replit/agent/.agent_state_105818a9aa21ca2378c55672ea7f8fda478db719.bin deleted file mode 100644 index 760fe43..0000000 Binary files a/.local/state/replit/agent/.agent_state_105818a9aa21ca2378c55672ea7f8fda478db719.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_11896c29a6438ce38114a3025e0cb03a047926e9.bin b/.local/state/replit/agent/.agent_state_11896c29a6438ce38114a3025e0cb03a047926e9.bin deleted file mode 100644 index 834580d..0000000 Binary files a/.local/state/replit/agent/.agent_state_11896c29a6438ce38114a3025e0cb03a047926e9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_12577a015fca322bcea647886382cf0d794c0176.bin b/.local/state/replit/agent/.agent_state_12577a015fca322bcea647886382cf0d794c0176.bin deleted file mode 100644 index 3545acc..0000000 Binary files a/.local/state/replit/agent/.agent_state_12577a015fca322bcea647886382cf0d794c0176.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_126d2d24aac8c4a2d7fcfd40020d3722bdeeb2dd.bin b/.local/state/replit/agent/.agent_state_126d2d24aac8c4a2d7fcfd40020d3722bdeeb2dd.bin deleted file mode 100644 index a777d92..0000000 Binary files a/.local/state/replit/agent/.agent_state_126d2d24aac8c4a2d7fcfd40020d3722bdeeb2dd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1295858a6ffe193191a3525e39f766a36ca20ce1.bin b/.local/state/replit/agent/.agent_state_1295858a6ffe193191a3525e39f766a36ca20ce1.bin deleted file mode 100644 index 0539b3e..0000000 Binary files a/.local/state/replit/agent/.agent_state_1295858a6ffe193191a3525e39f766a36ca20ce1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_12c6e784406b5612b4d6301781cd905affc42910.bin b/.local/state/replit/agent/.agent_state_12c6e784406b5612b4d6301781cd905affc42910.bin deleted file mode 100644 index c54fbe8..0000000 Binary files a/.local/state/replit/agent/.agent_state_12c6e784406b5612b4d6301781cd905affc42910.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_12ec8dbdddb1ed5d8788ad8196d4dbe3eebf9367.bin b/.local/state/replit/agent/.agent_state_12ec8dbdddb1ed5d8788ad8196d4dbe3eebf9367.bin deleted file mode 100644 index aff5020..0000000 Binary files a/.local/state/replit/agent/.agent_state_12ec8dbdddb1ed5d8788ad8196d4dbe3eebf9367.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_137bb905b9d4797173a0394f9c6d9d703856486b.bin b/.local/state/replit/agent/.agent_state_137bb905b9d4797173a0394f9c6d9d703856486b.bin deleted file mode 100644 index 91c2fbf..0000000 Binary files a/.local/state/replit/agent/.agent_state_137bb905b9d4797173a0394f9c6d9d703856486b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_140503a0cbda0e8ab2fe3d4106dc814910dd29c4.bin b/.local/state/replit/agent/.agent_state_140503a0cbda0e8ab2fe3d4106dc814910dd29c4.bin deleted file mode 100644 index 7dff637..0000000 Binary files a/.local/state/replit/agent/.agent_state_140503a0cbda0e8ab2fe3d4106dc814910dd29c4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1436f7037646cc0f3e355715cb48c8884b685600.bin b/.local/state/replit/agent/.agent_state_1436f7037646cc0f3e355715cb48c8884b685600.bin deleted file mode 100644 index 14e8f0d..0000000 Binary files a/.local/state/replit/agent/.agent_state_1436f7037646cc0f3e355715cb48c8884b685600.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_146f485fe4a707bb7f7a0eeaf9c9e942d769342b.bin b/.local/state/replit/agent/.agent_state_146f485fe4a707bb7f7a0eeaf9c9e942d769342b.bin deleted file mode 100644 index 7355c65..0000000 Binary files a/.local/state/replit/agent/.agent_state_146f485fe4a707bb7f7a0eeaf9c9e942d769342b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_147be43c28cf4abf24daf0ea3c438006d3095cd2.bin b/.local/state/replit/agent/.agent_state_147be43c28cf4abf24daf0ea3c438006d3095cd2.bin deleted file mode 100644 index 0bcfd77..0000000 Binary files a/.local/state/replit/agent/.agent_state_147be43c28cf4abf24daf0ea3c438006d3095cd2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_14b5241cffc13b0e9e9847ec37dd504ddc397632.bin b/.local/state/replit/agent/.agent_state_14b5241cffc13b0e9e9847ec37dd504ddc397632.bin deleted file mode 100644 index 3386fc3..0000000 Binary files a/.local/state/replit/agent/.agent_state_14b5241cffc13b0e9e9847ec37dd504ddc397632.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1627f057bcb18ceb2d62f98dfb17ef8c36c1a6b7.bin b/.local/state/replit/agent/.agent_state_1627f057bcb18ceb2d62f98dfb17ef8c36c1a6b7.bin deleted file mode 100644 index 9df7446..0000000 Binary files a/.local/state/replit/agent/.agent_state_1627f057bcb18ceb2d62f98dfb17ef8c36c1a6b7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_166d164a9e23142364a1d4980efef58fca63a606.bin b/.local/state/replit/agent/.agent_state_166d164a9e23142364a1d4980efef58fca63a606.bin deleted file mode 100644 index ff19a23..0000000 Binary files a/.local/state/replit/agent/.agent_state_166d164a9e23142364a1d4980efef58fca63a606.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_176d1736e6a77d987ab31b66e87a52933fe6e470.bin b/.local/state/replit/agent/.agent_state_176d1736e6a77d987ab31b66e87a52933fe6e470.bin deleted file mode 100644 index b3e0388..0000000 Binary files a/.local/state/replit/agent/.agent_state_176d1736e6a77d987ab31b66e87a52933fe6e470.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1853b5fa157fdabc666cf2ddd02f7ef483674687.bin b/.local/state/replit/agent/.agent_state_1853b5fa157fdabc666cf2ddd02f7ef483674687.bin deleted file mode 100644 index 197e4b2..0000000 Binary files a/.local/state/replit/agent/.agent_state_1853b5fa157fdabc666cf2ddd02f7ef483674687.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_18dcb3176609d699bf37718201bb98c48d997135.bin b/.local/state/replit/agent/.agent_state_18dcb3176609d699bf37718201bb98c48d997135.bin deleted file mode 100644 index a1b2422..0000000 Binary files a/.local/state/replit/agent/.agent_state_18dcb3176609d699bf37718201bb98c48d997135.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_190cf155d6d2ca3cfc602f29028798e73db141ad.bin b/.local/state/replit/agent/.agent_state_190cf155d6d2ca3cfc602f29028798e73db141ad.bin deleted file mode 100644 index 4d31e3f..0000000 Binary files a/.local/state/replit/agent/.agent_state_190cf155d6d2ca3cfc602f29028798e73db141ad.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_19887b759ea2aaee6200692f651c097a54e8b26b.bin b/.local/state/replit/agent/.agent_state_19887b759ea2aaee6200692f651c097a54e8b26b.bin deleted file mode 100644 index fa5a1d3..0000000 Binary files a/.local/state/replit/agent/.agent_state_19887b759ea2aaee6200692f651c097a54e8b26b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_19a5c646ea3c4844d8cd6d0ec6694f7cbd64eeb4.bin b/.local/state/replit/agent/.agent_state_19a5c646ea3c4844d8cd6d0ec6694f7cbd64eeb4.bin deleted file mode 100644 index 06d52c1..0000000 Binary files a/.local/state/replit/agent/.agent_state_19a5c646ea3c4844d8cd6d0ec6694f7cbd64eeb4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1a636e465770527306523467986dafacf096df08.bin b/.local/state/replit/agent/.agent_state_1a636e465770527306523467986dafacf096df08.bin deleted file mode 100644 index 39561ab..0000000 Binary files a/.local/state/replit/agent/.agent_state_1a636e465770527306523467986dafacf096df08.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1a90f5e1ff0442005719521314a90e1bdb691ea8.bin b/.local/state/replit/agent/.agent_state_1a90f5e1ff0442005719521314a90e1bdb691ea8.bin deleted file mode 100644 index cd91660..0000000 Binary files a/.local/state/replit/agent/.agent_state_1a90f5e1ff0442005719521314a90e1bdb691ea8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1b5e00a60206d41547329870a0bc4c0341c62302.bin b/.local/state/replit/agent/.agent_state_1b5e00a60206d41547329870a0bc4c0341c62302.bin deleted file mode 100644 index 7e0851e..0000000 Binary files a/.local/state/replit/agent/.agent_state_1b5e00a60206d41547329870a0bc4c0341c62302.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1b66bc3abda4811459bf97369b7bc39f600cbf2f.bin b/.local/state/replit/agent/.agent_state_1b66bc3abda4811459bf97369b7bc39f600cbf2f.bin deleted file mode 100644 index 1d98d72..0000000 Binary files a/.local/state/replit/agent/.agent_state_1b66bc3abda4811459bf97369b7bc39f600cbf2f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1bf0ff29bac2e7127ecac34a42ace9d4234c347e.bin b/.local/state/replit/agent/.agent_state_1bf0ff29bac2e7127ecac34a42ace9d4234c347e.bin deleted file mode 100644 index 0329181..0000000 Binary files a/.local/state/replit/agent/.agent_state_1bf0ff29bac2e7127ecac34a42ace9d4234c347e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1d709f78e15174ebf529a06460ef11b1ee9c8f17.bin b/.local/state/replit/agent/.agent_state_1d709f78e15174ebf529a06460ef11b1ee9c8f17.bin deleted file mode 100644 index 9fd876e..0000000 Binary files a/.local/state/replit/agent/.agent_state_1d709f78e15174ebf529a06460ef11b1ee9c8f17.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1dcc00f1c731e7563267371f3173ff9cdabbcbc9.bin b/.local/state/replit/agent/.agent_state_1dcc00f1c731e7563267371f3173ff9cdabbcbc9.bin deleted file mode 100644 index e5213c4..0000000 Binary files a/.local/state/replit/agent/.agent_state_1dcc00f1c731e7563267371f3173ff9cdabbcbc9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_1e570c4654627420b0b1760264e9fa06f2cd08a1.bin b/.local/state/replit/agent/.agent_state_1e570c4654627420b0b1760264e9fa06f2cd08a1.bin deleted file mode 100644 index b6ee76e..0000000 Binary files a/.local/state/replit/agent/.agent_state_1e570c4654627420b0b1760264e9fa06f2cd08a1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2018a6a247d9ea04c835ddd4462914d1a2d95e4b.bin b/.local/state/replit/agent/.agent_state_2018a6a247d9ea04c835ddd4462914d1a2d95e4b.bin deleted file mode 100644 index be0c557..0000000 Binary files a/.local/state/replit/agent/.agent_state_2018a6a247d9ea04c835ddd4462914d1a2d95e4b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_205ad5202a9f04578f244ab8b05b8bb24c140c32.bin b/.local/state/replit/agent/.agent_state_205ad5202a9f04578f244ab8b05b8bb24c140c32.bin deleted file mode 100644 index 46b3687..0000000 Binary files a/.local/state/replit/agent/.agent_state_205ad5202a9f04578f244ab8b05b8bb24c140c32.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2088ba55da7c989e64ce0a12134e6eb22db4f71f.bin b/.local/state/replit/agent/.agent_state_2088ba55da7c989e64ce0a12134e6eb22db4f71f.bin deleted file mode 100644 index 632456d..0000000 Binary files a/.local/state/replit/agent/.agent_state_2088ba55da7c989e64ce0a12134e6eb22db4f71f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_21532e0b7ba78e7c22031f65e068e8aa6767e58b.bin b/.local/state/replit/agent/.agent_state_21532e0b7ba78e7c22031f65e068e8aa6767e58b.bin deleted file mode 100644 index cbaa4f9..0000000 Binary files a/.local/state/replit/agent/.agent_state_21532e0b7ba78e7c22031f65e068e8aa6767e58b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_225a46d70208ef7c71c02160b23adf39a1892610.bin b/.local/state/replit/agent/.agent_state_225a46d70208ef7c71c02160b23adf39a1892610.bin deleted file mode 100644 index f27438d..0000000 Binary files a/.local/state/replit/agent/.agent_state_225a46d70208ef7c71c02160b23adf39a1892610.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_22e04d52f5afa53b0cedd83b9a9ef213f1a9545a.bin b/.local/state/replit/agent/.agent_state_22e04d52f5afa53b0cedd83b9a9ef213f1a9545a.bin deleted file mode 100644 index b62fbe7..0000000 Binary files a/.local/state/replit/agent/.agent_state_22e04d52f5afa53b0cedd83b9a9ef213f1a9545a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_22f06a39ab3224115ddea4b5e520be97f4baf4ed.bin b/.local/state/replit/agent/.agent_state_22f06a39ab3224115ddea4b5e520be97f4baf4ed.bin deleted file mode 100644 index 776c223..0000000 Binary files a/.local/state/replit/agent/.agent_state_22f06a39ab3224115ddea4b5e520be97f4baf4ed.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2313083764836a7f81ad8b0e9d34bd4f87b4bd2c.bin b/.local/state/replit/agent/.agent_state_2313083764836a7f81ad8b0e9d34bd4f87b4bd2c.bin deleted file mode 100644 index 194a4d7..0000000 Binary files a/.local/state/replit/agent/.agent_state_2313083764836a7f81ad8b0e9d34bd4f87b4bd2c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_243d07a1e1225807fb379c92a6e528bde3f6e3e6.bin b/.local/state/replit/agent/.agent_state_243d07a1e1225807fb379c92a6e528bde3f6e3e6.bin deleted file mode 100644 index 7a01967..0000000 Binary files a/.local/state/replit/agent/.agent_state_243d07a1e1225807fb379c92a6e528bde3f6e3e6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_245930c4360706e52a52d57061b9390a4ceb0228.bin b/.local/state/replit/agent/.agent_state_245930c4360706e52a52d57061b9390a4ceb0228.bin deleted file mode 100644 index 4793426..0000000 Binary files a/.local/state/replit/agent/.agent_state_245930c4360706e52a52d57061b9390a4ceb0228.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_24dd79047b61582b2d4195c59b8a9a86972cd20e.bin b/.local/state/replit/agent/.agent_state_24dd79047b61582b2d4195c59b8a9a86972cd20e.bin deleted file mode 100644 index 0fb976e..0000000 Binary files a/.local/state/replit/agent/.agent_state_24dd79047b61582b2d4195c59b8a9a86972cd20e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_25038d71bd3a82ef0022d4414bbb3aed61a16e6b.bin b/.local/state/replit/agent/.agent_state_25038d71bd3a82ef0022d4414bbb3aed61a16e6b.bin deleted file mode 100644 index 6524940..0000000 Binary files a/.local/state/replit/agent/.agent_state_25038d71bd3a82ef0022d4414bbb3aed61a16e6b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_250ae3de45e5b72eb5e30132333d460401caf5d0.bin b/.local/state/replit/agent/.agent_state_250ae3de45e5b72eb5e30132333d460401caf5d0.bin deleted file mode 100644 index ab92914..0000000 Binary files a/.local/state/replit/agent/.agent_state_250ae3de45e5b72eb5e30132333d460401caf5d0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_253150a0218d82118c397b9d471b63087e3b7a55.bin b/.local/state/replit/agent/.agent_state_253150a0218d82118c397b9d471b63087e3b7a55.bin deleted file mode 100644 index 974c86f..0000000 Binary files a/.local/state/replit/agent/.agent_state_253150a0218d82118c397b9d471b63087e3b7a55.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_25e188c5c210c75c340541ceeb18ee671f383763.bin b/.local/state/replit/agent/.agent_state_25e188c5c210c75c340541ceeb18ee671f383763.bin deleted file mode 100644 index 61cde79..0000000 Binary files a/.local/state/replit/agent/.agent_state_25e188c5c210c75c340541ceeb18ee671f383763.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_25e36c11314994e5010dc96e01eafd888afac381.bin b/.local/state/replit/agent/.agent_state_25e36c11314994e5010dc96e01eafd888afac381.bin deleted file mode 100644 index 925a61f..0000000 Binary files a/.local/state/replit/agent/.agent_state_25e36c11314994e5010dc96e01eafd888afac381.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_26134968cfb37718733f0d17a86fd21c0ed29007.bin b/.local/state/replit/agent/.agent_state_26134968cfb37718733f0d17a86fd21c0ed29007.bin deleted file mode 100644 index da65adb..0000000 Binary files a/.local/state/replit/agent/.agent_state_26134968cfb37718733f0d17a86fd21c0ed29007.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_26d02d280d8eb9ef851cadd763e8b1ce55cb6cd5.bin b/.local/state/replit/agent/.agent_state_26d02d280d8eb9ef851cadd763e8b1ce55cb6cd5.bin deleted file mode 100644 index c2890b0..0000000 Binary files a/.local/state/replit/agent/.agent_state_26d02d280d8eb9ef851cadd763e8b1ce55cb6cd5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_26d43e8f8bb2b690b57bbe90499907a9ea1c5d00.bin b/.local/state/replit/agent/.agent_state_26d43e8f8bb2b690b57bbe90499907a9ea1c5d00.bin deleted file mode 100644 index a9a0639..0000000 Binary files a/.local/state/replit/agent/.agent_state_26d43e8f8bb2b690b57bbe90499907a9ea1c5d00.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_274c39aea440cc5f7cf26964c980b664749707c4.bin b/.local/state/replit/agent/.agent_state_274c39aea440cc5f7cf26964c980b664749707c4.bin deleted file mode 100644 index cde0319..0000000 Binary files a/.local/state/replit/agent/.agent_state_274c39aea440cc5f7cf26964c980b664749707c4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_282cd5f8518f2eaeb40e1039cf6f1f4622016376.bin b/.local/state/replit/agent/.agent_state_282cd5f8518f2eaeb40e1039cf6f1f4622016376.bin deleted file mode 100644 index 6b9d97b..0000000 Binary files a/.local/state/replit/agent/.agent_state_282cd5f8518f2eaeb40e1039cf6f1f4622016376.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_285639a9bb1fee5cd487c9c27eb6d4478e71edc7.bin b/.local/state/replit/agent/.agent_state_285639a9bb1fee5cd487c9c27eb6d4478e71edc7.bin deleted file mode 100644 index eb5d6f9..0000000 Binary files a/.local/state/replit/agent/.agent_state_285639a9bb1fee5cd487c9c27eb6d4478e71edc7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_285d32e6511e52ada46df6b7967fef08c81feb0a.bin b/.local/state/replit/agent/.agent_state_285d32e6511e52ada46df6b7967fef08c81feb0a.bin deleted file mode 100644 index 7f200ea..0000000 Binary files a/.local/state/replit/agent/.agent_state_285d32e6511e52ada46df6b7967fef08c81feb0a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_287bd20f29ce4e441b92b876defb40c1da09b25c.bin b/.local/state/replit/agent/.agent_state_287bd20f29ce4e441b92b876defb40c1da09b25c.bin deleted file mode 100644 index 93c1238..0000000 Binary files a/.local/state/replit/agent/.agent_state_287bd20f29ce4e441b92b876defb40c1da09b25c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_28a4130d4b9806d5c72181834776d806aa98778c.bin b/.local/state/replit/agent/.agent_state_28a4130d4b9806d5c72181834776d806aa98778c.bin deleted file mode 100644 index 0e6d3a9..0000000 Binary files a/.local/state/replit/agent/.agent_state_28a4130d4b9806d5c72181834776d806aa98778c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2990d3b15b728d58673c8931789070007435d5c1.bin b/.local/state/replit/agent/.agent_state_2990d3b15b728d58673c8931789070007435d5c1.bin deleted file mode 100644 index 24668e1..0000000 Binary files a/.local/state/replit/agent/.agent_state_2990d3b15b728d58673c8931789070007435d5c1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2a54e3cf1015ce9669ee3469709db030ca37b6dd.bin b/.local/state/replit/agent/.agent_state_2a54e3cf1015ce9669ee3469709db030ca37b6dd.bin deleted file mode 100644 index 37a0ed4..0000000 Binary files a/.local/state/replit/agent/.agent_state_2a54e3cf1015ce9669ee3469709db030ca37b6dd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2b54a5e388d33c88d218f2ed4462a8445a99454b.bin b/.local/state/replit/agent/.agent_state_2b54a5e388d33c88d218f2ed4462a8445a99454b.bin deleted file mode 100644 index ccb3ebf..0000000 Binary files a/.local/state/replit/agent/.agent_state_2b54a5e388d33c88d218f2ed4462a8445a99454b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2b7262ed274225e20adeaf6813b9afaa45a84de5.bin b/.local/state/replit/agent/.agent_state_2b7262ed274225e20adeaf6813b9afaa45a84de5.bin deleted file mode 100644 index 6654ae3..0000000 Binary files a/.local/state/replit/agent/.agent_state_2b7262ed274225e20adeaf6813b9afaa45a84de5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2b82f52f75204c9830703dbfdb646bac2f4a30b6.bin b/.local/state/replit/agent/.agent_state_2b82f52f75204c9830703dbfdb646bac2f4a30b6.bin deleted file mode 100644 index 3fd22a3..0000000 Binary files a/.local/state/replit/agent/.agent_state_2b82f52f75204c9830703dbfdb646bac2f4a30b6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2bb0aa5188ba47eea6eb2d0958dc7af0b7e00eac.bin b/.local/state/replit/agent/.agent_state_2bb0aa5188ba47eea6eb2d0958dc7af0b7e00eac.bin deleted file mode 100644 index b88f0d4..0000000 Binary files a/.local/state/replit/agent/.agent_state_2bb0aa5188ba47eea6eb2d0958dc7af0b7e00eac.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2bc7ab13c10dbfbc929e887124a946769f01dc52.bin b/.local/state/replit/agent/.agent_state_2bc7ab13c10dbfbc929e887124a946769f01dc52.bin deleted file mode 100644 index 3108406..0000000 Binary files a/.local/state/replit/agent/.agent_state_2bc7ab13c10dbfbc929e887124a946769f01dc52.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2dc078da839bca6b923c3d2d0415491897847002.bin b/.local/state/replit/agent/.agent_state_2dc078da839bca6b923c3d2d0415491897847002.bin deleted file mode 100644 index 8a1b7de..0000000 Binary files a/.local/state/replit/agent/.agent_state_2dc078da839bca6b923c3d2d0415491897847002.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2e2f085fec1e4087021c7d73e7c1fd72ac165447.bin b/.local/state/replit/agent/.agent_state_2e2f085fec1e4087021c7d73e7c1fd72ac165447.bin deleted file mode 100644 index 3aecd88..0000000 Binary files a/.local/state/replit/agent/.agent_state_2e2f085fec1e4087021c7d73e7c1fd72ac165447.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2f1522c8b88d73602d8622c206b18d71d13d6202.bin b/.local/state/replit/agent/.agent_state_2f1522c8b88d73602d8622c206b18d71d13d6202.bin deleted file mode 100644 index 689acd0..0000000 Binary files a/.local/state/replit/agent/.agent_state_2f1522c8b88d73602d8622c206b18d71d13d6202.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_2fcf23931447c7a27bb83a0887f41eab07ed9e0e.bin b/.local/state/replit/agent/.agent_state_2fcf23931447c7a27bb83a0887f41eab07ed9e0e.bin deleted file mode 100644 index ad52fa3..0000000 Binary files a/.local/state/replit/agent/.agent_state_2fcf23931447c7a27bb83a0887f41eab07ed9e0e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_30522106c999b9141b18d9febc8d7727662f194d.bin b/.local/state/replit/agent/.agent_state_30522106c999b9141b18d9febc8d7727662f194d.bin deleted file mode 100644 index 1fda9de..0000000 Binary files a/.local/state/replit/agent/.agent_state_30522106c999b9141b18d9febc8d7727662f194d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_307758ad40dc521dad037e3eb24c99bbd96d3a90.bin b/.local/state/replit/agent/.agent_state_307758ad40dc521dad037e3eb24c99bbd96d3a90.bin deleted file mode 100644 index 616d6a7..0000000 Binary files a/.local/state/replit/agent/.agent_state_307758ad40dc521dad037e3eb24c99bbd96d3a90.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_30a2a2e1359bf168b9f117d354a50e0e812afd74.bin b/.local/state/replit/agent/.agent_state_30a2a2e1359bf168b9f117d354a50e0e812afd74.bin deleted file mode 100644 index b8e1e4b..0000000 Binary files a/.local/state/replit/agent/.agent_state_30a2a2e1359bf168b9f117d354a50e0e812afd74.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_32dff6e28577bb3a3d79b1487b4cca9c7c089e7d.bin b/.local/state/replit/agent/.agent_state_32dff6e28577bb3a3d79b1487b4cca9c7c089e7d.bin deleted file mode 100644 index f03e4f0..0000000 Binary files a/.local/state/replit/agent/.agent_state_32dff6e28577bb3a3d79b1487b4cca9c7c089e7d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_333c7a12fb8a792c243d1abc1f3acc1b995c7cff.bin b/.local/state/replit/agent/.agent_state_333c7a12fb8a792c243d1abc1f3acc1b995c7cff.bin deleted file mode 100644 index 41eb702..0000000 Binary files a/.local/state/replit/agent/.agent_state_333c7a12fb8a792c243d1abc1f3acc1b995c7cff.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_33d3fefdd7bc28f940f13e260677b0a7fa237d4e.bin b/.local/state/replit/agent/.agent_state_33d3fefdd7bc28f940f13e260677b0a7fa237d4e.bin deleted file mode 100644 index 890aa70..0000000 Binary files a/.local/state/replit/agent/.agent_state_33d3fefdd7bc28f940f13e260677b0a7fa237d4e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_341dbd4b7daf24f4f61d2a0c7fe1e4cf05fa1e05.bin b/.local/state/replit/agent/.agent_state_341dbd4b7daf24f4f61d2a0c7fe1e4cf05fa1e05.bin deleted file mode 100644 index 6e3f2ee..0000000 Binary files a/.local/state/replit/agent/.agent_state_341dbd4b7daf24f4f61d2a0c7fe1e4cf05fa1e05.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3456ba785eb0c4f0894888ce7ec9ac8908d52a55.bin b/.local/state/replit/agent/.agent_state_3456ba785eb0c4f0894888ce7ec9ac8908d52a55.bin deleted file mode 100644 index ef7b4ef..0000000 Binary files a/.local/state/replit/agent/.agent_state_3456ba785eb0c4f0894888ce7ec9ac8908d52a55.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_34c370399a2550929c24e5b3508422ae61e93bb4.bin b/.local/state/replit/agent/.agent_state_34c370399a2550929c24e5b3508422ae61e93bb4.bin deleted file mode 100644 index 11d1c86..0000000 Binary files a/.local/state/replit/agent/.agent_state_34c370399a2550929c24e5b3508422ae61e93bb4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_34daef79210b2cae353dd139f5292525e2cf5074.bin b/.local/state/replit/agent/.agent_state_34daef79210b2cae353dd139f5292525e2cf5074.bin deleted file mode 100644 index 99661f8..0000000 Binary files a/.local/state/replit/agent/.agent_state_34daef79210b2cae353dd139f5292525e2cf5074.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_34fb5694bcd78c35be1d88425385a263f180e6a2.bin b/.local/state/replit/agent/.agent_state_34fb5694bcd78c35be1d88425385a263f180e6a2.bin deleted file mode 100644 index f388f54..0000000 Binary files a/.local/state/replit/agent/.agent_state_34fb5694bcd78c35be1d88425385a263f180e6a2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3537d2422a38d47b6cb572b0ffd8562c45610b7f.bin b/.local/state/replit/agent/.agent_state_3537d2422a38d47b6cb572b0ffd8562c45610b7f.bin deleted file mode 100644 index 805c2f3..0000000 Binary files a/.local/state/replit/agent/.agent_state_3537d2422a38d47b6cb572b0ffd8562c45610b7f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_369fc90d2e0835aa1b691a59c91870481aa2ac2e.bin b/.local/state/replit/agent/.agent_state_369fc90d2e0835aa1b691a59c91870481aa2ac2e.bin deleted file mode 100644 index b07f3e8..0000000 Binary files a/.local/state/replit/agent/.agent_state_369fc90d2e0835aa1b691a59c91870481aa2ac2e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_36e6a964a23f94040bee1d5f91b05cf2f0044fe7.bin b/.local/state/replit/agent/.agent_state_36e6a964a23f94040bee1d5f91b05cf2f0044fe7.bin deleted file mode 100644 index de09225..0000000 Binary files a/.local/state/replit/agent/.agent_state_36e6a964a23f94040bee1d5f91b05cf2f0044fe7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_371a19ec974abd7f1fa37d50cd4bcfabe5dd4145.bin b/.local/state/replit/agent/.agent_state_371a19ec974abd7f1fa37d50cd4bcfabe5dd4145.bin deleted file mode 100644 index 0633b9c..0000000 Binary files a/.local/state/replit/agent/.agent_state_371a19ec974abd7f1fa37d50cd4bcfabe5dd4145.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3866eb2a4c0baaf254dab854b8404e6fb6add4d3.bin b/.local/state/replit/agent/.agent_state_3866eb2a4c0baaf254dab854b8404e6fb6add4d3.bin deleted file mode 100644 index 7379d7b..0000000 Binary files a/.local/state/replit/agent/.agent_state_3866eb2a4c0baaf254dab854b8404e6fb6add4d3.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_39a860c4c0141047179d655651a5742c4e1cdba2.bin b/.local/state/replit/agent/.agent_state_39a860c4c0141047179d655651a5742c4e1cdba2.bin deleted file mode 100644 index 5f6da48..0000000 Binary files a/.local/state/replit/agent/.agent_state_39a860c4c0141047179d655651a5742c4e1cdba2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_39b881b0db55fe7b523b7a41adf3d06f1c6925f6.bin b/.local/state/replit/agent/.agent_state_39b881b0db55fe7b523b7a41adf3d06f1c6925f6.bin deleted file mode 100644 index 9e06453..0000000 Binary files a/.local/state/replit/agent/.agent_state_39b881b0db55fe7b523b7a41adf3d06f1c6925f6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_39c127dd3d01a397986a7f5894f00f767b77c594.bin b/.local/state/replit/agent/.agent_state_39c127dd3d01a397986a7f5894f00f767b77c594.bin deleted file mode 100644 index f3144b6..0000000 Binary files a/.local/state/replit/agent/.agent_state_39c127dd3d01a397986a7f5894f00f767b77c594.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3a10807d0b0df2f5e36c8e132f56a372127a835a.bin b/.local/state/replit/agent/.agent_state_3a10807d0b0df2f5e36c8e132f56a372127a835a.bin deleted file mode 100644 index a15fb15..0000000 Binary files a/.local/state/replit/agent/.agent_state_3a10807d0b0df2f5e36c8e132f56a372127a835a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3c08efefe56755812f3a6ab102a836d965defd8f.bin b/.local/state/replit/agent/.agent_state_3c08efefe56755812f3a6ab102a836d965defd8f.bin deleted file mode 100644 index 55e0288..0000000 Binary files a/.local/state/replit/agent/.agent_state_3c08efefe56755812f3a6ab102a836d965defd8f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3c090336e40c052e259006a991b8b875109b3d28.bin b/.local/state/replit/agent/.agent_state_3c090336e40c052e259006a991b8b875109b3d28.bin deleted file mode 100644 index 69ce4b7..0000000 Binary files a/.local/state/replit/agent/.agent_state_3c090336e40c052e259006a991b8b875109b3d28.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3c4f2a6bc62deb1b7b4071917478e1535433df60.bin b/.local/state/replit/agent/.agent_state_3c4f2a6bc62deb1b7b4071917478e1535433df60.bin deleted file mode 100644 index 47b6cde..0000000 Binary files a/.local/state/replit/agent/.agent_state_3c4f2a6bc62deb1b7b4071917478e1535433df60.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3cd9d35daaadf4b79b3c3fb056ed22cbd31859db.bin b/.local/state/replit/agent/.agent_state_3cd9d35daaadf4b79b3c3fb056ed22cbd31859db.bin deleted file mode 100644 index 1bd5da6..0000000 Binary files a/.local/state/replit/agent/.agent_state_3cd9d35daaadf4b79b3c3fb056ed22cbd31859db.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3d3cad0add141d4a64068718e49b90d712d47121.bin b/.local/state/replit/agent/.agent_state_3d3cad0add141d4a64068718e49b90d712d47121.bin deleted file mode 100644 index 616b869..0000000 Binary files a/.local/state/replit/agent/.agent_state_3d3cad0add141d4a64068718e49b90d712d47121.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3dd7f37659164220ade693730d410266075b22b9.bin b/.local/state/replit/agent/.agent_state_3dd7f37659164220ade693730d410266075b22b9.bin deleted file mode 100644 index ced9457..0000000 Binary files a/.local/state/replit/agent/.agent_state_3dd7f37659164220ade693730d410266075b22b9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3e5601d6b1fc4acf60103bc8765f4388f2e83609.bin b/.local/state/replit/agent/.agent_state_3e5601d6b1fc4acf60103bc8765f4388f2e83609.bin deleted file mode 100644 index 164bff8..0000000 Binary files a/.local/state/replit/agent/.agent_state_3e5601d6b1fc4acf60103bc8765f4388f2e83609.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3e68f4f4961222ceff9ff15ced0974c64d589839.bin b/.local/state/replit/agent/.agent_state_3e68f4f4961222ceff9ff15ced0974c64d589839.bin deleted file mode 100644 index 3c3cd4d..0000000 Binary files a/.local/state/replit/agent/.agent_state_3e68f4f4961222ceff9ff15ced0974c64d589839.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_3f95b7e12c6ae325d8366ee42d12ddcf15e7639e.bin b/.local/state/replit/agent/.agent_state_3f95b7e12c6ae325d8366ee42d12ddcf15e7639e.bin deleted file mode 100644 index 92f6bb3..0000000 Binary files a/.local/state/replit/agent/.agent_state_3f95b7e12c6ae325d8366ee42d12ddcf15e7639e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_40a4c9ef378c4761a59590cc41cfaf350d92959f.bin b/.local/state/replit/agent/.agent_state_40a4c9ef378c4761a59590cc41cfaf350d92959f.bin deleted file mode 100644 index c948b13..0000000 Binary files a/.local/state/replit/agent/.agent_state_40a4c9ef378c4761a59590cc41cfaf350d92959f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_40c73b893678f3389f2fc1f4c7be87d441aacedd.bin b/.local/state/replit/agent/.agent_state_40c73b893678f3389f2fc1f4c7be87d441aacedd.bin deleted file mode 100644 index f521db1..0000000 Binary files a/.local/state/replit/agent/.agent_state_40c73b893678f3389f2fc1f4c7be87d441aacedd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4164af96c42a4237eeb88ab1df14e05d1ded6f60.bin b/.local/state/replit/agent/.agent_state_4164af96c42a4237eeb88ab1df14e05d1ded6f60.bin deleted file mode 100644 index 3b51858..0000000 Binary files a/.local/state/replit/agent/.agent_state_4164af96c42a4237eeb88ab1df14e05d1ded6f60.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_416c4f800a5b1904334dbb2cf09f3c03bbdc9572.bin b/.local/state/replit/agent/.agent_state_416c4f800a5b1904334dbb2cf09f3c03bbdc9572.bin deleted file mode 100644 index b825040..0000000 Binary files a/.local/state/replit/agent/.agent_state_416c4f800a5b1904334dbb2cf09f3c03bbdc9572.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_41e17d4430c66023841a0ad1228e5f3d167f1789.bin b/.local/state/replit/agent/.agent_state_41e17d4430c66023841a0ad1228e5f3d167f1789.bin deleted file mode 100644 index 1c4f509..0000000 Binary files a/.local/state/replit/agent/.agent_state_41e17d4430c66023841a0ad1228e5f3d167f1789.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_421b5fc19ebe3c75099bd935cc01eb6b627ca203.bin b/.local/state/replit/agent/.agent_state_421b5fc19ebe3c75099bd935cc01eb6b627ca203.bin deleted file mode 100644 index 7badb16..0000000 Binary files a/.local/state/replit/agent/.agent_state_421b5fc19ebe3c75099bd935cc01eb6b627ca203.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4312a93fae351c4ae20c3e11765781b2e36cee0f.bin b/.local/state/replit/agent/.agent_state_4312a93fae351c4ae20c3e11765781b2e36cee0f.bin deleted file mode 100644 index 54ff303..0000000 Binary files a/.local/state/replit/agent/.agent_state_4312a93fae351c4ae20c3e11765781b2e36cee0f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_431a835848adf3195c14f9f03fdf22a508a00b4f.bin b/.local/state/replit/agent/.agent_state_431a835848adf3195c14f9f03fdf22a508a00b4f.bin deleted file mode 100644 index de13814..0000000 Binary files a/.local/state/replit/agent/.agent_state_431a835848adf3195c14f9f03fdf22a508a00b4f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_438df744b8c4d3e18a09fc61f167bb2a970db14c.bin b/.local/state/replit/agent/.agent_state_438df744b8c4d3e18a09fc61f167bb2a970db14c.bin deleted file mode 100644 index 19c9bf5..0000000 Binary files a/.local/state/replit/agent/.agent_state_438df744b8c4d3e18a09fc61f167bb2a970db14c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_44fa6544c263b2815d68c02c309bbbd184c1972e.bin b/.local/state/replit/agent/.agent_state_44fa6544c263b2815d68c02c309bbbd184c1972e.bin deleted file mode 100644 index 5853d79..0000000 Binary files a/.local/state/replit/agent/.agent_state_44fa6544c263b2815d68c02c309bbbd184c1972e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4650ac88f0e2db3f8b95bb3cdf9db74d892eaf71.bin b/.local/state/replit/agent/.agent_state_4650ac88f0e2db3f8b95bb3cdf9db74d892eaf71.bin deleted file mode 100644 index 5ceb4e7..0000000 Binary files a/.local/state/replit/agent/.agent_state_4650ac88f0e2db3f8b95bb3cdf9db74d892eaf71.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_47e08c39d710a5b44e5a3bc3d96a56be5c01173c.bin b/.local/state/replit/agent/.agent_state_47e08c39d710a5b44e5a3bc3d96a56be5c01173c.bin deleted file mode 100644 index 4fd8139..0000000 Binary files a/.local/state/replit/agent/.agent_state_47e08c39d710a5b44e5a3bc3d96a56be5c01173c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_48263d0391c08bdf2ca93ad75a7ab2dc3197f92e.bin b/.local/state/replit/agent/.agent_state_48263d0391c08bdf2ca93ad75a7ab2dc3197f92e.bin deleted file mode 100644 index 2dda9ae..0000000 Binary files a/.local/state/replit/agent/.agent_state_48263d0391c08bdf2ca93ad75a7ab2dc3197f92e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_48afc7498158a883e6b564bd2ed47fd6737eeeae.bin b/.local/state/replit/agent/.agent_state_48afc7498158a883e6b564bd2ed47fd6737eeeae.bin deleted file mode 100644 index ad12683..0000000 Binary files a/.local/state/replit/agent/.agent_state_48afc7498158a883e6b564bd2ed47fd6737eeeae.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_49e350358fe19d2cd2e472c452f62aba0a1d6a39.bin b/.local/state/replit/agent/.agent_state_49e350358fe19d2cd2e472c452f62aba0a1d6a39.bin deleted file mode 100644 index 034f8a9..0000000 Binary files a/.local/state/replit/agent/.agent_state_49e350358fe19d2cd2e472c452f62aba0a1d6a39.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_49e70c533858bcc55a748f1babe926cea73f2561.bin b/.local/state/replit/agent/.agent_state_49e70c533858bcc55a748f1babe926cea73f2561.bin deleted file mode 100644 index 72504d4..0000000 Binary files a/.local/state/replit/agent/.agent_state_49e70c533858bcc55a748f1babe926cea73f2561.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4a8333e4a7bd727fe5eb2847c32894e77d4647fa.bin b/.local/state/replit/agent/.agent_state_4a8333e4a7bd727fe5eb2847c32894e77d4647fa.bin deleted file mode 100644 index 78b99bc..0000000 Binary files a/.local/state/replit/agent/.agent_state_4a8333e4a7bd727fe5eb2847c32894e77d4647fa.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4b1690e0352be406dd91a0d30a2f74f3455fdd3c.bin b/.local/state/replit/agent/.agent_state_4b1690e0352be406dd91a0d30a2f74f3455fdd3c.bin deleted file mode 100644 index 895db4a..0000000 Binary files a/.local/state/replit/agent/.agent_state_4b1690e0352be406dd91a0d30a2f74f3455fdd3c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4c7187808c657993ed91054d1cdcce9a7b601ef2.bin b/.local/state/replit/agent/.agent_state_4c7187808c657993ed91054d1cdcce9a7b601ef2.bin deleted file mode 100644 index 22c0ffb..0000000 Binary files a/.local/state/replit/agent/.agent_state_4c7187808c657993ed91054d1cdcce9a7b601ef2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4ccaa7adcfa70e54ddc3baf2a0daebfccb94f0a6.bin b/.local/state/replit/agent/.agent_state_4ccaa7adcfa70e54ddc3baf2a0daebfccb94f0a6.bin deleted file mode 100644 index 6ac89fa..0000000 Binary files a/.local/state/replit/agent/.agent_state_4ccaa7adcfa70e54ddc3baf2a0daebfccb94f0a6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4ccc82625258f7da951afab3d815ec1d7d2ea27b.bin b/.local/state/replit/agent/.agent_state_4ccc82625258f7da951afab3d815ec1d7d2ea27b.bin deleted file mode 100644 index 25e966d..0000000 Binary files a/.local/state/replit/agent/.agent_state_4ccc82625258f7da951afab3d815ec1d7d2ea27b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4d0c30006043864f6bb34d26d6389ad8a9a097a4.bin b/.local/state/replit/agent/.agent_state_4d0c30006043864f6bb34d26d6389ad8a9a097a4.bin deleted file mode 100644 index 4af433f..0000000 Binary files a/.local/state/replit/agent/.agent_state_4d0c30006043864f6bb34d26d6389ad8a9a097a4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4d1d297d7ed4293bd5c71a1655917f5d7b3a16cf.bin b/.local/state/replit/agent/.agent_state_4d1d297d7ed4293bd5c71a1655917f5d7b3a16cf.bin deleted file mode 100644 index 5924164..0000000 Binary files a/.local/state/replit/agent/.agent_state_4d1d297d7ed4293bd5c71a1655917f5d7b3a16cf.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4d54e13d73573a13da7f0e877b0d83ef5beb47a5.bin b/.local/state/replit/agent/.agent_state_4d54e13d73573a13da7f0e877b0d83ef5beb47a5.bin deleted file mode 100644 index 79bc315..0000000 Binary files a/.local/state/replit/agent/.agent_state_4d54e13d73573a13da7f0e877b0d83ef5beb47a5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4d83aa551304de0eb58369f959ece2c1f9179c51.bin b/.local/state/replit/agent/.agent_state_4d83aa551304de0eb58369f959ece2c1f9179c51.bin deleted file mode 100644 index 7be8f02..0000000 Binary files a/.local/state/replit/agent/.agent_state_4d83aa551304de0eb58369f959ece2c1f9179c51.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4d9bfa9a4c365961f03258a5f2d7b6e9cf308603.bin b/.local/state/replit/agent/.agent_state_4d9bfa9a4c365961f03258a5f2d7b6e9cf308603.bin deleted file mode 100644 index 271f485..0000000 Binary files a/.local/state/replit/agent/.agent_state_4d9bfa9a4c365961f03258a5f2d7b6e9cf308603.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_4f0d9fe5fe070ddd8ae328e3c02b0dfae2e37224.bin b/.local/state/replit/agent/.agent_state_4f0d9fe5fe070ddd8ae328e3c02b0dfae2e37224.bin deleted file mode 100644 index 1a54dd9..0000000 Binary files a/.local/state/replit/agent/.agent_state_4f0d9fe5fe070ddd8ae328e3c02b0dfae2e37224.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_50cf67c2fdbe3d9b9c71072659a17e3d277c1273.bin b/.local/state/replit/agent/.agent_state_50cf67c2fdbe3d9b9c71072659a17e3d277c1273.bin deleted file mode 100644 index 3228642..0000000 Binary files a/.local/state/replit/agent/.agent_state_50cf67c2fdbe3d9b9c71072659a17e3d277c1273.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_51ab1e2fc0d62a0b348a0c44bac69dfb91421f04.bin b/.local/state/replit/agent/.agent_state_51ab1e2fc0d62a0b348a0c44bac69dfb91421f04.bin deleted file mode 100644 index 3307918..0000000 Binary files a/.local/state/replit/agent/.agent_state_51ab1e2fc0d62a0b348a0c44bac69dfb91421f04.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_52407a9c09f8445855678aafba813d9090154d36.bin b/.local/state/replit/agent/.agent_state_52407a9c09f8445855678aafba813d9090154d36.bin deleted file mode 100644 index 06de360..0000000 Binary files a/.local/state/replit/agent/.agent_state_52407a9c09f8445855678aafba813d9090154d36.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_52917732582fdcd0379a9fc7432a36cc379d63e8.bin b/.local/state/replit/agent/.agent_state_52917732582fdcd0379a9fc7432a36cc379d63e8.bin deleted file mode 100644 index 6c32aee..0000000 Binary files a/.local/state/replit/agent/.agent_state_52917732582fdcd0379a9fc7432a36cc379d63e8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_52d4312d08669c89a21f1cccfee3021241c641e1.bin b/.local/state/replit/agent/.agent_state_52d4312d08669c89a21f1cccfee3021241c641e1.bin deleted file mode 100644 index 049b3eb..0000000 Binary files a/.local/state/replit/agent/.agent_state_52d4312d08669c89a21f1cccfee3021241c641e1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_52dc8b02664e80354b6a79be5705336f6356731a.bin b/.local/state/replit/agent/.agent_state_52dc8b02664e80354b6a79be5705336f6356731a.bin deleted file mode 100644 index 0b7537b..0000000 Binary files a/.local/state/replit/agent/.agent_state_52dc8b02664e80354b6a79be5705336f6356731a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_56112fc92d42ebc2630b0dcb2417cce6c875f121.bin b/.local/state/replit/agent/.agent_state_56112fc92d42ebc2630b0dcb2417cce6c875f121.bin deleted file mode 100644 index dd852ef..0000000 Binary files a/.local/state/replit/agent/.agent_state_56112fc92d42ebc2630b0dcb2417cce6c875f121.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_57194358b3afa00d13cd78b4a7bc0647fff9435d.bin b/.local/state/replit/agent/.agent_state_57194358b3afa00d13cd78b4a7bc0647fff9435d.bin deleted file mode 100644 index 90eff7a..0000000 Binary files a/.local/state/replit/agent/.agent_state_57194358b3afa00d13cd78b4a7bc0647fff9435d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_57eb24f512c1bd2e912ccfc274577dcefb9bea71.bin b/.local/state/replit/agent/.agent_state_57eb24f512c1bd2e912ccfc274577dcefb9bea71.bin deleted file mode 100644 index fc4a3b5..0000000 Binary files a/.local/state/replit/agent/.agent_state_57eb24f512c1bd2e912ccfc274577dcefb9bea71.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_583bca347a5dccb0a58f68ee48b5610905a64e51.bin b/.local/state/replit/agent/.agent_state_583bca347a5dccb0a58f68ee48b5610905a64e51.bin deleted file mode 100644 index cb24675..0000000 Binary files a/.local/state/replit/agent/.agent_state_583bca347a5dccb0a58f68ee48b5610905a64e51.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_584ae103c988016d3a8b25dba54e71efcc1ef883.bin b/.local/state/replit/agent/.agent_state_584ae103c988016d3a8b25dba54e71efcc1ef883.bin deleted file mode 100644 index ad13cd3..0000000 Binary files a/.local/state/replit/agent/.agent_state_584ae103c988016d3a8b25dba54e71efcc1ef883.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_58c813e1cea3342552ffec830055a8b7b705fbd5.bin b/.local/state/replit/agent/.agent_state_58c813e1cea3342552ffec830055a8b7b705fbd5.bin deleted file mode 100644 index 08a921e..0000000 Binary files a/.local/state/replit/agent/.agent_state_58c813e1cea3342552ffec830055a8b7b705fbd5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_58fa90a376253cd6f4e090015691bcfc2798a24b.bin b/.local/state/replit/agent/.agent_state_58fa90a376253cd6f4e090015691bcfc2798a24b.bin deleted file mode 100644 index 1a4d72f..0000000 Binary files a/.local/state/replit/agent/.agent_state_58fa90a376253cd6f4e090015691bcfc2798a24b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_5a8490228ec170abbb514d0d0db56b37bdbd453c.bin b/.local/state/replit/agent/.agent_state_5a8490228ec170abbb514d0d0db56b37bdbd453c.bin deleted file mode 100644 index 9d58dfc..0000000 Binary files a/.local/state/replit/agent/.agent_state_5a8490228ec170abbb514d0d0db56b37bdbd453c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_5b0a814c4b51bc85e5c3d88553497c8c3350f65d.bin b/.local/state/replit/agent/.agent_state_5b0a814c4b51bc85e5c3d88553497c8c3350f65d.bin deleted file mode 100644 index a9693a1..0000000 Binary files a/.local/state/replit/agent/.agent_state_5b0a814c4b51bc85e5c3d88553497c8c3350f65d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_5b6c426510bf25d80ba2e32a5b730c16523d9011.bin b/.local/state/replit/agent/.agent_state_5b6c426510bf25d80ba2e32a5b730c16523d9011.bin deleted file mode 100644 index 77215f8..0000000 Binary files a/.local/state/replit/agent/.agent_state_5b6c426510bf25d80ba2e32a5b730c16523d9011.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_5c1b55d4169c4b31f14511fb0f52411d3a50014f.bin b/.local/state/replit/agent/.agent_state_5c1b55d4169c4b31f14511fb0f52411d3a50014f.bin deleted file mode 100644 index 5ec3828..0000000 Binary files a/.local/state/replit/agent/.agent_state_5c1b55d4169c4b31f14511fb0f52411d3a50014f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_5d43ae7a8432c0622f1506be8c4028f274b93c0f.bin b/.local/state/replit/agent/.agent_state_5d43ae7a8432c0622f1506be8c4028f274b93c0f.bin deleted file mode 100644 index ad20fcb..0000000 Binary files a/.local/state/replit/agent/.agent_state_5d43ae7a8432c0622f1506be8c4028f274b93c0f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_60cc7686a881efad210e147c955afb5398802520.bin b/.local/state/replit/agent/.agent_state_60cc7686a881efad210e147c955afb5398802520.bin deleted file mode 100644 index 9b5212d..0000000 Binary files a/.local/state/replit/agent/.agent_state_60cc7686a881efad210e147c955afb5398802520.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_615a5ee2b9265190211073dfcd47e53c8e5c7972.bin b/.local/state/replit/agent/.agent_state_615a5ee2b9265190211073dfcd47e53c8e5c7972.bin deleted file mode 100644 index 4395b6a..0000000 Binary files a/.local/state/replit/agent/.agent_state_615a5ee2b9265190211073dfcd47e53c8e5c7972.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_61fb9c3c4cc8921760236ca329aaff903fa8e444.bin b/.local/state/replit/agent/.agent_state_61fb9c3c4cc8921760236ca329aaff903fa8e444.bin deleted file mode 100644 index 54c398d..0000000 Binary files a/.local/state/replit/agent/.agent_state_61fb9c3c4cc8921760236ca329aaff903fa8e444.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6286b7c3ddac62c3afa17dd6379cb0b6abcadacf.bin b/.local/state/replit/agent/.agent_state_6286b7c3ddac62c3afa17dd6379cb0b6abcadacf.bin deleted file mode 100644 index f278d03..0000000 Binary files a/.local/state/replit/agent/.agent_state_6286b7c3ddac62c3afa17dd6379cb0b6abcadacf.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_62f8d295a060cca36c3306e025ca60414060ab9e.bin b/.local/state/replit/agent/.agent_state_62f8d295a060cca36c3306e025ca60414060ab9e.bin deleted file mode 100644 index 110f910..0000000 Binary files a/.local/state/replit/agent/.agent_state_62f8d295a060cca36c3306e025ca60414060ab9e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_64a3ee7818161f6a998bf52237e5da3492dcb945.bin b/.local/state/replit/agent/.agent_state_64a3ee7818161f6a998bf52237e5da3492dcb945.bin deleted file mode 100644 index 0c663a0..0000000 Binary files a/.local/state/replit/agent/.agent_state_64a3ee7818161f6a998bf52237e5da3492dcb945.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6525e199fd884275c139105ddd2b6b98a7272e64.bin b/.local/state/replit/agent/.agent_state_6525e199fd884275c139105ddd2b6b98a7272e64.bin deleted file mode 100644 index fbede16..0000000 Binary files a/.local/state/replit/agent/.agent_state_6525e199fd884275c139105ddd2b6b98a7272e64.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_65a3434fdec2f584610c19bb7f15276d402654a5.bin b/.local/state/replit/agent/.agent_state_65a3434fdec2f584610c19bb7f15276d402654a5.bin deleted file mode 100644 index 99e9a7e..0000000 Binary files a/.local/state/replit/agent/.agent_state_65a3434fdec2f584610c19bb7f15276d402654a5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_664355e2211868015f3f3c7a57988d2cfe742ab1.bin b/.local/state/replit/agent/.agent_state_664355e2211868015f3f3c7a57988d2cfe742ab1.bin deleted file mode 100644 index c5b29fc..0000000 Binary files a/.local/state/replit/agent/.agent_state_664355e2211868015f3f3c7a57988d2cfe742ab1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_66584e7eafd2a19b8a87a3e9f8daefa2c8c805e8.bin b/.local/state/replit/agent/.agent_state_66584e7eafd2a19b8a87a3e9f8daefa2c8c805e8.bin deleted file mode 100644 index 9b95fd8..0000000 Binary files a/.local/state/replit/agent/.agent_state_66584e7eafd2a19b8a87a3e9f8daefa2c8c805e8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_678b5f32515a43be172ea8bd36971c607ea66350.bin b/.local/state/replit/agent/.agent_state_678b5f32515a43be172ea8bd36971c607ea66350.bin deleted file mode 100644 index 69115cd..0000000 Binary files a/.local/state/replit/agent/.agent_state_678b5f32515a43be172ea8bd36971c607ea66350.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6827b076a7e11a8b62fcc1ce13863bafa99728f5.bin b/.local/state/replit/agent/.agent_state_6827b076a7e11a8b62fcc1ce13863bafa99728f5.bin deleted file mode 100644 index 0842b94..0000000 Binary files a/.local/state/replit/agent/.agent_state_6827b076a7e11a8b62fcc1ce13863bafa99728f5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_68a62b4add0098a5c545677505d67458294ee7d8.bin b/.local/state/replit/agent/.agent_state_68a62b4add0098a5c545677505d67458294ee7d8.bin deleted file mode 100644 index 02abbb9..0000000 Binary files a/.local/state/replit/agent/.agent_state_68a62b4add0098a5c545677505d67458294ee7d8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_690277dec5f902a4ae33df07a3de88a18949b37f.bin b/.local/state/replit/agent/.agent_state_690277dec5f902a4ae33df07a3de88a18949b37f.bin deleted file mode 100644 index 29155b5..0000000 Binary files a/.local/state/replit/agent/.agent_state_690277dec5f902a4ae33df07a3de88a18949b37f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_69581b33fd0ce8b574f8b222eac9eca8c4bf6952.bin b/.local/state/replit/agent/.agent_state_69581b33fd0ce8b574f8b222eac9eca8c4bf6952.bin deleted file mode 100644 index fc0528c..0000000 Binary files a/.local/state/replit/agent/.agent_state_69581b33fd0ce8b574f8b222eac9eca8c4bf6952.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_695ad086e39bf7e276ae4973bbb27af299cf08fd.bin b/.local/state/replit/agent/.agent_state_695ad086e39bf7e276ae4973bbb27af299cf08fd.bin deleted file mode 100644 index c44ee9e..0000000 Binary files a/.local/state/replit/agent/.agent_state_695ad086e39bf7e276ae4973bbb27af299cf08fd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6b2255143bbb97b5297d24b84d5d8aa49f56d004.bin b/.local/state/replit/agent/.agent_state_6b2255143bbb97b5297d24b84d5d8aa49f56d004.bin deleted file mode 100644 index b087a22..0000000 Binary files a/.local/state/replit/agent/.agent_state_6b2255143bbb97b5297d24b84d5d8aa49f56d004.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6bf8445561396f0b4b7fafef8820ccdc9f127abf.bin b/.local/state/replit/agent/.agent_state_6bf8445561396f0b4b7fafef8820ccdc9f127abf.bin deleted file mode 100644 index 9ce41fd..0000000 Binary files a/.local/state/replit/agent/.agent_state_6bf8445561396f0b4b7fafef8820ccdc9f127abf.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6c46ae779aa5e7a82484cc765faae359d12ffc9e.bin b/.local/state/replit/agent/.agent_state_6c46ae779aa5e7a82484cc765faae359d12ffc9e.bin deleted file mode 100644 index 8594a51..0000000 Binary files a/.local/state/replit/agent/.agent_state_6c46ae779aa5e7a82484cc765faae359d12ffc9e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6daae6f3452eb3a97bdbf645af0f822ff0a6ac37.bin b/.local/state/replit/agent/.agent_state_6daae6f3452eb3a97bdbf645af0f822ff0a6ac37.bin deleted file mode 100644 index fd48a16..0000000 Binary files a/.local/state/replit/agent/.agent_state_6daae6f3452eb3a97bdbf645af0f822ff0a6ac37.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6e2069260b0e4d9528c9bd73ca4f6148c81545b5.bin b/.local/state/replit/agent/.agent_state_6e2069260b0e4d9528c9bd73ca4f6148c81545b5.bin deleted file mode 100644 index 9579f63..0000000 Binary files a/.local/state/replit/agent/.agent_state_6e2069260b0e4d9528c9bd73ca4f6148c81545b5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6e236ff40dd621fcb8378458ea371886e73c498c.bin b/.local/state/replit/agent/.agent_state_6e236ff40dd621fcb8378458ea371886e73c498c.bin deleted file mode 100644 index 8a45c41..0000000 Binary files a/.local/state/replit/agent/.agent_state_6e236ff40dd621fcb8378458ea371886e73c498c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6e8881b9fb0b25ee98cd37acd8e2eab75439b99e.bin b/.local/state/replit/agent/.agent_state_6e8881b9fb0b25ee98cd37acd8e2eab75439b99e.bin deleted file mode 100644 index cd4cfa8..0000000 Binary files a/.local/state/replit/agent/.agent_state_6e8881b9fb0b25ee98cd37acd8e2eab75439b99e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_6f104f82b3d7d9adca7309d98b4575bb740b287e.bin b/.local/state/replit/agent/.agent_state_6f104f82b3d7d9adca7309d98b4575bb740b287e.bin deleted file mode 100644 index 46aebb1..0000000 Binary files a/.local/state/replit/agent/.agent_state_6f104f82b3d7d9adca7309d98b4575bb740b287e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_70c30604e40b1f019ca30023b6a52ae7d961fdd7.bin b/.local/state/replit/agent/.agent_state_70c30604e40b1f019ca30023b6a52ae7d961fdd7.bin deleted file mode 100644 index a96b70e..0000000 Binary files a/.local/state/replit/agent/.agent_state_70c30604e40b1f019ca30023b6a52ae7d961fdd7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7129777be0a40a5f86c9b99887a9431697e08ce0.bin b/.local/state/replit/agent/.agent_state_7129777be0a40a5f86c9b99887a9431697e08ce0.bin deleted file mode 100644 index 7229d91..0000000 Binary files a/.local/state/replit/agent/.agent_state_7129777be0a40a5f86c9b99887a9431697e08ce0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7242d056f1cf450e900493e04ade6f482f6c120e.bin b/.local/state/replit/agent/.agent_state_7242d056f1cf450e900493e04ade6f482f6c120e.bin deleted file mode 100644 index 2d40ea3..0000000 Binary files a/.local/state/replit/agent/.agent_state_7242d056f1cf450e900493e04ade6f482f6c120e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7307e3bb2274cc6ab44bee2cced2f621e251fe45.bin b/.local/state/replit/agent/.agent_state_7307e3bb2274cc6ab44bee2cced2f621e251fe45.bin deleted file mode 100644 index 27bf985..0000000 Binary files a/.local/state/replit/agent/.agent_state_7307e3bb2274cc6ab44bee2cced2f621e251fe45.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_74219c90e29ca29d1f0d0b612220941c4b5e830d.bin b/.local/state/replit/agent/.agent_state_74219c90e29ca29d1f0d0b612220941c4b5e830d.bin deleted file mode 100644 index 6273717..0000000 Binary files a/.local/state/replit/agent/.agent_state_74219c90e29ca29d1f0d0b612220941c4b5e830d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_746eb14c09c87645e286d100bcb776ddcf3cdf44.bin b/.local/state/replit/agent/.agent_state_746eb14c09c87645e286d100bcb776ddcf3cdf44.bin deleted file mode 100644 index b5deeb2..0000000 Binary files a/.local/state/replit/agent/.agent_state_746eb14c09c87645e286d100bcb776ddcf3cdf44.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_75a0ab63771bc0aafe12a7d8f7b425894acc1806.bin b/.local/state/replit/agent/.agent_state_75a0ab63771bc0aafe12a7d8f7b425894acc1806.bin deleted file mode 100644 index b9c2004..0000000 Binary files a/.local/state/replit/agent/.agent_state_75a0ab63771bc0aafe12a7d8f7b425894acc1806.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_75ba98774bf37dbdc7a31b3f01fcb5d65645cd7a.bin b/.local/state/replit/agent/.agent_state_75ba98774bf37dbdc7a31b3f01fcb5d65645cd7a.bin deleted file mode 100644 index 8720c92..0000000 Binary files a/.local/state/replit/agent/.agent_state_75ba98774bf37dbdc7a31b3f01fcb5d65645cd7a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_75d7f3cfbc63480ed4c58a57aa69caa70eb8c791.bin b/.local/state/replit/agent/.agent_state_75d7f3cfbc63480ed4c58a57aa69caa70eb8c791.bin deleted file mode 100644 index 044b3f1..0000000 Binary files a/.local/state/replit/agent/.agent_state_75d7f3cfbc63480ed4c58a57aa69caa70eb8c791.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_75f8d70e7a5e8c3834cd23987e72e57e6a8ff477.bin b/.local/state/replit/agent/.agent_state_75f8d70e7a5e8c3834cd23987e72e57e6a8ff477.bin deleted file mode 100644 index 59eefdd..0000000 Binary files a/.local/state/replit/agent/.agent_state_75f8d70e7a5e8c3834cd23987e72e57e6a8ff477.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_764ea60478c4eddb8cbbe8e6ca7b9f2da44280ea.bin b/.local/state/replit/agent/.agent_state_764ea60478c4eddb8cbbe8e6ca7b9f2da44280ea.bin deleted file mode 100644 index f525e4e..0000000 Binary files a/.local/state/replit/agent/.agent_state_764ea60478c4eddb8cbbe8e6ca7b9f2da44280ea.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_76879791134457f21ef31adda601bb2ca46324c1.bin b/.local/state/replit/agent/.agent_state_76879791134457f21ef31adda601bb2ca46324c1.bin deleted file mode 100644 index 5bb0cad..0000000 Binary files a/.local/state/replit/agent/.agent_state_76879791134457f21ef31adda601bb2ca46324c1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_77545af13fafe18f7a49bf03f31162f242118843.bin b/.local/state/replit/agent/.agent_state_77545af13fafe18f7a49bf03f31162f242118843.bin deleted file mode 100644 index 50710be..0000000 Binary files a/.local/state/replit/agent/.agent_state_77545af13fafe18f7a49bf03f31162f242118843.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_78270e6b59b5ed5fb857e0fd87ee0313523a888e.bin b/.local/state/replit/agent/.agent_state_78270e6b59b5ed5fb857e0fd87ee0313523a888e.bin deleted file mode 100644 index 0d231c1..0000000 Binary files a/.local/state/replit/agent/.agent_state_78270e6b59b5ed5fb857e0fd87ee0313523a888e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_78a9caaab9554e1be1c2d5c0de80bbe4f9ee8d75.bin b/.local/state/replit/agent/.agent_state_78a9caaab9554e1be1c2d5c0de80bbe4f9ee8d75.bin deleted file mode 100644 index 555eb68..0000000 Binary files a/.local/state/replit/agent/.agent_state_78a9caaab9554e1be1c2d5c0de80bbe4f9ee8d75.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_794230bbb78bf9c48db3cbfbf39fe102a19ea03a.bin b/.local/state/replit/agent/.agent_state_794230bbb78bf9c48db3cbfbf39fe102a19ea03a.bin deleted file mode 100644 index b6ca5fe..0000000 Binary files a/.local/state/replit/agent/.agent_state_794230bbb78bf9c48db3cbfbf39fe102a19ea03a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_79ed7c2f391d7b2c7abad8f97b9930177b0784c7.bin b/.local/state/replit/agent/.agent_state_79ed7c2f391d7b2c7abad8f97b9930177b0784c7.bin deleted file mode 100644 index 0fdd263..0000000 Binary files a/.local/state/replit/agent/.agent_state_79ed7c2f391d7b2c7abad8f97b9930177b0784c7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7af82a341e60ad5c6099c89b11e4e92980945c66.bin b/.local/state/replit/agent/.agent_state_7af82a341e60ad5c6099c89b11e4e92980945c66.bin deleted file mode 100644 index bbe2997..0000000 Binary files a/.local/state/replit/agent/.agent_state_7af82a341e60ad5c6099c89b11e4e92980945c66.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7c3ab6b8343d31c7e2556827b0efbd1ec603096f.bin b/.local/state/replit/agent/.agent_state_7c3ab6b8343d31c7e2556827b0efbd1ec603096f.bin deleted file mode 100644 index c1ec242..0000000 Binary files a/.local/state/replit/agent/.agent_state_7c3ab6b8343d31c7e2556827b0efbd1ec603096f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7ccef11be6294581e8606fb7446018232d781b24.bin b/.local/state/replit/agent/.agent_state_7ccef11be6294581e8606fb7446018232d781b24.bin deleted file mode 100644 index 58b2be0..0000000 Binary files a/.local/state/replit/agent/.agent_state_7ccef11be6294581e8606fb7446018232d781b24.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7d316c1eda6ea00c69748a22c7e7f5048b4674ba.bin b/.local/state/replit/agent/.agent_state_7d316c1eda6ea00c69748a22c7e7f5048b4674ba.bin deleted file mode 100644 index fb5d055..0000000 Binary files a/.local/state/replit/agent/.agent_state_7d316c1eda6ea00c69748a22c7e7f5048b4674ba.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7d385268778ba7ac46d2ddfdee474d51bfa9a8c6.bin b/.local/state/replit/agent/.agent_state_7d385268778ba7ac46d2ddfdee474d51bfa9a8c6.bin deleted file mode 100644 index 8494a7f..0000000 Binary files a/.local/state/replit/agent/.agent_state_7d385268778ba7ac46d2ddfdee474d51bfa9a8c6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7e38171a7844ad6cdc03abbde1319d107581dbc6.bin b/.local/state/replit/agent/.agent_state_7e38171a7844ad6cdc03abbde1319d107581dbc6.bin deleted file mode 100644 index f108ffe..0000000 Binary files a/.local/state/replit/agent/.agent_state_7e38171a7844ad6cdc03abbde1319d107581dbc6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7eb43b67fb7fba87da64babedd6de8b841495f1e.bin b/.local/state/replit/agent/.agent_state_7eb43b67fb7fba87da64babedd6de8b841495f1e.bin deleted file mode 100644 index 4a4e2be..0000000 Binary files a/.local/state/replit/agent/.agent_state_7eb43b67fb7fba87da64babedd6de8b841495f1e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7f26511d583b100524bc34a39e512de6725d1a2e.bin b/.local/state/replit/agent/.agent_state_7f26511d583b100524bc34a39e512de6725d1a2e.bin deleted file mode 100644 index 4f37ead..0000000 Binary files a/.local/state/replit/agent/.agent_state_7f26511d583b100524bc34a39e512de6725d1a2e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_7fe1698c4b1f1ffc1af67cc083847c0513b4cbec.bin b/.local/state/replit/agent/.agent_state_7fe1698c4b1f1ffc1af67cc083847c0513b4cbec.bin deleted file mode 100644 index eb5777a..0000000 Binary files a/.local/state/replit/agent/.agent_state_7fe1698c4b1f1ffc1af67cc083847c0513b4cbec.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_806d5bc00ce33f8037d566f732c1b2d67e0acc39.bin b/.local/state/replit/agent/.agent_state_806d5bc00ce33f8037d566f732c1b2d67e0acc39.bin deleted file mode 100644 index 136a093..0000000 Binary files a/.local/state/replit/agent/.agent_state_806d5bc00ce33f8037d566f732c1b2d67e0acc39.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_81103e87da6ec08839a70459ec746152e9534ce3.bin b/.local/state/replit/agent/.agent_state_81103e87da6ec08839a70459ec746152e9534ce3.bin deleted file mode 100644 index 0a9bf75..0000000 Binary files a/.local/state/replit/agent/.agent_state_81103e87da6ec08839a70459ec746152e9534ce3.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_81376e6270044e02840ec813a0c7fd24d7c8727b.bin b/.local/state/replit/agent/.agent_state_81376e6270044e02840ec813a0c7fd24d7c8727b.bin deleted file mode 100644 index 658e83a..0000000 Binary files a/.local/state/replit/agent/.agent_state_81376e6270044e02840ec813a0c7fd24d7c8727b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_816ef2a4a9ad6df75efa84e6ea9df04ebc47192a.bin b/.local/state/replit/agent/.agent_state_816ef2a4a9ad6df75efa84e6ea9df04ebc47192a.bin deleted file mode 100644 index e313ebb..0000000 Binary files a/.local/state/replit/agent/.agent_state_816ef2a4a9ad6df75efa84e6ea9df04ebc47192a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_818e2d0f8ca84588d5dee59627e42c50d355bc3e.bin b/.local/state/replit/agent/.agent_state_818e2d0f8ca84588d5dee59627e42c50d355bc3e.bin deleted file mode 100644 index b34c5fe..0000000 Binary files a/.local/state/replit/agent/.agent_state_818e2d0f8ca84588d5dee59627e42c50d355bc3e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_822d8c438e6a8f36df60b536ae7a7979f46b04c4.bin b/.local/state/replit/agent/.agent_state_822d8c438e6a8f36df60b536ae7a7979f46b04c4.bin deleted file mode 100644 index 431af0a..0000000 Binary files a/.local/state/replit/agent/.agent_state_822d8c438e6a8f36df60b536ae7a7979f46b04c4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8269a22549afbd0d3abad46d87faadeb93d93942.bin b/.local/state/replit/agent/.agent_state_8269a22549afbd0d3abad46d87faadeb93d93942.bin deleted file mode 100644 index 77f10af..0000000 Binary files a/.local/state/replit/agent/.agent_state_8269a22549afbd0d3abad46d87faadeb93d93942.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_839583485657b89dccbef93525b5598fd402bdc7.bin b/.local/state/replit/agent/.agent_state_839583485657b89dccbef93525b5598fd402bdc7.bin deleted file mode 100644 index 5cc12e9..0000000 Binary files a/.local/state/replit/agent/.agent_state_839583485657b89dccbef93525b5598fd402bdc7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_84d1cb1478968a8fa5c415d5769942adbc70c0bd.bin b/.local/state/replit/agent/.agent_state_84d1cb1478968a8fa5c415d5769942adbc70c0bd.bin deleted file mode 100644 index 02a2be7..0000000 Binary files a/.local/state/replit/agent/.agent_state_84d1cb1478968a8fa5c415d5769942adbc70c0bd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_84fd0fcae724d446148d91e181e88112ea62cc20.bin b/.local/state/replit/agent/.agent_state_84fd0fcae724d446148d91e181e88112ea62cc20.bin deleted file mode 100644 index d47c7c9..0000000 Binary files a/.local/state/replit/agent/.agent_state_84fd0fcae724d446148d91e181e88112ea62cc20.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_854fa2c583ff17d8198fe7c44325b35e0662f5df.bin b/.local/state/replit/agent/.agent_state_854fa2c583ff17d8198fe7c44325b35e0662f5df.bin deleted file mode 100644 index 6c30a9f..0000000 Binary files a/.local/state/replit/agent/.agent_state_854fa2c583ff17d8198fe7c44325b35e0662f5df.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_866e961b1913dfb4889feb4e02e8931f8e1a5783.bin b/.local/state/replit/agent/.agent_state_866e961b1913dfb4889feb4e02e8931f8e1a5783.bin deleted file mode 100644 index 0ca85ac..0000000 Binary files a/.local/state/replit/agent/.agent_state_866e961b1913dfb4889feb4e02e8931f8e1a5783.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8690512778e9c33037813a8b3539d35bbcefe267.bin b/.local/state/replit/agent/.agent_state_8690512778e9c33037813a8b3539d35bbcefe267.bin deleted file mode 100644 index 7dd1dde..0000000 Binary files a/.local/state/replit/agent/.agent_state_8690512778e9c33037813a8b3539d35bbcefe267.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8807872af095ce785b8d10f6d94be0d1529c10b7.bin b/.local/state/replit/agent/.agent_state_8807872af095ce785b8d10f6d94be0d1529c10b7.bin deleted file mode 100644 index 1e41111..0000000 Binary files a/.local/state/replit/agent/.agent_state_8807872af095ce785b8d10f6d94be0d1529c10b7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_891b68717196b351488b530a60a45df997d97da9.bin b/.local/state/replit/agent/.agent_state_891b68717196b351488b530a60a45df997d97da9.bin deleted file mode 100644 index 98074f0..0000000 Binary files a/.local/state/replit/agent/.agent_state_891b68717196b351488b530a60a45df997d97da9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_899b50f1f71d7a96bcefa464f9b3e0b72510e9f4.bin b/.local/state/replit/agent/.agent_state_899b50f1f71d7a96bcefa464f9b3e0b72510e9f4.bin deleted file mode 100644 index e225de3..0000000 Binary files a/.local/state/replit/agent/.agent_state_899b50f1f71d7a96bcefa464f9b3e0b72510e9f4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_89b8be96beffb97aa68cbf29f0b6373cfcc2310b.bin b/.local/state/replit/agent/.agent_state_89b8be96beffb97aa68cbf29f0b6373cfcc2310b.bin deleted file mode 100644 index a2e5e0e..0000000 Binary files a/.local/state/replit/agent/.agent_state_89b8be96beffb97aa68cbf29f0b6373cfcc2310b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8a1c5d50903f980610d5f0640467a6d1b57e4ce7.bin b/.local/state/replit/agent/.agent_state_8a1c5d50903f980610d5f0640467a6d1b57e4ce7.bin deleted file mode 100644 index f184843..0000000 Binary files a/.local/state/replit/agent/.agent_state_8a1c5d50903f980610d5f0640467a6d1b57e4ce7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8a343f2c4d73c1266bb3d401778007f18daede20.bin b/.local/state/replit/agent/.agent_state_8a343f2c4d73c1266bb3d401778007f18daede20.bin deleted file mode 100644 index eaab135..0000000 Binary files a/.local/state/replit/agent/.agent_state_8a343f2c4d73c1266bb3d401778007f18daede20.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8b0921b59213d4ed2f81812bc5ecea53e1389a2f.bin b/.local/state/replit/agent/.agent_state_8b0921b59213d4ed2f81812bc5ecea53e1389a2f.bin deleted file mode 100644 index 1663bba..0000000 Binary files a/.local/state/replit/agent/.agent_state_8b0921b59213d4ed2f81812bc5ecea53e1389a2f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8b8999c31da70969f7ef275187ebc18a7bd1e4da.bin b/.local/state/replit/agent/.agent_state_8b8999c31da70969f7ef275187ebc18a7bd1e4da.bin deleted file mode 100644 index 8b86a6f..0000000 Binary files a/.local/state/replit/agent/.agent_state_8b8999c31da70969f7ef275187ebc18a7bd1e4da.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8c3951deed979b53c879d17c3138bc5068b98bc7.bin b/.local/state/replit/agent/.agent_state_8c3951deed979b53c879d17c3138bc5068b98bc7.bin deleted file mode 100644 index ad4e31f..0000000 Binary files a/.local/state/replit/agent/.agent_state_8c3951deed979b53c879d17c3138bc5068b98bc7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8c7f17a622e8a601fd7f21567af65ced039ce291.bin b/.local/state/replit/agent/.agent_state_8c7f17a622e8a601fd7f21567af65ced039ce291.bin deleted file mode 100644 index 8856ba2..0000000 Binary files a/.local/state/replit/agent/.agent_state_8c7f17a622e8a601fd7f21567af65ced039ce291.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8d71c070620805eb58ce783cbdce5988581c986f.bin b/.local/state/replit/agent/.agent_state_8d71c070620805eb58ce783cbdce5988581c986f.bin deleted file mode 100644 index 74e3e06..0000000 Binary files a/.local/state/replit/agent/.agent_state_8d71c070620805eb58ce783cbdce5988581c986f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8e1ede0ec99385f935be6a527d828a03a4942f41.bin b/.local/state/replit/agent/.agent_state_8e1ede0ec99385f935be6a527d828a03a4942f41.bin deleted file mode 100644 index c3ba6c7..0000000 Binary files a/.local/state/replit/agent/.agent_state_8e1ede0ec99385f935be6a527d828a03a4942f41.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8eda39a9d49ab3c1a715347a8b67b396fbbbb457.bin b/.local/state/replit/agent/.agent_state_8eda39a9d49ab3c1a715347a8b67b396fbbbb457.bin deleted file mode 100644 index 8549176..0000000 Binary files a/.local/state/replit/agent/.agent_state_8eda39a9d49ab3c1a715347a8b67b396fbbbb457.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_8fbbe91aa4366c0f1893327fc701024493f06b5d.bin b/.local/state/replit/agent/.agent_state_8fbbe91aa4366c0f1893327fc701024493f06b5d.bin deleted file mode 100644 index e74a36a..0000000 Binary files a/.local/state/replit/agent/.agent_state_8fbbe91aa4366c0f1893327fc701024493f06b5d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_91fec9a4587222b18dbc8dd8a0b49b8d0a57e870.bin b/.local/state/replit/agent/.agent_state_91fec9a4587222b18dbc8dd8a0b49b8d0a57e870.bin deleted file mode 100644 index 167b6b1..0000000 Binary files a/.local/state/replit/agent/.agent_state_91fec9a4587222b18dbc8dd8a0b49b8d0a57e870.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9265333fa1f29dca6eca59964645283703ab6f75.bin b/.local/state/replit/agent/.agent_state_9265333fa1f29dca6eca59964645283703ab6f75.bin deleted file mode 100644 index 307d317..0000000 Binary files a/.local/state/replit/agent/.agent_state_9265333fa1f29dca6eca59964645283703ab6f75.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_92cb783d6fa046c8088685b2e4394dcf45722e29.bin b/.local/state/replit/agent/.agent_state_92cb783d6fa046c8088685b2e4394dcf45722e29.bin deleted file mode 100644 index 4ad1708..0000000 Binary files a/.local/state/replit/agent/.agent_state_92cb783d6fa046c8088685b2e4394dcf45722e29.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9311e6ab95b3a3fd849a13e330daefd9b0112024.bin b/.local/state/replit/agent/.agent_state_9311e6ab95b3a3fd849a13e330daefd9b0112024.bin deleted file mode 100644 index 09196fd..0000000 Binary files a/.local/state/replit/agent/.agent_state_9311e6ab95b3a3fd849a13e330daefd9b0112024.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_934720fcd813f4dae81ad2ccb50de10a2a6a5865.bin b/.local/state/replit/agent/.agent_state_934720fcd813f4dae81ad2ccb50de10a2a6a5865.bin deleted file mode 100644 index 029cb4f..0000000 Binary files a/.local/state/replit/agent/.agent_state_934720fcd813f4dae81ad2ccb50de10a2a6a5865.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_934767315d9878ee46c79c614dfed58c35e0b7f4.bin b/.local/state/replit/agent/.agent_state_934767315d9878ee46c79c614dfed58c35e0b7f4.bin deleted file mode 100644 index 96c0a0d..0000000 Binary files a/.local/state/replit/agent/.agent_state_934767315d9878ee46c79c614dfed58c35e0b7f4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_942f3411bb8571eab9032f8c31d8991540652313.bin b/.local/state/replit/agent/.agent_state_942f3411bb8571eab9032f8c31d8991540652313.bin deleted file mode 100644 index c2a0a3b..0000000 Binary files a/.local/state/replit/agent/.agent_state_942f3411bb8571eab9032f8c31d8991540652313.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_94adc36b8328c7f337e9365b0334af506dde7e42.bin b/.local/state/replit/agent/.agent_state_94adc36b8328c7f337e9365b0334af506dde7e42.bin deleted file mode 100644 index c09ac34..0000000 Binary files a/.local/state/replit/agent/.agent_state_94adc36b8328c7f337e9365b0334af506dde7e42.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9658483d4c7148a067acc6dd15f1570c191bea3c.bin b/.local/state/replit/agent/.agent_state_9658483d4c7148a067acc6dd15f1570c191bea3c.bin deleted file mode 100644 index 281c091..0000000 Binary files a/.local/state/replit/agent/.agent_state_9658483d4c7148a067acc6dd15f1570c191bea3c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_970d24683c03585d5366b174216e50093bbb1324.bin b/.local/state/replit/agent/.agent_state_970d24683c03585d5366b174216e50093bbb1324.bin deleted file mode 100644 index 080ec54..0000000 Binary files a/.local/state/replit/agent/.agent_state_970d24683c03585d5366b174216e50093bbb1324.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_97232589cfdedb907e4967619818125196e93393.bin b/.local/state/replit/agent/.agent_state_97232589cfdedb907e4967619818125196e93393.bin deleted file mode 100644 index 11535a9..0000000 Binary files a/.local/state/replit/agent/.agent_state_97232589cfdedb907e4967619818125196e93393.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9765241931207548113f7cf79be0b894c386bc4e.bin b/.local/state/replit/agent/.agent_state_9765241931207548113f7cf79be0b894c386bc4e.bin deleted file mode 100644 index 240ae16..0000000 Binary files a/.local/state/replit/agent/.agent_state_9765241931207548113f7cf79be0b894c386bc4e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_981b1d1337d9333768212ed5d3c538140920990b.bin b/.local/state/replit/agent/.agent_state_981b1d1337d9333768212ed5d3c538140920990b.bin deleted file mode 100644 index 92b9699..0000000 Binary files a/.local/state/replit/agent/.agent_state_981b1d1337d9333768212ed5d3c538140920990b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_985f7e552bf94741887878c647b13cca5b6880af.bin b/.local/state/replit/agent/.agent_state_985f7e552bf94741887878c647b13cca5b6880af.bin deleted file mode 100644 index 9f81050..0000000 Binary files a/.local/state/replit/agent/.agent_state_985f7e552bf94741887878c647b13cca5b6880af.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_995b23885adf06523f5ae5dfd51b8373b065bef3.bin b/.local/state/replit/agent/.agent_state_995b23885adf06523f5ae5dfd51b8373b065bef3.bin deleted file mode 100644 index faf2453..0000000 Binary files a/.local/state/replit/agent/.agent_state_995b23885adf06523f5ae5dfd51b8373b065bef3.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_99a1ce6e8c1d65063b29dd6066209812e50d8fbf.bin b/.local/state/replit/agent/.agent_state_99a1ce6e8c1d65063b29dd6066209812e50d8fbf.bin deleted file mode 100644 index 0f20731..0000000 Binary files a/.local/state/replit/agent/.agent_state_99a1ce6e8c1d65063b29dd6066209812e50d8fbf.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9b30f2c8e557c01d219f1c02cc1300faf71687aa.bin b/.local/state/replit/agent/.agent_state_9b30f2c8e557c01d219f1c02cc1300faf71687aa.bin deleted file mode 100644 index 9b8b569..0000000 Binary files a/.local/state/replit/agent/.agent_state_9b30f2c8e557c01d219f1c02cc1300faf71687aa.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9bf4d23ce07e5592f2a99ce5427f001aa064696e.bin b/.local/state/replit/agent/.agent_state_9bf4d23ce07e5592f2a99ce5427f001aa064696e.bin deleted file mode 100644 index e9a03d3..0000000 Binary files a/.local/state/replit/agent/.agent_state_9bf4d23ce07e5592f2a99ce5427f001aa064696e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9bff9b9adf27738bcb13f04fdad67be2d27cc93e.bin b/.local/state/replit/agent/.agent_state_9bff9b9adf27738bcb13f04fdad67be2d27cc93e.bin deleted file mode 100644 index 4ec7469..0000000 Binary files a/.local/state/replit/agent/.agent_state_9bff9b9adf27738bcb13f04fdad67be2d27cc93e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9c7aaa4e109bd251073d9275a9d026f27c463017.bin b/.local/state/replit/agent/.agent_state_9c7aaa4e109bd251073d9275a9d026f27c463017.bin deleted file mode 100644 index 6b29546..0000000 Binary files a/.local/state/replit/agent/.agent_state_9c7aaa4e109bd251073d9275a9d026f27c463017.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9d1d9d383c4de0240cba65f3482aa4c55b067434.bin b/.local/state/replit/agent/.agent_state_9d1d9d383c4de0240cba65f3482aa4c55b067434.bin deleted file mode 100644 index 9bc1eaf..0000000 Binary files a/.local/state/replit/agent/.agent_state_9d1d9d383c4de0240cba65f3482aa4c55b067434.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9d293491d37334c7b2e05b3a62999c5c4ae1b1af.bin b/.local/state/replit/agent/.agent_state_9d293491d37334c7b2e05b3a62999c5c4ae1b1af.bin deleted file mode 100644 index 07e1ae4..0000000 Binary files a/.local/state/replit/agent/.agent_state_9d293491d37334c7b2e05b3a62999c5c4ae1b1af.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9d46a9d7fb2206da39bed6ceb7ba0ddb25366fb1.bin b/.local/state/replit/agent/.agent_state_9d46a9d7fb2206da39bed6ceb7ba0ddb25366fb1.bin deleted file mode 100644 index 48bf8fb..0000000 Binary files a/.local/state/replit/agent/.agent_state_9d46a9d7fb2206da39bed6ceb7ba0ddb25366fb1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9d8b19aa70492b9901e6ac073fab457829cd85d4.bin b/.local/state/replit/agent/.agent_state_9d8b19aa70492b9901e6ac073fab457829cd85d4.bin deleted file mode 100644 index 6b7e0ef..0000000 Binary files a/.local/state/replit/agent/.agent_state_9d8b19aa70492b9901e6ac073fab457829cd85d4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9e7c107b0e1a11a8177ea9974453790da7c6fdc1.bin b/.local/state/replit/agent/.agent_state_9e7c107b0e1a11a8177ea9974453790da7c6fdc1.bin deleted file mode 100644 index 8f6def4..0000000 Binary files a/.local/state/replit/agent/.agent_state_9e7c107b0e1a11a8177ea9974453790da7c6fdc1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9ebf7edcf8735e2bca2d0cd2833f7a152767111e.bin b/.local/state/replit/agent/.agent_state_9ebf7edcf8735e2bca2d0cd2833f7a152767111e.bin deleted file mode 100644 index cdfb52e..0000000 Binary files a/.local/state/replit/agent/.agent_state_9ebf7edcf8735e2bca2d0cd2833f7a152767111e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9f1d8b479783fbad7345e727a1f9d7fbd30ccec5.bin b/.local/state/replit/agent/.agent_state_9f1d8b479783fbad7345e727a1f9d7fbd30ccec5.bin deleted file mode 100644 index d096e1e..0000000 Binary files a/.local/state/replit/agent/.agent_state_9f1d8b479783fbad7345e727a1f9d7fbd30ccec5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_9f449d164f6858321657c2aa4b555e3a3aea482d.bin b/.local/state/replit/agent/.agent_state_9f449d164f6858321657c2aa4b555e3a3aea482d.bin deleted file mode 100644 index ecceb8b..0000000 Binary files a/.local/state/replit/agent/.agent_state_9f449d164f6858321657c2aa4b555e3a3aea482d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a040d2e857fa2acb295993281d27139fa8fe1579.bin b/.local/state/replit/agent/.agent_state_a040d2e857fa2acb295993281d27139fa8fe1579.bin deleted file mode 100644 index 7c824e8..0000000 Binary files a/.local/state/replit/agent/.agent_state_a040d2e857fa2acb295993281d27139fa8fe1579.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a0a06858b809f0b242467e4e63140bf7946c243d.bin b/.local/state/replit/agent/.agent_state_a0a06858b809f0b242467e4e63140bf7946c243d.bin deleted file mode 100644 index 88784dd..0000000 Binary files a/.local/state/replit/agent/.agent_state_a0a06858b809f0b242467e4e63140bf7946c243d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a1a81f8db3a8d751da25a6a575a5f7addf1c8ca2.bin b/.local/state/replit/agent/.agent_state_a1a81f8db3a8d751da25a6a575a5f7addf1c8ca2.bin deleted file mode 100644 index f487098..0000000 Binary files a/.local/state/replit/agent/.agent_state_a1a81f8db3a8d751da25a6a575a5f7addf1c8ca2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a1f0ec9c07050d560b74000b8991916848d5f428.bin b/.local/state/replit/agent/.agent_state_a1f0ec9c07050d560b74000b8991916848d5f428.bin deleted file mode 100644 index 2089884..0000000 Binary files a/.local/state/replit/agent/.agent_state_a1f0ec9c07050d560b74000b8991916848d5f428.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a27202c911d514502dadb8dc2f8896ecf05dba26.bin b/.local/state/replit/agent/.agent_state_a27202c911d514502dadb8dc2f8896ecf05dba26.bin deleted file mode 100644 index de6d1c3..0000000 Binary files a/.local/state/replit/agent/.agent_state_a27202c911d514502dadb8dc2f8896ecf05dba26.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a288747a7ec8675100ead5186b3b4bc950a71b79.bin b/.local/state/replit/agent/.agent_state_a288747a7ec8675100ead5186b3b4bc950a71b79.bin deleted file mode 100644 index 7103021..0000000 Binary files a/.local/state/replit/agent/.agent_state_a288747a7ec8675100ead5186b3b4bc950a71b79.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a35ea7987c7ec5e0584dc28ca6d66afc5cf98901.bin b/.local/state/replit/agent/.agent_state_a35ea7987c7ec5e0584dc28ca6d66afc5cf98901.bin deleted file mode 100644 index 00959f5..0000000 Binary files a/.local/state/replit/agent/.agent_state_a35ea7987c7ec5e0584dc28ca6d66afc5cf98901.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a576440a5ab05e4bc138118859162d0eae5ff266.bin b/.local/state/replit/agent/.agent_state_a576440a5ab05e4bc138118859162d0eae5ff266.bin deleted file mode 100644 index 94749d0..0000000 Binary files a/.local/state/replit/agent/.agent_state_a576440a5ab05e4bc138118859162d0eae5ff266.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a6080b3d44e4d27ab8648ffb5e0c179e5e767fc0.bin b/.local/state/replit/agent/.agent_state_a6080b3d44e4d27ab8648ffb5e0c179e5e767fc0.bin deleted file mode 100644 index f032a25..0000000 Binary files a/.local/state/replit/agent/.agent_state_a6080b3d44e4d27ab8648ffb5e0c179e5e767fc0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a642b302db1539ab56862ad8f33d19ce9d2f647c.bin b/.local/state/replit/agent/.agent_state_a642b302db1539ab56862ad8f33d19ce9d2f647c.bin deleted file mode 100644 index 2d5f74b..0000000 Binary files a/.local/state/replit/agent/.agent_state_a642b302db1539ab56862ad8f33d19ce9d2f647c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a778726d48e0b80ac156dfe34f6a548906037736.bin b/.local/state/replit/agent/.agent_state_a778726d48e0b80ac156dfe34f6a548906037736.bin deleted file mode 100644 index 33d94a9..0000000 Binary files a/.local/state/replit/agent/.agent_state_a778726d48e0b80ac156dfe34f6a548906037736.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a781fa4c94daa3bbd1d76dfa93cc3327b58f462b.bin b/.local/state/replit/agent/.agent_state_a781fa4c94daa3bbd1d76dfa93cc3327b58f462b.bin deleted file mode 100644 index 3029393..0000000 Binary files a/.local/state/replit/agent/.agent_state_a781fa4c94daa3bbd1d76dfa93cc3327b58f462b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_a974d7917f04facb934f87e06dc7c0e383362aa1.bin b/.local/state/replit/agent/.agent_state_a974d7917f04facb934f87e06dc7c0e383362aa1.bin deleted file mode 100644 index 1e427ad..0000000 Binary files a/.local/state/replit/agent/.agent_state_a974d7917f04facb934f87e06dc7c0e383362aa1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_aa32c287db9909a71f713740056d56b5674d4a5c.bin b/.local/state/replit/agent/.agent_state_aa32c287db9909a71f713740056d56b5674d4a5c.bin deleted file mode 100644 index 629601f..0000000 Binary files a/.local/state/replit/agent/.agent_state_aa32c287db9909a71f713740056d56b5674d4a5c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ab8d5fba165c783a855ff3d89b49326e561040a0.bin b/.local/state/replit/agent/.agent_state_ab8d5fba165c783a855ff3d89b49326e561040a0.bin deleted file mode 100644 index 18aa516..0000000 Binary files a/.local/state/replit/agent/.agent_state_ab8d5fba165c783a855ff3d89b49326e561040a0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_abadefb619fcbfc04ea5d9267fee7e051365d60b.bin b/.local/state/replit/agent/.agent_state_abadefb619fcbfc04ea5d9267fee7e051365d60b.bin deleted file mode 100644 index 3ff242e..0000000 Binary files a/.local/state/replit/agent/.agent_state_abadefb619fcbfc04ea5d9267fee7e051365d60b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_abea3a6a2747228cbd6a1015801a9c079254fcee.bin b/.local/state/replit/agent/.agent_state_abea3a6a2747228cbd6a1015801a9c079254fcee.bin deleted file mode 100644 index cf5dcd3..0000000 Binary files a/.local/state/replit/agent/.agent_state_abea3a6a2747228cbd6a1015801a9c079254fcee.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_acfb19b3d84c41ad0e3b19ae699731f9745c3401.bin b/.local/state/replit/agent/.agent_state_acfb19b3d84c41ad0e3b19ae699731f9745c3401.bin deleted file mode 100644 index 494aad6..0000000 Binary files a/.local/state/replit/agent/.agent_state_acfb19b3d84c41ad0e3b19ae699731f9745c3401.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ad96d60b9b8c43975a0f1ef833ef209f9b7d85ba.bin b/.local/state/replit/agent/.agent_state_ad96d60b9b8c43975a0f1ef833ef209f9b7d85ba.bin deleted file mode 100644 index 76c35e2..0000000 Binary files a/.local/state/replit/agent/.agent_state_ad96d60b9b8c43975a0f1ef833ef209f9b7d85ba.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_adda103f3fc25be255229602c9c022385671dce0.bin b/.local/state/replit/agent/.agent_state_adda103f3fc25be255229602c9c022385671dce0.bin deleted file mode 100644 index df8b149..0000000 Binary files a/.local/state/replit/agent/.agent_state_adda103f3fc25be255229602c9c022385671dce0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ade30f97c0f63bed6746ecae6e6d16832b4a62db.bin b/.local/state/replit/agent/.agent_state_ade30f97c0f63bed6746ecae6e6d16832b4a62db.bin deleted file mode 100644 index 8c51f11..0000000 Binary files a/.local/state/replit/agent/.agent_state_ade30f97c0f63bed6746ecae6e6d16832b4a62db.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_aef2bfcf1ae1f1e34cb26db2f261ced8d0a6f873.bin b/.local/state/replit/agent/.agent_state_aef2bfcf1ae1f1e34cb26db2f261ced8d0a6f873.bin deleted file mode 100644 index 19f325f..0000000 Binary files a/.local/state/replit/agent/.agent_state_aef2bfcf1ae1f1e34cb26db2f261ced8d0a6f873.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_af04b20afb3506a095afaa17e4771200ff6099cf.bin b/.local/state/replit/agent/.agent_state_af04b20afb3506a095afaa17e4771200ff6099cf.bin deleted file mode 100644 index dd5cd62..0000000 Binary files a/.local/state/replit/agent/.agent_state_af04b20afb3506a095afaa17e4771200ff6099cf.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_afa7557fddd8466bbe0ddada5ddeb56ce3b449e6.bin b/.local/state/replit/agent/.agent_state_afa7557fddd8466bbe0ddada5ddeb56ce3b449e6.bin deleted file mode 100644 index d281814..0000000 Binary files a/.local/state/replit/agent/.agent_state_afa7557fddd8466bbe0ddada5ddeb56ce3b449e6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b20c08e8710bafa5a716dce75bd8f616fd8e9d3b.bin b/.local/state/replit/agent/.agent_state_b20c08e8710bafa5a716dce75bd8f616fd8e9d3b.bin deleted file mode 100644 index 70cdc2e..0000000 Binary files a/.local/state/replit/agent/.agent_state_b20c08e8710bafa5a716dce75bd8f616fd8e9d3b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b21064f9e3ef9db02be06db2607d5afdf7ce2b54.bin b/.local/state/replit/agent/.agent_state_b21064f9e3ef9db02be06db2607d5afdf7ce2b54.bin deleted file mode 100644 index 9851a1a..0000000 Binary files a/.local/state/replit/agent/.agent_state_b21064f9e3ef9db02be06db2607d5afdf7ce2b54.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b23eed4c8f541a21a3495de7f548949be1a699e0.bin b/.local/state/replit/agent/.agent_state_b23eed4c8f541a21a3495de7f548949be1a699e0.bin deleted file mode 100644 index 0aeee84..0000000 Binary files a/.local/state/replit/agent/.agent_state_b23eed4c8f541a21a3495de7f548949be1a699e0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b255c84adf604217a901ff05b5607beaea97b9e5.bin b/.local/state/replit/agent/.agent_state_b255c84adf604217a901ff05b5607beaea97b9e5.bin deleted file mode 100644 index 48e76f5..0000000 Binary files a/.local/state/replit/agent/.agent_state_b255c84adf604217a901ff05b5607beaea97b9e5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b305959978ddc4b05c717fa2ea1c1f6cadf2f90a.bin b/.local/state/replit/agent/.agent_state_b305959978ddc4b05c717fa2ea1c1f6cadf2f90a.bin deleted file mode 100644 index 0e7bd83..0000000 Binary files a/.local/state/replit/agent/.agent_state_b305959978ddc4b05c717fa2ea1c1f6cadf2f90a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b3355e07e71b419b4679fe1fc2d667012be722c9.bin b/.local/state/replit/agent/.agent_state_b3355e07e71b419b4679fe1fc2d667012be722c9.bin deleted file mode 100644 index b439840..0000000 Binary files a/.local/state/replit/agent/.agent_state_b3355e07e71b419b4679fe1fc2d667012be722c9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b4894098a8b7ff0b216a3170b794a6202302c284.bin b/.local/state/replit/agent/.agent_state_b4894098a8b7ff0b216a3170b794a6202302c284.bin deleted file mode 100644 index 7bc4918..0000000 Binary files a/.local/state/replit/agent/.agent_state_b4894098a8b7ff0b216a3170b794a6202302c284.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b59d581e349eb362235e2dd3848aab1cb3be6a8c.bin b/.local/state/replit/agent/.agent_state_b59d581e349eb362235e2dd3848aab1cb3be6a8c.bin deleted file mode 100644 index 84cf92c..0000000 Binary files a/.local/state/replit/agent/.agent_state_b59d581e349eb362235e2dd3848aab1cb3be6a8c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b5ddff4e38df08062fea2228b2f6afc41b5b972d.bin b/.local/state/replit/agent/.agent_state_b5ddff4e38df08062fea2228b2f6afc41b5b972d.bin deleted file mode 100644 index aa8a680..0000000 Binary files a/.local/state/replit/agent/.agent_state_b5ddff4e38df08062fea2228b2f6afc41b5b972d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b614a09187e76b5e4de660239adb89461608d4b7.bin b/.local/state/replit/agent/.agent_state_b614a09187e76b5e4de660239adb89461608d4b7.bin deleted file mode 100644 index 72ee8dd..0000000 Binary files a/.local/state/replit/agent/.agent_state_b614a09187e76b5e4de660239adb89461608d4b7.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b66983eda5c8167973419db66292fe2a9773f96f.bin b/.local/state/replit/agent/.agent_state_b66983eda5c8167973419db66292fe2a9773f96f.bin deleted file mode 100644 index b3e8e42..0000000 Binary files a/.local/state/replit/agent/.agent_state_b66983eda5c8167973419db66292fe2a9773f96f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b6ec946f27c09839a2a6741e9799fad8394432a6.bin b/.local/state/replit/agent/.agent_state_b6ec946f27c09839a2a6741e9799fad8394432a6.bin deleted file mode 100644 index 8b32a9c..0000000 Binary files a/.local/state/replit/agent/.agent_state_b6ec946f27c09839a2a6741e9799fad8394432a6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b834881d55fde268cfd917ea344aa99af8b0c75a.bin b/.local/state/replit/agent/.agent_state_b834881d55fde268cfd917ea344aa99af8b0c75a.bin deleted file mode 100644 index 4d3a055..0000000 Binary files a/.local/state/replit/agent/.agent_state_b834881d55fde268cfd917ea344aa99af8b0c75a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b84574c930e7f541d4e0a41cc982979bc2b6434c.bin b/.local/state/replit/agent/.agent_state_b84574c930e7f541d4e0a41cc982979bc2b6434c.bin deleted file mode 100644 index 7e0570b..0000000 Binary files a/.local/state/replit/agent/.agent_state_b84574c930e7f541d4e0a41cc982979bc2b6434c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b884c5715c81d8f21ac6cc48386e02e9b1b85c12.bin b/.local/state/replit/agent/.agent_state_b884c5715c81d8f21ac6cc48386e02e9b1b85c12.bin deleted file mode 100644 index 716ea4f..0000000 Binary files a/.local/state/replit/agent/.agent_state_b884c5715c81d8f21ac6cc48386e02e9b1b85c12.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b8ede6527ba8337341c371ad1aaf51f5517c205e.bin b/.local/state/replit/agent/.agent_state_b8ede6527ba8337341c371ad1aaf51f5517c205e.bin deleted file mode 100644 index 0ea3ac0..0000000 Binary files a/.local/state/replit/agent/.agent_state_b8ede6527ba8337341c371ad1aaf51f5517c205e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_b9985cbe5dbd7823a347e09865d63c0f934fe249.bin b/.local/state/replit/agent/.agent_state_b9985cbe5dbd7823a347e09865d63c0f934fe249.bin deleted file mode 100644 index 349a616..0000000 Binary files a/.local/state/replit/agent/.agent_state_b9985cbe5dbd7823a347e09865d63c0f934fe249.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_baa77711a92274a77d0b924a4c3f9ca546ff3c1d.bin b/.local/state/replit/agent/.agent_state_baa77711a92274a77d0b924a4c3f9ca546ff3c1d.bin deleted file mode 100644 index 55dc2a9..0000000 Binary files a/.local/state/replit/agent/.agent_state_baa77711a92274a77d0b924a4c3f9ca546ff3c1d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_bc923392e1042fc5b99fc6d1346dcc1a455f658b.bin b/.local/state/replit/agent/.agent_state_bc923392e1042fc5b99fc6d1346dcc1a455f658b.bin deleted file mode 100644 index 3312fa5..0000000 Binary files a/.local/state/replit/agent/.agent_state_bc923392e1042fc5b99fc6d1346dcc1a455f658b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_bd857414c57125845d7537483836f30e80717c68.bin b/.local/state/replit/agent/.agent_state_bd857414c57125845d7537483836f30e80717c68.bin deleted file mode 100644 index 4c15037..0000000 Binary files a/.local/state/replit/agent/.agent_state_bd857414c57125845d7537483836f30e80717c68.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_bdba60d1f43d8956923198ef0cca38dcf51748a4.bin b/.local/state/replit/agent/.agent_state_bdba60d1f43d8956923198ef0cca38dcf51748a4.bin deleted file mode 100644 index d104e05..0000000 Binary files a/.local/state/replit/agent/.agent_state_bdba60d1f43d8956923198ef0cca38dcf51748a4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_bdeebcea4fbd6dd01f6594ada77fbf99e862b814.bin b/.local/state/replit/agent/.agent_state_bdeebcea4fbd6dd01f6594ada77fbf99e862b814.bin deleted file mode 100644 index c9eae11..0000000 Binary files a/.local/state/replit/agent/.agent_state_bdeebcea4fbd6dd01f6594ada77fbf99e862b814.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_befad22375b83f2b17e4e2682dd5b8413d63b4fb.bin b/.local/state/replit/agent/.agent_state_befad22375b83f2b17e4e2682dd5b8413d63b4fb.bin deleted file mode 100644 index a20cd5e..0000000 Binary files a/.local/state/replit/agent/.agent_state_befad22375b83f2b17e4e2682dd5b8413d63b4fb.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_bf73d69ea231f478569665611aa3e334a013038b.bin b/.local/state/replit/agent/.agent_state_bf73d69ea231f478569665611aa3e334a013038b.bin deleted file mode 100644 index 060500a..0000000 Binary files a/.local/state/replit/agent/.agent_state_bf73d69ea231f478569665611aa3e334a013038b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c170471c8bbf4761ca40ebfe7c3bcfed88aa154c.bin b/.local/state/replit/agent/.agent_state_c170471c8bbf4761ca40ebfe7c3bcfed88aa154c.bin deleted file mode 100644 index 5bccb83..0000000 Binary files a/.local/state/replit/agent/.agent_state_c170471c8bbf4761ca40ebfe7c3bcfed88aa154c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c1b07a858a79f2486a52705acdebd4486e379881.bin b/.local/state/replit/agent/.agent_state_c1b07a858a79f2486a52705acdebd4486e379881.bin deleted file mode 100644 index e1eef30..0000000 Binary files a/.local/state/replit/agent/.agent_state_c1b07a858a79f2486a52705acdebd4486e379881.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c219088e8008dacc36ea95f8f0b99100b30a695c.bin b/.local/state/replit/agent/.agent_state_c219088e8008dacc36ea95f8f0b99100b30a695c.bin deleted file mode 100644 index 4f7eca0..0000000 Binary files a/.local/state/replit/agent/.agent_state_c219088e8008dacc36ea95f8f0b99100b30a695c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c2781c0802bd9121d4edbcfe86cf42bde13e0cbb.bin b/.local/state/replit/agent/.agent_state_c2781c0802bd9121d4edbcfe86cf42bde13e0cbb.bin deleted file mode 100644 index 52d1104..0000000 Binary files a/.local/state/replit/agent/.agent_state_c2781c0802bd9121d4edbcfe86cf42bde13e0cbb.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c34e8ec05dd4889ed200d639faa648bb5d0a07df.bin b/.local/state/replit/agent/.agent_state_c34e8ec05dd4889ed200d639faa648bb5d0a07df.bin deleted file mode 100644 index cb1c317..0000000 Binary files a/.local/state/replit/agent/.agent_state_c34e8ec05dd4889ed200d639faa648bb5d0a07df.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c36b5bcd14d33fceac7c74cfe458bf126ca4bf10.bin b/.local/state/replit/agent/.agent_state_c36b5bcd14d33fceac7c74cfe458bf126ca4bf10.bin deleted file mode 100644 index b29e5c7..0000000 Binary files a/.local/state/replit/agent/.agent_state_c36b5bcd14d33fceac7c74cfe458bf126ca4bf10.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c445c9f7e0af0a5e2267e4c44c1d9b66ec8c6890.bin b/.local/state/replit/agent/.agent_state_c445c9f7e0af0a5e2267e4c44c1d9b66ec8c6890.bin deleted file mode 100644 index 2b050b1..0000000 Binary files a/.local/state/replit/agent/.agent_state_c445c9f7e0af0a5e2267e4c44c1d9b66ec8c6890.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c473ddf60f8e0c8ce2e65fe0bcf8a1c778956b62.bin b/.local/state/replit/agent/.agent_state_c473ddf60f8e0c8ce2e65fe0bcf8a1c778956b62.bin deleted file mode 100644 index 1d18294..0000000 Binary files a/.local/state/replit/agent/.agent_state_c473ddf60f8e0c8ce2e65fe0bcf8a1c778956b62.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c5e53a4324c8f84ab398414429b438c2fad38e7a.bin b/.local/state/replit/agent/.agent_state_c5e53a4324c8f84ab398414429b438c2fad38e7a.bin deleted file mode 100644 index e24aa94..0000000 Binary files a/.local/state/replit/agent/.agent_state_c5e53a4324c8f84ab398414429b438c2fad38e7a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c62aeae97b63305c19ee09abf18859525de0e253.bin b/.local/state/replit/agent/.agent_state_c62aeae97b63305c19ee09abf18859525de0e253.bin deleted file mode 100644 index adadcad..0000000 Binary files a/.local/state/replit/agent/.agent_state_c62aeae97b63305c19ee09abf18859525de0e253.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c67d770da3b9a1e7fe8d9bf1c7b7296b4138b3a3.bin b/.local/state/replit/agent/.agent_state_c67d770da3b9a1e7fe8d9bf1c7b7296b4138b3a3.bin deleted file mode 100644 index 12d8254..0000000 Binary files a/.local/state/replit/agent/.agent_state_c67d770da3b9a1e7fe8d9bf1c7b7296b4138b3a3.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c70e5b9979a2956d6e026a26c3f04885144e948c.bin b/.local/state/replit/agent/.agent_state_c70e5b9979a2956d6e026a26c3f04885144e948c.bin deleted file mode 100644 index a68fa2f..0000000 Binary files a/.local/state/replit/agent/.agent_state_c70e5b9979a2956d6e026a26c3f04885144e948c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c7a84bda3312447c181e1200c6025988e73d3717.bin b/.local/state/replit/agent/.agent_state_c7a84bda3312447c181e1200c6025988e73d3717.bin deleted file mode 100644 index 98a85ad..0000000 Binary files a/.local/state/replit/agent/.agent_state_c7a84bda3312447c181e1200c6025988e73d3717.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_c8eb132a4a48ba9aed6b747158bf1479df0ccf11.bin b/.local/state/replit/agent/.agent_state_c8eb132a4a48ba9aed6b747158bf1479df0ccf11.bin deleted file mode 100644 index 00d542e..0000000 Binary files a/.local/state/replit/agent/.agent_state_c8eb132a4a48ba9aed6b747158bf1479df0ccf11.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_caae9596865c1ac8152be7dffa7939a1ad391a4b.bin b/.local/state/replit/agent/.agent_state_caae9596865c1ac8152be7dffa7939a1ad391a4b.bin deleted file mode 100644 index f9002ec..0000000 Binary files a/.local/state/replit/agent/.agent_state_caae9596865c1ac8152be7dffa7939a1ad391a4b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cb0546a0c3574a315c530c6300257c7411843419.bin b/.local/state/replit/agent/.agent_state_cb0546a0c3574a315c530c6300257c7411843419.bin deleted file mode 100644 index e30b008..0000000 Binary files a/.local/state/replit/agent/.agent_state_cb0546a0c3574a315c530c6300257c7411843419.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cb3b405bd24f57806f20d98528c1d49f64b2ab72.bin b/.local/state/replit/agent/.agent_state_cb3b405bd24f57806f20d98528c1d49f64b2ab72.bin deleted file mode 100644 index cf57f4d..0000000 Binary files a/.local/state/replit/agent/.agent_state_cb3b405bd24f57806f20d98528c1d49f64b2ab72.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cb4ddd7254433bccfa8a1e2b930ef4681760c867.bin b/.local/state/replit/agent/.agent_state_cb4ddd7254433bccfa8a1e2b930ef4681760c867.bin deleted file mode 100644 index a511313..0000000 Binary files a/.local/state/replit/agent/.agent_state_cb4ddd7254433bccfa8a1e2b930ef4681760c867.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cb5e4ea3b6ec3aeda5f9638a990b07f933a4ee6b.bin b/.local/state/replit/agent/.agent_state_cb5e4ea3b6ec3aeda5f9638a990b07f933a4ee6b.bin deleted file mode 100644 index 0cd2cea..0000000 Binary files a/.local/state/replit/agent/.agent_state_cb5e4ea3b6ec3aeda5f9638a990b07f933a4ee6b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cb9a9a6e36e21ba92ec8cb32ff14c47b146379dd.bin b/.local/state/replit/agent/.agent_state_cb9a9a6e36e21ba92ec8cb32ff14c47b146379dd.bin deleted file mode 100644 index d0a0759..0000000 Binary files a/.local/state/replit/agent/.agent_state_cb9a9a6e36e21ba92ec8cb32ff14c47b146379dd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cc10d40f2f816d39b4cb66ccc1a8b21d9f013dbe.bin b/.local/state/replit/agent/.agent_state_cc10d40f2f816d39b4cb66ccc1a8b21d9f013dbe.bin deleted file mode 100644 index 252af29..0000000 Binary files a/.local/state/replit/agent/.agent_state_cc10d40f2f816d39b4cb66ccc1a8b21d9f013dbe.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ccf244c7b48dfbbabdbaa1222f95f79d9872787d.bin b/.local/state/replit/agent/.agent_state_ccf244c7b48dfbbabdbaa1222f95f79d9872787d.bin deleted file mode 100644 index 9bd72c2..0000000 Binary files a/.local/state/replit/agent/.agent_state_ccf244c7b48dfbbabdbaa1222f95f79d9872787d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ccfda546a34a4301a2d621dbf4f77711574cd1b8.bin b/.local/state/replit/agent/.agent_state_ccfda546a34a4301a2d621dbf4f77711574cd1b8.bin deleted file mode 100644 index 2bbe9c8..0000000 Binary files a/.local/state/replit/agent/.agent_state_ccfda546a34a4301a2d621dbf4f77711574cd1b8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cd796aefaeafd6e373ec519cd86b07897d5e52a6.bin b/.local/state/replit/agent/.agent_state_cd796aefaeafd6e373ec519cd86b07897d5e52a6.bin deleted file mode 100644 index fdaaaa0..0000000 Binary files a/.local/state/replit/agent/.agent_state_cd796aefaeafd6e373ec519cd86b07897d5e52a6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cdd613d5058533c7f978f1cab9d8bdf6a634d544.bin b/.local/state/replit/agent/.agent_state_cdd613d5058533c7f978f1cab9d8bdf6a634d544.bin deleted file mode 100644 index 4536529..0000000 Binary files a/.local/state/replit/agent/.agent_state_cdd613d5058533c7f978f1cab9d8bdf6a634d544.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cf579c7a5600a481ff666d5739e199bb3a7cb63a.bin b/.local/state/replit/agent/.agent_state_cf579c7a5600a481ff666d5739e199bb3a7cb63a.bin deleted file mode 100644 index 89848a3..0000000 Binary files a/.local/state/replit/agent/.agent_state_cf579c7a5600a481ff666d5739e199bb3a7cb63a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cf6157418df545f4eae04a921bf63c42eed6b7fd.bin b/.local/state/replit/agent/.agent_state_cf6157418df545f4eae04a921bf63c42eed6b7fd.bin deleted file mode 100644 index eaa471a..0000000 Binary files a/.local/state/replit/agent/.agent_state_cf6157418df545f4eae04a921bf63c42eed6b7fd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_cf73e452fd2149d35830346acc06ce68e52f2cf8.bin b/.local/state/replit/agent/.agent_state_cf73e452fd2149d35830346acc06ce68e52f2cf8.bin deleted file mode 100644 index 1cdb38b..0000000 Binary files a/.local/state/replit/agent/.agent_state_cf73e452fd2149d35830346acc06ce68e52f2cf8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d00b720764f7bdef5672cc55068a73fcd543c923.bin b/.local/state/replit/agent/.agent_state_d00b720764f7bdef5672cc55068a73fcd543c923.bin deleted file mode 100644 index 16ba572..0000000 Binary files a/.local/state/replit/agent/.agent_state_d00b720764f7bdef5672cc55068a73fcd543c923.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d17d42722a45593236d45cde3866b7fc8e60345b.bin b/.local/state/replit/agent/.agent_state_d17d42722a45593236d45cde3866b7fc8e60345b.bin deleted file mode 100644 index b6d4f3f..0000000 Binary files a/.local/state/replit/agent/.agent_state_d17d42722a45593236d45cde3866b7fc8e60345b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d2558baf1e4e77d3cd16221e8c74241f534f269d.bin b/.local/state/replit/agent/.agent_state_d2558baf1e4e77d3cd16221e8c74241f534f269d.bin deleted file mode 100644 index d7b297c..0000000 Binary files a/.local/state/replit/agent/.agent_state_d2558baf1e4e77d3cd16221e8c74241f534f269d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d2fc2fd0e8d55c5fc133e9da10d7abec310eebe6.bin b/.local/state/replit/agent/.agent_state_d2fc2fd0e8d55c5fc133e9da10d7abec310eebe6.bin deleted file mode 100644 index 0382abd..0000000 Binary files a/.local/state/replit/agent/.agent_state_d2fc2fd0e8d55c5fc133e9da10d7abec310eebe6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d3bad412a7f30c85ebf9b8139ac94d3deaf5ccde.bin b/.local/state/replit/agent/.agent_state_d3bad412a7f30c85ebf9b8139ac94d3deaf5ccde.bin deleted file mode 100644 index e4a1b4f..0000000 Binary files a/.local/state/replit/agent/.agent_state_d3bad412a7f30c85ebf9b8139ac94d3deaf5ccde.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d4a808db49760c565c8e4c1d13e3170913ed5732.bin b/.local/state/replit/agent/.agent_state_d4a808db49760c565c8e4c1d13e3170913ed5732.bin deleted file mode 100644 index a79e379..0000000 Binary files a/.local/state/replit/agent/.agent_state_d4a808db49760c565c8e4c1d13e3170913ed5732.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d9190444be477bd99cf5f80e1a3036790d4323bd.bin b/.local/state/replit/agent/.agent_state_d9190444be477bd99cf5f80e1a3036790d4323bd.bin deleted file mode 100644 index c56ccf3..0000000 Binary files a/.local/state/replit/agent/.agent_state_d9190444be477bd99cf5f80e1a3036790d4323bd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d9762df14d070125e0d4f46a8a00369b217a79d4.bin b/.local/state/replit/agent/.agent_state_d9762df14d070125e0d4f46a8a00369b217a79d4.bin deleted file mode 100644 index b23af81..0000000 Binary files a/.local/state/replit/agent/.agent_state_d9762df14d070125e0d4f46a8a00369b217a79d4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d980d8e26deee798d5b0cba1273db907a0d2017b.bin b/.local/state/replit/agent/.agent_state_d980d8e26deee798d5b0cba1273db907a0d2017b.bin deleted file mode 100644 index a5178c3..0000000 Binary files a/.local/state/replit/agent/.agent_state_d980d8e26deee798d5b0cba1273db907a0d2017b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d99d80fee17679c54d68d5bb64bbd1dcd6c2e36e.bin b/.local/state/replit/agent/.agent_state_d99d80fee17679c54d68d5bb64bbd1dcd6c2e36e.bin deleted file mode 100644 index 9348266..0000000 Binary files a/.local/state/replit/agent/.agent_state_d99d80fee17679c54d68d5bb64bbd1dcd6c2e36e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_d9ffb02087b0a402a683b8c9fade2a957954a2ae.bin b/.local/state/replit/agent/.agent_state_d9ffb02087b0a402a683b8c9fade2a957954a2ae.bin deleted file mode 100644 index c539a4a..0000000 Binary files a/.local/state/replit/agent/.agent_state_d9ffb02087b0a402a683b8c9fade2a957954a2ae.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_db5e65360d90dc4f593688ef4885feb94e2ba045.bin b/.local/state/replit/agent/.agent_state_db5e65360d90dc4f593688ef4885feb94e2ba045.bin deleted file mode 100644 index c821098..0000000 Binary files a/.local/state/replit/agent/.agent_state_db5e65360d90dc4f593688ef4885feb94e2ba045.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dcb015fc6406359bd37a2209ac68ba96d21594a5.bin b/.local/state/replit/agent/.agent_state_dcb015fc6406359bd37a2209ac68ba96d21594a5.bin deleted file mode 100644 index 4f59b57..0000000 Binary files a/.local/state/replit/agent/.agent_state_dcb015fc6406359bd37a2209ac68ba96d21594a5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dcd741050f3438a93a8b883696af65ca57971c87.bin b/.local/state/replit/agent/.agent_state_dcd741050f3438a93a8b883696af65ca57971c87.bin deleted file mode 100644 index 4712457..0000000 Binary files a/.local/state/replit/agent/.agent_state_dcd741050f3438a93a8b883696af65ca57971c87.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dd1c3df10617853121a7518f8e467ccf0770a3a5.bin b/.local/state/replit/agent/.agent_state_dd1c3df10617853121a7518f8e467ccf0770a3a5.bin deleted file mode 100644 index dd5f5b3..0000000 Binary files a/.local/state/replit/agent/.agent_state_dd1c3df10617853121a7518f8e467ccf0770a3a5.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dd7362905b64fcaaf2fdc5f965a7424334046de2.bin b/.local/state/replit/agent/.agent_state_dd7362905b64fcaaf2fdc5f965a7424334046de2.bin deleted file mode 100644 index ac2fa0a..0000000 Binary files a/.local/state/replit/agent/.agent_state_dd7362905b64fcaaf2fdc5f965a7424334046de2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dda876547dcb3ba44c205e7bdce3e06266177918.bin b/.local/state/replit/agent/.agent_state_dda876547dcb3ba44c205e7bdce3e06266177918.bin deleted file mode 100644 index 8657273..0000000 Binary files a/.local/state/replit/agent/.agent_state_dda876547dcb3ba44c205e7bdce3e06266177918.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ddebfd7db878734a443fbdc6eee18712601b6e0b.bin b/.local/state/replit/agent/.agent_state_ddebfd7db878734a443fbdc6eee18712601b6e0b.bin deleted file mode 100644 index 9541bd3..0000000 Binary files a/.local/state/replit/agent/.agent_state_ddebfd7db878734a443fbdc6eee18712601b6e0b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dee4e1d0088b57981e919be6b848e6115890d0b0.bin b/.local/state/replit/agent/.agent_state_dee4e1d0088b57981e919be6b848e6115890d0b0.bin deleted file mode 100644 index b342ca3..0000000 Binary files a/.local/state/replit/agent/.agent_state_dee4e1d0088b57981e919be6b848e6115890d0b0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_def067d072da6394986ee3b31b04816b4b5e5ff4.bin b/.local/state/replit/agent/.agent_state_def067d072da6394986ee3b31b04816b4b5e5ff4.bin deleted file mode 100644 index 7cd4343..0000000 Binary files a/.local/state/replit/agent/.agent_state_def067d072da6394986ee3b31b04816b4b5e5ff4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_df28a37b261d31393a516c4719b577fcf229ed3a.bin b/.local/state/replit/agent/.agent_state_df28a37b261d31393a516c4719b577fcf229ed3a.bin deleted file mode 100644 index 911d8fb..0000000 Binary files a/.local/state/replit/agent/.agent_state_df28a37b261d31393a516c4719b577fcf229ed3a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_df9dff688d6f0b29819ff9a5e52650d8fe96ee69.bin b/.local/state/replit/agent/.agent_state_df9dff688d6f0b29819ff9a5e52650d8fe96ee69.bin deleted file mode 100644 index 3c48780..0000000 Binary files a/.local/state/replit/agent/.agent_state_df9dff688d6f0b29819ff9a5e52650d8fe96ee69.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_dfa0b66934e76dcd36b338982b45b0f4d096e8f9.bin b/.local/state/replit/agent/.agent_state_dfa0b66934e76dcd36b338982b45b0f4d096e8f9.bin deleted file mode 100644 index c825132..0000000 Binary files a/.local/state/replit/agent/.agent_state_dfa0b66934e76dcd36b338982b45b0f4d096e8f9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e083cacb49c9bef12055d7e877327cb02390263d.bin b/.local/state/replit/agent/.agent_state_e083cacb49c9bef12055d7e877327cb02390263d.bin deleted file mode 100644 index 3dc366a..0000000 Binary files a/.local/state/replit/agent/.agent_state_e083cacb49c9bef12055d7e877327cb02390263d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e09a9227337049038b9ef6a51d31ee501f2778d4.bin b/.local/state/replit/agent/.agent_state_e09a9227337049038b9ef6a51d31ee501f2778d4.bin deleted file mode 100644 index 92de7d2..0000000 Binary files a/.local/state/replit/agent/.agent_state_e09a9227337049038b9ef6a51d31ee501f2778d4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e246efcadb369c278d3a4f9048c27f41e1f5c5d8.bin b/.local/state/replit/agent/.agent_state_e246efcadb369c278d3a4f9048c27f41e1f5c5d8.bin deleted file mode 100644 index 626cfcd..0000000 Binary files a/.local/state/replit/agent/.agent_state_e246efcadb369c278d3a4f9048c27f41e1f5c5d8.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e2663a84348e65a1d04d03e1b08668d459e7bf93.bin b/.local/state/replit/agent/.agent_state_e2663a84348e65a1d04d03e1b08668d459e7bf93.bin deleted file mode 100644 index 3b8d208..0000000 Binary files a/.local/state/replit/agent/.agent_state_e2663a84348e65a1d04d03e1b08668d459e7bf93.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e30c320cdae131289ad5beeb8e1046bcb45d2cc1.bin b/.local/state/replit/agent/.agent_state_e30c320cdae131289ad5beeb8e1046bcb45d2cc1.bin deleted file mode 100644 index 1c4aaf2..0000000 Binary files a/.local/state/replit/agent/.agent_state_e30c320cdae131289ad5beeb8e1046bcb45d2cc1.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e357f1d770baa6eeaea7e72b6017505c21c61627.bin b/.local/state/replit/agent/.agent_state_e357f1d770baa6eeaea7e72b6017505c21c61627.bin deleted file mode 100644 index 1bb1c80..0000000 Binary files a/.local/state/replit/agent/.agent_state_e357f1d770baa6eeaea7e72b6017505c21c61627.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e5fba7f5f254ef98d8f550d6492fc896d02c79db.bin b/.local/state/replit/agent/.agent_state_e5fba7f5f254ef98d8f550d6492fc896d02c79db.bin deleted file mode 100644 index 4f3a57b..0000000 Binary files a/.local/state/replit/agent/.agent_state_e5fba7f5f254ef98d8f550d6492fc896d02c79db.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e682e431bc2030cb9ddf0ac11cc188ccc455a4fb.bin b/.local/state/replit/agent/.agent_state_e682e431bc2030cb9ddf0ac11cc188ccc455a4fb.bin deleted file mode 100644 index b3bf577..0000000 Binary files a/.local/state/replit/agent/.agent_state_e682e431bc2030cb9ddf0ac11cc188ccc455a4fb.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e7210052d7642be4d9ba1f7b743466191cac98f9.bin b/.local/state/replit/agent/.agent_state_e7210052d7642be4d9ba1f7b743466191cac98f9.bin deleted file mode 100644 index f76b336..0000000 Binary files a/.local/state/replit/agent/.agent_state_e7210052d7642be4d9ba1f7b743466191cac98f9.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e748f23f3a5d6f8f771856574f07156b248a30ef.bin b/.local/state/replit/agent/.agent_state_e748f23f3a5d6f8f771856574f07156b248a30ef.bin deleted file mode 100644 index 2ebbc4c..0000000 Binary files a/.local/state/replit/agent/.agent_state_e748f23f3a5d6f8f771856574f07156b248a30ef.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_e93ec7eee7f06caff319e0c7f94bc7f6ff4065c6.bin b/.local/state/replit/agent/.agent_state_e93ec7eee7f06caff319e0c7f94bc7f6ff4065c6.bin deleted file mode 100644 index 5a1d99b..0000000 Binary files a/.local/state/replit/agent/.agent_state_e93ec7eee7f06caff319e0c7f94bc7f6ff4065c6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ea1913494da59a82320265236f929a9dd90ad084.bin b/.local/state/replit/agent/.agent_state_ea1913494da59a82320265236f929a9dd90ad084.bin deleted file mode 100644 index b45fd99..0000000 Binary files a/.local/state/replit/agent/.agent_state_ea1913494da59a82320265236f929a9dd90ad084.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ea39ad644ed7d5ae09302c03e22ff8362e2e8926.bin b/.local/state/replit/agent/.agent_state_ea39ad644ed7d5ae09302c03e22ff8362e2e8926.bin deleted file mode 100644 index 0ce56dd..0000000 Binary files a/.local/state/replit/agent/.agent_state_ea39ad644ed7d5ae09302c03e22ff8362e2e8926.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ea963c099cb3c5b4265a630f5c0649d946448f65.bin b/.local/state/replit/agent/.agent_state_ea963c099cb3c5b4265a630f5c0649d946448f65.bin deleted file mode 100644 index 8c496c5..0000000 Binary files a/.local/state/replit/agent/.agent_state_ea963c099cb3c5b4265a630f5c0649d946448f65.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_eb1008beb53783a97aee410947307ea2479e4780.bin b/.local/state/replit/agent/.agent_state_eb1008beb53783a97aee410947307ea2479e4780.bin deleted file mode 100644 index 3b7927c..0000000 Binary files a/.local/state/replit/agent/.agent_state_eb1008beb53783a97aee410947307ea2479e4780.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ebb6422a3d6f039f2c9ccb51ac3935aa32e00ce2.bin b/.local/state/replit/agent/.agent_state_ebb6422a3d6f039f2c9ccb51ac3935aa32e00ce2.bin deleted file mode 100644 index 76ca1ee..0000000 Binary files a/.local/state/replit/agent/.agent_state_ebb6422a3d6f039f2c9ccb51ac3935aa32e00ce2.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ec44707597b70037a68b52ef115a8d166fc2eccc.bin b/.local/state/replit/agent/.agent_state_ec44707597b70037a68b52ef115a8d166fc2eccc.bin deleted file mode 100644 index 13fc8b0..0000000 Binary files a/.local/state/replit/agent/.agent_state_ec44707597b70037a68b52ef115a8d166fc2eccc.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ee129a4cdba774fabf622a0194a9fe94d0a0d483.bin b/.local/state/replit/agent/.agent_state_ee129a4cdba774fabf622a0194a9fe94d0a0d483.bin deleted file mode 100644 index c374529..0000000 Binary files a/.local/state/replit/agent/.agent_state_ee129a4cdba774fabf622a0194a9fe94d0a0d483.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_eea41b2158dcca07e579aebe208a4cc06a356b07.bin b/.local/state/replit/agent/.agent_state_eea41b2158dcca07e579aebe208a4cc06a356b07.bin deleted file mode 100644 index 6b4afe6..0000000 Binary files a/.local/state/replit/agent/.agent_state_eea41b2158dcca07e579aebe208a4cc06a356b07.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ef11be68a8b2b7b5212e868bc23f8007c89adf67.bin b/.local/state/replit/agent/.agent_state_ef11be68a8b2b7b5212e868bc23f8007c89adf67.bin deleted file mode 100644 index 1e46b08..0000000 Binary files a/.local/state/replit/agent/.agent_state_ef11be68a8b2b7b5212e868bc23f8007c89adf67.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ef7e49bad792c019d40d6118ca322414e946d051.bin b/.local/state/replit/agent/.agent_state_ef7e49bad792c019d40d6118ca322414e946d051.bin deleted file mode 100644 index 7245f4a..0000000 Binary files a/.local/state/replit/agent/.agent_state_ef7e49bad792c019d40d6118ca322414e946d051.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f02e9882f3a55c840c4d81144cf666e610d33d8f.bin b/.local/state/replit/agent/.agent_state_f02e9882f3a55c840c4d81144cf666e610d33d8f.bin deleted file mode 100644 index 7706d60..0000000 Binary files a/.local/state/replit/agent/.agent_state_f02e9882f3a55c840c4d81144cf666e610d33d8f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f04f2a65a25b15f362a1f61e4bd48c864163603c.bin b/.local/state/replit/agent/.agent_state_f04f2a65a25b15f362a1f61e4bd48c864163603c.bin deleted file mode 100644 index d48f59f..0000000 Binary files a/.local/state/replit/agent/.agent_state_f04f2a65a25b15f362a1f61e4bd48c864163603c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f04f62bcd398f511e673be464043bd6450da1374.bin b/.local/state/replit/agent/.agent_state_f04f62bcd398f511e673be464043bd6450da1374.bin deleted file mode 100644 index 7946d20..0000000 Binary files a/.local/state/replit/agent/.agent_state_f04f62bcd398f511e673be464043bd6450da1374.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f0fd1e5a91159f929f65a9461d07de56c1dc446f.bin b/.local/state/replit/agent/.agent_state_f0fd1e5a91159f929f65a9461d07de56c1dc446f.bin deleted file mode 100644 index 9ccd6a3..0000000 Binary files a/.local/state/replit/agent/.agent_state_f0fd1e5a91159f929f65a9461d07de56c1dc446f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f1e72d462e9cde533e037b796e299e043613150f.bin b/.local/state/replit/agent/.agent_state_f1e72d462e9cde533e037b796e299e043613150f.bin deleted file mode 100644 index 306a1e4..0000000 Binary files a/.local/state/replit/agent/.agent_state_f1e72d462e9cde533e037b796e299e043613150f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f280486122dff011ca9bc2799c72a6318f4435e0.bin b/.local/state/replit/agent/.agent_state_f280486122dff011ca9bc2799c72a6318f4435e0.bin deleted file mode 100644 index bed0ce6..0000000 Binary files a/.local/state/replit/agent/.agent_state_f280486122dff011ca9bc2799c72a6318f4435e0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f2bb9fea63b4364345376dd9811bcabd9a30568d.bin b/.local/state/replit/agent/.agent_state_f2bb9fea63b4364345376dd9811bcabd9a30568d.bin deleted file mode 100644 index 1134860..0000000 Binary files a/.local/state/replit/agent/.agent_state_f2bb9fea63b4364345376dd9811bcabd9a30568d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f3f5507dba177e28227c323dc55ab67d8b18421b.bin b/.local/state/replit/agent/.agent_state_f3f5507dba177e28227c323dc55ab67d8b18421b.bin deleted file mode 100644 index e942e7f..0000000 Binary files a/.local/state/replit/agent/.agent_state_f3f5507dba177e28227c323dc55ab67d8b18421b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f477c3895516f1f757bbdd675d2aac9e0bfc5d1c.bin b/.local/state/replit/agent/.agent_state_f477c3895516f1f757bbdd675d2aac9e0bfc5d1c.bin deleted file mode 100644 index 5eedf34..0000000 Binary files a/.local/state/replit/agent/.agent_state_f477c3895516f1f757bbdd675d2aac9e0bfc5d1c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f5160eff9292cc103472e0d456353c31dc95543d.bin b/.local/state/replit/agent/.agent_state_f5160eff9292cc103472e0d456353c31dc95543d.bin deleted file mode 100644 index 4d0cbda..0000000 Binary files a/.local/state/replit/agent/.agent_state_f5160eff9292cc103472e0d456353c31dc95543d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f65f987b054f7e7188f1f6bbe1701c9ab4241b5e.bin b/.local/state/replit/agent/.agent_state_f65f987b054f7e7188f1f6bbe1701c9ab4241b5e.bin deleted file mode 100644 index aa72ba0..0000000 Binary files a/.local/state/replit/agent/.agent_state_f65f987b054f7e7188f1f6bbe1701c9ab4241b5e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f6ea41d02c01cd9700af6ad82a99f5f0f1cfefa0.bin b/.local/state/replit/agent/.agent_state_f6ea41d02c01cd9700af6ad82a99f5f0f1cfefa0.bin deleted file mode 100644 index 5438dbf..0000000 Binary files a/.local/state/replit/agent/.agent_state_f6ea41d02c01cd9700af6ad82a99f5f0f1cfefa0.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f73626eddb2e8ee1eb287df03f5582ad3b1cda3e.bin b/.local/state/replit/agent/.agent_state_f73626eddb2e8ee1eb287df03f5582ad3b1cda3e.bin deleted file mode 100644 index 2cd43eb..0000000 Binary files a/.local/state/replit/agent/.agent_state_f73626eddb2e8ee1eb287df03f5582ad3b1cda3e.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f79f64cc3a7945d536907ed38e87e729e29d8247.bin b/.local/state/replit/agent/.agent_state_f79f64cc3a7945d536907ed38e87e729e29d8247.bin deleted file mode 100644 index 4dcd6ea..0000000 Binary files a/.local/state/replit/agent/.agent_state_f79f64cc3a7945d536907ed38e87e729e29d8247.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f839b20c5afe17f4294b625a3b8df85258a66c3c.bin b/.local/state/replit/agent/.agent_state_f839b20c5afe17f4294b625a3b8df85258a66c3c.bin deleted file mode 100644 index b075bd1..0000000 Binary files a/.local/state/replit/agent/.agent_state_f839b20c5afe17f4294b625a3b8df85258a66c3c.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f8bd7d2920c6cfad069e12c1368f0da46ed991ce.bin b/.local/state/replit/agent/.agent_state_f8bd7d2920c6cfad069e12c1368f0da46ed991ce.bin deleted file mode 100644 index df82e50..0000000 Binary files a/.local/state/replit/agent/.agent_state_f8bd7d2920c6cfad069e12c1368f0da46ed991ce.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f9163e600ccd2fd78c8b9e4f24f5bcd9797393cc.bin b/.local/state/replit/agent/.agent_state_f9163e600ccd2fd78c8b9e4f24f5bcd9797393cc.bin deleted file mode 100644 index df0b0c2..0000000 Binary files a/.local/state/replit/agent/.agent_state_f9163e600ccd2fd78c8b9e4f24f5bcd9797393cc.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f983758a3a992db12311192fac2dc3df4df14aea.bin b/.local/state/replit/agent/.agent_state_f983758a3a992db12311192fac2dc3df4df14aea.bin deleted file mode 100644 index 9a9fc19..0000000 Binary files a/.local/state/replit/agent/.agent_state_f983758a3a992db12311192fac2dc3df4df14aea.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f98e61d6a48f49fecfbd983070c6adec9b34798a.bin b/.local/state/replit/agent/.agent_state_f98e61d6a48f49fecfbd983070c6adec9b34798a.bin deleted file mode 100644 index 72d5761..0000000 Binary files a/.local/state/replit/agent/.agent_state_f98e61d6a48f49fecfbd983070c6adec9b34798a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_f9bf5c5f557060c425a9e3c11cd87369a5c7c1b3.bin b/.local/state/replit/agent/.agent_state_f9bf5c5f557060c425a9e3c11cd87369a5c7c1b3.bin deleted file mode 100644 index 6dab0bd..0000000 Binary files a/.local/state/replit/agent/.agent_state_f9bf5c5f557060c425a9e3c11cd87369a5c7c1b3.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fa9c05b9fcf7cba959564641189d94239ff2be00.bin b/.local/state/replit/agent/.agent_state_fa9c05b9fcf7cba959564641189d94239ff2be00.bin deleted file mode 100644 index 79be10d..0000000 Binary files a/.local/state/replit/agent/.agent_state_fa9c05b9fcf7cba959564641189d94239ff2be00.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fad06860433a6c3aa97426746cb6ce9d0cb2c94d.bin b/.local/state/replit/agent/.agent_state_fad06860433a6c3aa97426746cb6ce9d0cb2c94d.bin deleted file mode 100644 index 255286b..0000000 Binary files a/.local/state/replit/agent/.agent_state_fad06860433a6c3aa97426746cb6ce9d0cb2c94d.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fb5078c5291efb0f2fac96d55aab8ec129142bd6.bin b/.local/state/replit/agent/.agent_state_fb5078c5291efb0f2fac96d55aab8ec129142bd6.bin deleted file mode 100644 index b0be957..0000000 Binary files a/.local/state/replit/agent/.agent_state_fb5078c5291efb0f2fac96d55aab8ec129142bd6.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fbb9afe0c90eb2b93b3815194459dec987cde9e4.bin b/.local/state/replit/agent/.agent_state_fbb9afe0c90eb2b93b3815194459dec987cde9e4.bin deleted file mode 100644 index 2f633b2..0000000 Binary files a/.local/state/replit/agent/.agent_state_fbb9afe0c90eb2b93b3815194459dec987cde9e4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fcb145754a0dd9ccd3c2de04a71a14a904df23f4.bin b/.local/state/replit/agent/.agent_state_fcb145754a0dd9ccd3c2de04a71a14a904df23f4.bin deleted file mode 100644 index a832cda..0000000 Binary files a/.local/state/replit/agent/.agent_state_fcb145754a0dd9ccd3c2de04a71a14a904df23f4.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fcc18219236cb0889aa0b82b01e41cd4bd0b3d4a.bin b/.local/state/replit/agent/.agent_state_fcc18219236cb0889aa0b82b01e41cd4bd0b3d4a.bin deleted file mode 100644 index 1f3a5ae..0000000 Binary files a/.local/state/replit/agent/.agent_state_fcc18219236cb0889aa0b82b01e41cd4bd0b3d4a.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fcf4e1d10d6b9a4f257f0cd9cb4cf5943d7eaa4b.bin b/.local/state/replit/agent/.agent_state_fcf4e1d10d6b9a4f257f0cd9cb4cf5943d7eaa4b.bin deleted file mode 100644 index 29aebfb..0000000 Binary files a/.local/state/replit/agent/.agent_state_fcf4e1d10d6b9a4f257f0cd9cb4cf5943d7eaa4b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fd1131bda23ac50c8967b1a7192df65dc39f2e09.bin b/.local/state/replit/agent/.agent_state_fd1131bda23ac50c8967b1a7192df65dc39f2e09.bin deleted file mode 100644 index 011460d..0000000 Binary files a/.local/state/replit/agent/.agent_state_fd1131bda23ac50c8967b1a7192df65dc39f2e09.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fd9d4379e36b5bbfd9f8956dfe7ff87fb9363f22.bin b/.local/state/replit/agent/.agent_state_fd9d4379e36b5bbfd9f8956dfe7ff87fb9363f22.bin deleted file mode 100644 index a502a47..0000000 Binary files a/.local/state/replit/agent/.agent_state_fd9d4379e36b5bbfd9f8956dfe7ff87fb9363f22.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fe5a4b2ffcd774be9308d7281e7cd138987fa0dd.bin b/.local/state/replit/agent/.agent_state_fe5a4b2ffcd774be9308d7281e7cd138987fa0dd.bin deleted file mode 100644 index 4d3c0cb..0000000 Binary files a/.local/state/replit/agent/.agent_state_fe5a4b2ffcd774be9308d7281e7cd138987fa0dd.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fe767eb593d7c6851ef73045d8d796c43569972f.bin b/.local/state/replit/agent/.agent_state_fe767eb593d7c6851ef73045d8d796c43569972f.bin deleted file mode 100644 index e00f492..0000000 Binary files a/.local/state/replit/agent/.agent_state_fe767eb593d7c6851ef73045d8d796c43569972f.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fe7dbe5296d109e7cced0cf014f0f15057840b92.bin b/.local/state/replit/agent/.agent_state_fe7dbe5296d109e7cced0cf014f0f15057840b92.bin deleted file mode 100644 index ea8ab04..0000000 Binary files a/.local/state/replit/agent/.agent_state_fe7dbe5296d109e7cced0cf014f0f15057840b92.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_fec3517b626fd3cf03ce9f258fc754eeccf0ce31.bin b/.local/state/replit/agent/.agent_state_fec3517b626fd3cf03ce9f258fc754eeccf0ce31.bin deleted file mode 100644 index 7f153e3..0000000 Binary files a/.local/state/replit/agent/.agent_state_fec3517b626fd3cf03ce9f258fc754eeccf0ce31.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ff04c2167f1e64d355445fc6693913fa0f984eae.bin b/.local/state/replit/agent/.agent_state_ff04c2167f1e64d355445fc6693913fa0f984eae.bin deleted file mode 100644 index 8b1b9e9..0000000 Binary files a/.local/state/replit/agent/.agent_state_ff04c2167f1e64d355445fc6693913fa0f984eae.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_ffc7756ab9236dac1955e4265cd11b50ebfc699b.bin b/.local/state/replit/agent/.agent_state_ffc7756ab9236dac1955e4265cd11b50ebfc699b.bin deleted file mode 100644 index 76b4dd1..0000000 Binary files a/.local/state/replit/agent/.agent_state_ffc7756ab9236dac1955e4265cd11b50ebfc699b.bin and /dev/null differ diff --git a/.local/state/replit/agent/.agent_state_main.bin b/.local/state/replit/agent/.agent_state_main.bin deleted file mode 100644 index 369f9e3..0000000 Binary files a/.local/state/replit/agent/.agent_state_main.bin and /dev/null differ diff --git a/.local/state/replit/agent/.latest.json b/.local/state/replit/agent/.latest.json deleted file mode 100644 index 6a46732..0000000 --- a/.local/state/replit/agent/.latest.json +++ /dev/null @@ -1 +0,0 @@ -{"latest": "main"} \ No newline at end of file diff --git a/.local/state/replit/agent/filesystem/filesystem_state.json b/.local/state/replit/agent/filesystem/filesystem_state.json deleted file mode 100644 index 77374fd..0000000 --- a/.local/state/replit/agent/filesystem/filesystem_state.json +++ /dev/null @@ -1 +0,0 @@ -{"file_contents":{"design_guidelines.md":{"content":"# Mobile News App Design Guidelines\n\n## Design Approach\n**Reference-Based Approach**: Drawing inspiration from modern mobile news apps like Apple News, Google News, and Flipboard, with emphasis on clean typography, intuitive navigation, and content-first design.\n\n## Core Design Elements\n\n### A. Color Palette\n**Primary Colors:**\n- Dark mode: Background 222 15% 8%, Surface 222 15% 12%, Text 210 15% 95%\n- Light mode: Background 0 0% 98%, Surface 0 0% 100%, Text 222 15% 15%\n\n**Accent Colors:**\n- Primary brand: 210 85% 55% (modern blue)\n- Success/active: 142 76% 45% (green for interactions)\n\n### B. Typography\n**Font Stack:** Inter (Google Fonts) for exceptional mobile readability\n- Headlines: 600 weight, 1.2rem-1.8rem\n- Body text: 400 weight, 0.875rem-1rem\n- Captions: 500 weight, 0.75rem-0.825rem\n\n### C. Layout System\n**Spacing Units:** Tailwind units of 2, 4, 6, and 8 (p-2, m-4, gap-6, h-8)\n- Consistent 4-unit grid system for mobile optimization\n- 6-unit spacing for section breaks\n- 2-unit for tight element spacing\n\n### D. Component Library\n\n**Navigation:**\n- Sticky header with search icon, logo, and profile/language selector\n- Bottom tab navigation for main categories (People, Topics, Companies)\n- Swipeable horizontal card carousel on homepage\n\n**Content Cards:**\n- Article preview cards with AI-generated thumbnails (16:9 aspect ratio)\n- Media outlet profile cards with circular avatars and bio sections\n- Consistent card shadows: shadow-sm with subtle elevation\n\n**Interactive Elements:**\n- Search overlay with instant results filtering\n- Language selector dropdown with flag icons\n- Smooth scroll-based pagination for article feeds\n\n**Article Layout:**\n- Full-width hero images with gradient overlays\n- Navigation arrows for previous/next article browsing\n- Floating action buttons for sharing and bookmarking\n\n### E. Mobile-First Considerations\n- Touch-friendly tap targets (minimum 44px)\n- Thumb-zone navigation placement\n- Optimized scroll performance with virtual scrolling\n- Progressive image loading for thumbnails\n\n## Images\n**AI-Generated Thumbnails:** Each article requires a 16:9 landscape thumbnail generated via DALL-E based on article content. Place thumbnails prominently on article cards and as hero images on detail pages.\n\n**Media Outlet Avatars:** Circular profile images (64px) for each media outlet representing their focus area (People: portrait styles, Topics: abstract concepts, Companies: corporate/brand imagery).\n\n**No Large Hero Image:** The design prioritizes content discovery over large hero sections, focusing on article thumbnails and clean typography instead.","size_bytes":2612},"drizzle.config.ts":{"content":"import { defineConfig } from \"drizzle-kit\";\n\nif (!process.env.DATABASE_URL) {\n throw new Error(\"DATABASE_URL, ensure the database is provisioned\");\n}\n\nexport default defineConfig({\n out: \"./migrations\",\n schema: \"./shared/schema.ts\",\n dialect: \"postgresql\",\n dbCredentials: {\n url: process.env.DATABASE_URL,\n },\n});\n","size_bytes":325},"postcss.config.js":{"content":"export default {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n}\n","size_bytes":80},"replit.md":{"content":"# Sapiens Mobile News Platform\n\n## Overview\n\nThis is a mobile-first news application that provides specialized media outlets under the \"Sapiens\" brand. The platform features 11 distinct outlets categorized by People (Jacob Robert Steeves, Ala Shaabana, Joseph Jacks, Robert Myers), Topics (Alt coin, Stable coin, Bittensor), and Companies (xTAO, YUMA, TAOX, Oblong). Each outlet has expandable 3-bullet-point profiles (first bullet always visible, click to expand remaining 2), 20 scrollable articles per outlet, and uses real uploaded images for branding and thumbnails.\n\n## User Preferences\n\nPreferred communication style: Simple, everyday language.\n\n## System Architecture\n\n**Frontend Architecture**: React-based single-page application using Vite as the build tool and TypeScript for type safety. The application follows a mobile-first responsive design approach using Tailwind CSS for styling and shadcn/ui for component library. Navigation is handled by Wouter for client-side routing, with pages for home, outlet details, and individual articles.\n\n**Component Structure**: Modular component architecture with reusable UI components including ArticleCard, OutletCard, MobileHeader, SearchOverlay, SwipeableCarousel, and CategoryTabs. Components are organized with clear separation between UI components, page components, and business logic.\n\n**State Management**: Uses TanStack Query (React Query) for server state management, API calls, and caching. Local state is managed through React hooks for UI interactions like search overlay, language selection, and carousel navigation.\n\n**Backend Architecture**: Express.js server providing RESTful API endpoints for outlets, articles, and search functionality. Uses in-memory storage implementation (MemStorage class) as the data layer with interfaces designed for easy migration to database storage later.\n\n**Data Schema**: Drizzle ORM schema definitions for Users, MediaOutlets, and Articles with PostgreSQL as the intended database. Schema includes support for categories (people/topics/companies), focus subjects, article metadata, and user preferences.\n\n**Mobile-Optimized Design**: Design system based on modern news apps like Apple News and Google News, featuring clean typography with Inter font, consistent spacing using Tailwind's 4-unit grid system, and mobile-specific UI patterns like swipeable carousels and sticky headers.\n\n**Content Management**: Real data implementation provides sample articles and outlets with professional images and real profile photos. Content includes detailed profiles with expandable 3-bullet-point biographies for Jacob Robert Steeves, Ala Shaabana, Joseph Jacks, Robert Myers, and 7 other outlets covering alt coins, stable coins, Bittensor, and companies like xTAO, YUMA, TAOX, and Oblong. Each outlet has 20 identical articles for scrolling functionality. All placeholder images have been replaced with actual uploaded photos and branded thumbnails.\n\n## External Dependencies\n\n**UI Framework**: Radix UI primitives for accessible component foundations, shadcn/ui component library for pre-built components, Tailwind CSS for utility-first styling, and class-variance-authority for component variants.\n\n**State & API Management**: TanStack Query for data fetching and caching, Wouter for lightweight client-side routing.\n\n**Development Tools**: Vite for fast development and building, TypeScript for type safety, PostCSS with Autoprefixer for CSS processing.\n\n**Backend Dependencies**: Express.js for server framework, Drizzle ORM for database schema and migrations, Neon Database (@neondatabase/serverless) for PostgreSQL hosting.\n\n**Potential Integrations**: OpenAI API configured for AI-generated content and thumbnails, though not actively used in current implementation. Google Fonts (Inter) for typography consistency.\n\n**Form Handling**: React Hook Form with Hookform Resolvers for form validation, Zod for schema validation integrated with Drizzle.\n\n**Date Utilities**: date-fns for date formatting and manipulation throughout the application.","size_bytes":4046},"tailwind.config.ts":{"content":"import type { Config } from \"tailwindcss\";\n\nexport default {\n darkMode: [\"class\"],\n content: [\"./client/index.html\", \"./client/src/**/*.{js,jsx,ts,tsx}\"],\n theme: {\n extend: {\n borderRadius: {\n lg: \".5625rem\", /* 9px */\n md: \".375rem\", /* 6px */\n sm: \".1875rem\", /* 3px */\n },\n colors: {\n // Flat / base colors (regular buttons)\n background: \"hsl(var(--background) / )\",\n foreground: \"hsl(var(--foreground) / )\",\n border: \"hsl(var(--border) / )\",\n input: \"hsl(var(--input) / )\",\n card: {\n DEFAULT: \"hsl(var(--card) / )\",\n foreground: \"hsl(var(--card-foreground) / )\",\n border: \"hsl(var(--card-border) / )\",\n },\n popover: {\n DEFAULT: \"hsl(var(--popover) / )\",\n foreground: \"hsl(var(--popover-foreground) / )\",\n border: \"hsl(var(--popover-border) / )\",\n },\n primary: {\n DEFAULT: \"hsl(var(--primary) / )\",\n foreground: \"hsl(var(--primary-foreground) / )\",\n border: \"var(--primary-border)\",\n },\n secondary: {\n DEFAULT: \"hsl(var(--secondary) / )\",\n foreground: \"hsl(var(--secondary-foreground) / )\",\n border: \"var(--secondary-border)\",\n },\n muted: {\n DEFAULT: \"hsl(var(--muted) / )\",\n foreground: \"hsl(var(--muted-foreground) / )\",\n border: \"var(--muted-border)\",\n },\n accent: {\n DEFAULT: \"hsl(var(--accent) / )\",\n foreground: \"hsl(var(--accent-foreground) / )\",\n border: \"var(--accent-border)\",\n },\n destructive: {\n DEFAULT: \"hsl(var(--destructive) / )\",\n foreground: \"hsl(var(--destructive-foreground) / )\",\n border: \"var(--destructive-border)\",\n },\n ring: \"hsl(var(--ring) / )\",\n chart: {\n \"1\": \"hsl(var(--chart-1) / )\",\n \"2\": \"hsl(var(--chart-2) / )\",\n \"3\": \"hsl(var(--chart-3) / )\",\n \"4\": \"hsl(var(--chart-4) / )\",\n \"5\": \"hsl(var(--chart-5) / )\",\n },\n sidebar: {\n ring: \"hsl(var(--sidebar-ring) / )\",\n DEFAULT: \"hsl(var(--sidebar) / )\",\n foreground: \"hsl(var(--sidebar-foreground) / )\",\n border: \"hsl(var(--sidebar-border) / )\",\n },\n \"sidebar-primary\": {\n DEFAULT: \"hsl(var(--sidebar-primary) / )\",\n foreground: \"hsl(var(--sidebar-primary-foreground) / )\",\n border: \"var(--sidebar-primary-border)\",\n },\n \"sidebar-accent\": {\n DEFAULT: \"hsl(var(--sidebar-accent) / )\",\n foreground: \"hsl(var(--sidebar-accent-foreground) / )\",\n border: \"var(--sidebar-accent-border)\"\n },\n status: {\n online: \"rgb(34 197 94)\",\n away: \"rgb(245 158 11)\",\n busy: \"rgb(239 68 68)\",\n offline: \"rgb(156 163 175)\",\n },\n },\n fontFamily: {\n sans: [\"var(--font-sans)\"],\n serif: [\"var(--font-serif)\"],\n mono: [\"var(--font-mono)\"],\n },\n keyframes: {\n \"accordion-down\": {\n from: { height: \"0\" },\n to: { height: \"var(--radix-accordion-content-height)\" },\n },\n \"accordion-up\": {\n from: { height: \"var(--radix-accordion-content-height)\" },\n to: { height: \"0\" },\n },\n },\n animation: {\n \"accordion-down\": \"accordion-down 0.2s ease-out\",\n \"accordion-up\": \"accordion-up 0.2s ease-out\",\n },\n },\n },\n plugins: [require(\"tailwindcss-animate\"), require(\"@tailwindcss/typography\")],\n} satisfies Config;\n","size_bytes":4050},"vite.config.ts":{"content":"import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\nimport path from \"path\";\nimport runtimeErrorOverlay from \"@replit/vite-plugin-runtime-error-modal\";\n\nexport default defineConfig({\n plugins: [\n react(),\n runtimeErrorOverlay(),\n ...(process.env.NODE_ENV !== \"production\" &&\n process.env.REPL_ID !== undefined\n ? [\n await import(\"@replit/vite-plugin-cartographer\").then((m) =>\n m.cartographer(),\n ),\n ]\n : []),\n ],\n resolve: {\n alias: {\n \"@\": path.resolve(import.meta.dirname, \"client\", \"src\"),\n \"@shared\": path.resolve(import.meta.dirname, \"shared\"),\n \"@assets\": path.resolve(import.meta.dirname, \"attached_assets\"),\n },\n },\n root: path.resolve(import.meta.dirname, \"client\"),\n build: {\n outDir: path.resolve(import.meta.dirname, \"dist/public\"),\n emptyOutDir: true,\n },\n server: {\n fs: {\n strict: true,\n deny: [\"**/.*\"],\n },\n },\n});\n","size_bytes":971},"server/index.ts":{"content":"import express, { type Request, Response, NextFunction } from \"express\";\nimport { registerRoutes } from \"./routes\";\nimport { setupVite, serveStatic, log } from \"./vite\";\n\nconst app = express();\napp.use(express.json());\napp.use(express.urlencoded({ extended: false }));\n\napp.use((req, res, next) => {\n const start = Date.now();\n const path = req.path;\n let capturedJsonResponse: Record | undefined = undefined;\n\n const originalResJson = res.json;\n res.json = function (bodyJson, ...args) {\n capturedJsonResponse = bodyJson;\n return originalResJson.apply(res, [bodyJson, ...args]);\n };\n\n res.on(\"finish\", () => {\n const duration = Date.now() - start;\n if (path.startsWith(\"/api\")) {\n let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;\n if (capturedJsonResponse) {\n logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;\n }\n\n if (logLine.length > 80) {\n logLine = logLine.slice(0, 79) + \"…\";\n }\n\n log(logLine);\n }\n });\n\n next();\n});\n\n(async () => {\n const server = await registerRoutes(app);\n\n app.use((err: any, _req: Request, res: Response, _next: NextFunction) => {\n const status = err.status || err.statusCode || 500;\n const message = err.message || \"Internal Server Error\";\n\n res.status(status).json({ message });\n throw err;\n });\n\n // importantly only setup vite in development and after\n // setting up all the other routes so the catch-all route\n // doesn't interfere with the other routes\n const isProduction = app.get(\"env\") === \"production\" || process.env.REPLIT_DEPLOYMENT === \"1\";\n \n if (!isProduction) {\n await setupVite(app, server);\n } else {\n log(\"Setting up static file serving for production\");\n \n // Protect unmatched API routes from static file serving catch-all\n // This should come after all API routes are registered\n app.use('/api/*', (req, res) => {\n res.status(404).json({ error: `API endpoint not found: ${req.path}` });\n });\n \n serveStatic(app);\n }\n\n // ALWAYS serve the app on the port specified in the environment variable PORT\n // Other ports are firewalled. Default to 5000 if not specified.\n // this serves both the API and the client.\n // It is the only port that is not firewalled.\n const port = parseInt(process.env.PORT || '5000', 10);\n server.listen({\n port,\n host: \"0.0.0.0\",\n reusePort: true,\n }, () => {\n log(`serving on port ${port}`);\n });\n})();\n","size_bytes":2470},"server/routes.ts":{"content":"import type { Express } from \"express\";\nimport { createServer, type Server } from \"http\";\nimport express from \"express\";\nimport path from \"path\";\nimport { storage } from \"./storage\";\nimport { insertArticleSchema, insertMediaOutletSchema, type Article, type MediaOutlet } from \"@shared/schema\";\nimport OpenAI from \"openai\";\nimport { WebScraper } from './scraper';\nimport { OutletParser } from './outletParser';\nimport sharp from 'sharp';\nimport fs from 'fs';\n\n// the newest OpenAI model is \"gpt-5\" which was released August 7, 2025. do not change this unless explicitly requested by the user\nconst openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });\n\n// Utility functions for thumbnail generation\nfunction needsThumbnail(article: Article): boolean {\n // Check if article has no thumbnail or uses default placeholder\n return !article.thumbnail || \n article.thumbnail === '/api/assets/default-article.png' ||\n article.thumbnail.trim() === '';\n}\n\n// Function to format time ago - returns consistent random \"X min ago\" for each article\nfunction formatTimeAgo(date: Date | string, articleId?: string): string {\n // If we have an article ID, generate a consistent random value for it\n if (articleId) {\n const hash = articleId.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);\n const minutes = (hash % 59) + 1; // 1 to 59\n return `${minutes} min ago`;\n }\n \n // Fallback to actual time calculation\n const now = new Date();\n const past = new Date(date);\n const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000);\n let diffInMinutes = Math.floor(diffInSeconds / 60);\n \n // Clamp to 1-59 range\n if (diffInMinutes < 1) diffInMinutes = 1;\n if (diffInMinutes > 59) diffInMinutes = 59;\n \n return `${diffInMinutes} min ago`;\n}\n\n// Function to generate varied publication times for articles (1-59 minutes ago only)\nfunction generateVariedPublishedAt(seed?: string): Date {\n const now = new Date();\n \n // Use seed (title/summary) or random to create varied offsets\n const seedValue = seed || Math.random().toString();\n const hash = seedValue.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);\n const random = Math.abs(Math.sin(hash)) * 1000;\n \n // Generate varied minutes between 1-59 minutes ago\n const offsetMinutes = Math.floor((random * 1000) % 59) + 1; // 1 to 59 minutes\n \n return new Date(now.getTime() - offsetMinutes * 60 * 1000);\n}\n\nfunction generateImagePrompt(article: Article, outlet?: MediaOutlet): string {\n const outletContext = outlet ? ` related to ${outlet.focusSubject}` : '';\n return `Professional news thumbnail image for article: \"${article.title}\". ${article.summary || 'News article'}${outletContext}. Modern, clean, journalistic style, suitable for mobile news app, 16:9 aspect ratio, no text overlays, photorealistic.`;\n}\n\nasync function saveGeneratedImage(imageUrlOrBase64: string, filename: string): Promise {\n try {\n // Create directory if it doesn't exist\n const generatedImagesDir = path.resolve(process.cwd(), 'attached_assets', 'generated_images');\n if (!fs.existsSync(generatedImagesDir)) {\n fs.mkdirSync(generatedImagesDir, { recursive: true });\n }\n\n let buffer: Buffer;\n \n if (imageUrlOrBase64.startsWith('data:image/')) {\n // Handle base64 data\n const base64Data = imageUrlOrBase64.split(',')[1];\n buffer = Buffer.from(base64Data, 'base64');\n } else {\n // Handle URL\n const response = await fetch(imageUrlOrBase64);\n if (!response.ok) {\n throw new Error(`Failed to fetch image: ${response.statusText}`);\n }\n buffer = Buffer.from(await response.arrayBuffer());\n }\n \n // Generate thumbnail using sharp\n const thumbnailPath = path.join(generatedImagesDir, `thumb_${filename}.png`);\n const fullImagePath = path.join(generatedImagesDir, `${filename}.png`);\n \n // Save full size image\n await sharp(buffer)\n .png({ quality: 90 })\n .toFile(fullImagePath);\n \n // Create thumbnail (400x225 for 16:9 ratio)\n await sharp(buffer)\n .resize(400, 225, { fit: 'cover', position: 'center' })\n .png({ quality: 80 })\n .toFile(thumbnailPath);\n \n // Return the relative path for the thumbnail\n return `/api/assets/generated_images/thumb_${filename}.png`;\n } catch (error) {\n console.error('Error saving generated image:', error);\n throw error;\n }\n}\n\nexport async function registerRoutes(app: Express): Promise {\n // Health check\n app.get(\"/api/health\", (req, res) => {\n res.json({ status: \"ok\" });\n });\n\n // Media outlets routes\n app.get(\"/api/outlets\", async (req, res) => {\n try {\n const { category } = req.query;\n let outlets;\n \n if (category && typeof category === 'string') {\n outlets = await storage.getOutletsByCategory(category);\n } else {\n outlets = await storage.getAllOutlets();\n }\n \n // Add article count to each outlet (using efficient single query)\n const articleCounts = await storage.getArticleCountsByOutlets();\n const outletsWithCounts = outlets.map(outlet => ({\n ...outlet,\n articleCount: articleCounts[outlet.id] || 0\n }));\n \n res.json(outletsWithCounts);\n } catch (error) {\n console.error(\"Error fetching outlets:\", error);\n res.status(500).json({ error: \"Failed to fetch outlets\" });\n }\n });\n\n app.get(\"/api/outlets/:id\", async (req, res) => {\n try {\n const outlet = await storage.getOutletById(req.params.id);\n if (!outlet) {\n return res.status(404).json({ error: \"Outlet not found\" });\n }\n res.json(outlet);\n } catch (error) {\n console.error(\"Error fetching outlet:\", error);\n res.status(500).json({ error: \"Failed to fetch outlet\" });\n }\n });\n\n app.get(\"/api/outlets/:id/articles\", async (req, res) => {\n try {\n const articles = await storage.getArticlesByOutlet(req.params.id);\n res.json(articles);\n } catch (error) {\n console.error(\"Error fetching articles for outlet:\", error);\n res.status(500).json({ error: \"Failed to fetch articles\" });\n }\n });\n\n app.post(\"/api/outlets\", async (req, res) => {\n try {\n const validatedData = insertMediaOutletSchema.parse(req.body);\n const outlet = await storage.createOutlet(validatedData);\n res.status(201).json(outlet);\n } catch (error) {\n console.error(\"Error creating outlet:\", error);\n res.status(400).json({ error: \"Invalid outlet data\" });\n }\n });\n\n app.patch(\"/api/outlets/:id\", async (req, res) => {\n try {\n const partialSchema = insertMediaOutletSchema.omit({ id: true }).partial();\n const validatedData = partialSchema.parse(req.body);\n const outlet = await storage.updateOutlet(req.params.id, validatedData);\n if (!outlet) {\n return res.status(404).json({ error: \"Outlet not found\" });\n }\n res.json(outlet);\n } catch (error) {\n console.error(\"Error updating outlet:\", error);\n res.status(400).json({ error: \"Invalid outlet data\" });\n }\n });\n\n app.delete(\"/api/outlets/:id\", async (req, res) => {\n try {\n const success = await storage.deleteOutlet(req.params.id);\n if (!success) {\n return res.status(404).json({ error: \"Outlet not found\" });\n }\n res.status(204).send();\n } catch (error) {\n console.error(\"Error deleting outlet:\", error);\n res.status(500).json({ error: \"Failed to delete outlet\" });\n }\n });\n\n // Articles routes\n app.get(\"/api/articles\", async (req, res) => {\n try {\n const { outlet, featured, limit } = req.query;\n let articles;\n \n if (outlet && typeof outlet === 'string') {\n articles = await storage.getArticlesByOutlet(outlet);\n } else if (featured === 'true') {\n const limitNum = limit ? parseInt(limit as string) : 10;\n articles = await storage.getFeaturedArticles(limitNum);\n } else {\n articles = await storage.getAllArticles();\n }\n \n // Add timeAgo to each article first\n const articlesWithTimeAgo = articles.map(article => ({\n ...article,\n timeAgo: formatTimeAgo(article.publishedAt, article.id)\n }));\n \n // Sort by the minutes value in timeAgo (smallest to largest)\n articlesWithTimeAgo.sort((a, b) => {\n const aMin = parseInt(a.timeAgo.split(' ')[0]);\n const bMin = parseInt(b.timeAgo.split(' ')[0]);\n return aMin - bMin;\n });\n \n res.json(articlesWithTimeAgo);\n } catch (error) {\n console.error(\"Error fetching articles:\", error);\n res.status(500).json({ error: \"Failed to fetch articles\" });\n }\n });\n\n app.get(\"/api/articles/:id\", async (req, res) => {\n try {\n const article = await storage.getArticleById(req.params.id);\n if (!article) {\n return res.status(404).json({ error: \"Article not found\" });\n }\n // Add timeAgo to the article\n const articleWithTimeAgo = {\n ...article,\n timeAgo: formatTimeAgo(article.publishedAt, article.id)\n };\n res.json(articleWithTimeAgo);\n } catch (error) {\n console.error(\"Error fetching article:\", error);\n res.status(500).json({ error: \"Failed to fetch article\" });\n }\n });\n\n app.post(\"/api/articles\", async (req, res) => {\n try {\n const validatedData = insertArticleSchema.parse(req.body);\n const article = await storage.createArticle(validatedData);\n res.status(201).json(article);\n } catch (error) {\n console.error(\"Error creating article:\", error);\n res.status(400).json({ error: \"Invalid article data\" });\n }\n });\n\n app.patch(\"/api/articles/:id\", async (req, res) => {\n try {\n const { id } = req.params;\n const { thumbnail } = req.body;\n \n if (!thumbnail) {\n return res.status(400).json({ error: \"Thumbnail path required\" });\n }\n \n const updatedArticle = await storage.updateArticleThumbnail(id, thumbnail);\n if (!updatedArticle) {\n return res.status(404).json({ error: \"Article not found\" });\n }\n \n res.json(updatedArticle);\n } catch (error) {\n console.error(\"Error updating article:\", error);\n res.status(500).json({ error: \"Failed to update article\" });\n }\n });\n\n app.delete(\"/api/articles/:id\", async (req, res) => {\n try {\n const { id } = req.params;\n \n const success = await storage.deleteArticle(id);\n if (!success) {\n return res.status(404).json({ error: \"Article not found\" });\n }\n \n res.status(204).send();\n } catch (error) {\n console.error(\"Error deleting article:\", error);\n res.status(500).json({ error: \"Failed to delete article\" });\n }\n });\n\n // Search routes\n app.get(\"/api/search\", async (req, res) => {\n try {\n const { q, type = 'all' } = req.query;\n if (!q || typeof q !== 'string') {\n return res.status(400).json({ error: \"Search query required\" });\n }\n \n console.log(`[Search] Query: \"${q}\", Type: ${type}`);\n \n let articles: Article[] = [];\n let outlets: MediaOutlet[] = [];\n \n if (type === 'all' || type === 'articles') {\n articles = await storage.searchArticles(q);\n console.log(`[Search] Found ${articles.length} articles`);\n }\n \n if (type === 'all' || type === 'outlets') {\n const allOutlets = await storage.getAllOutlets();\n const searchTerm = q.toLowerCase();\n outlets = allOutlets.filter(outlet => {\n const nameMatch = outlet.name.toLowerCase().includes(searchTerm);\n const descMatch = outlet.description.toLowerCase().includes(searchTerm);\n const focusMatch = outlet.focusSubject.toLowerCase().includes(searchTerm);\n const bioMatch = outlet.bio && outlet.bio.toLowerCase().includes(searchTerm);\n \n return nameMatch || descMatch || focusMatch || bioMatch;\n });\n console.log(`[Search] Found ${outlets.length} outlets out of ${allOutlets.length} total outlets`);\n \n if (outlets.length > 0) {\n console.log(`[Search] Matching outlets: ${outlets.map(o => o.name).join(', ')}`);\n }\n }\n \n const result = { articles, outlets };\n console.log(`[Search] Returning ${articles.length} articles and ${outlets.length} outlets`);\n res.json(result);\n } catch (error) {\n console.error(\"Error searching:\", error);\n res.status(500).json({ error: \"Failed to search\" });\n }\n });\n\n // AI-powered image generation for articles\n app.post(\"/api/generate-thumbnail\", async (req, res) => {\n try {\n const { description, aspectRatio = \"16:9\" } = req.body;\n \n if (!description) {\n return res.status(400).json({ error: \"Description required\" });\n }\n\n const sizeMap = {\n \"16:9\": \"1792x1024\",\n \"1:1\": \"1024x1024\",\n \"9:16\": \"1024x1792\"\n };\n\n const size = sizeMap[aspectRatio as keyof typeof sizeMap] || \"1792x1024\";\n\n const response = await openai.images.generate({\n model: \"dall-e-3\",\n prompt: `Professional news article thumbnail: ${description}. High quality, modern, clean composition suitable for mobile news app.`,\n n: 1,\n size: size as any,\n quality: \"standard\",\n });\n\n // Robust handling of OpenAI response\n const imageData = response.data?.[0];\n if (!imageData) {\n throw new Error('No image data received from OpenAI');\n }\n \n const imageUrl = imageData.url || imageData.b64_json;\n if (!imageUrl) {\n throw new Error('No image URL or data received');\n }\n \n res.json({ \n url: imageData.url || `data:image/png;base64,${imageData.b64_json}`,\n format: imageData.url ? 'url' : 'base64'\n });\n } catch (error) {\n console.error(\"Error generating thumbnail:\", error);\n res.status(500).json({ error: \"Failed to generate thumbnail\" });\n }\n });\n\n // Generate thumbnail for a specific article\n app.post(\"/api/articles/:id/generate-thumbnail\", async (req, res) => {\n try {\n const { id } = req.params;\n \n // Get the article\n const article = await storage.getArticleById(id);\n if (!article) {\n return res.status(404).json({ error: \"Article not found\" });\n }\n\n // Check if article doesn't need a thumbnail (already has one that's not a placeholder)\n if (!needsThumbnail(article)) {\n return res.json({ \n message: \"Article already has a thumbnail\",\n thumbnailPath: article.thumbnail \n });\n }\n\n // Get the outlet for context\n const outlet = await storage.getOutletById(article.outletId);\n \n // Generate image prompt\n const prompt = await generateImagePrompt(article, outlet || undefined);\n \n // Generate image with OpenAI\n const response = await openai.images.generate({\n model: \"dall-e-3\",\n prompt,\n n: 1,\n size: \"1792x1024\",\n quality: \"standard\",\n });\n\n const imageData = response.data?.[0];\n if (!imageData) {\n throw new Error('No image data received from OpenAI');\n }\n \n const imageUrl = imageData.url || (imageData.b64_json ? `data:image/png;base64,${imageData.b64_json}` : null);\n if (!imageUrl) {\n throw new Error('No image URL or data received from OpenAI');\n }\n\n // Create filename\n const timestamp = Date.now();\n const randomId = Math.random().toString(36).substring(2, 8);\n const filename = `${article.title.replace(/[^a-zA-Z0-9]/g, '_').substring(0, 50)}_${timestamp}_${randomId}`;\n\n // Save image and get thumbnail path\n const thumbnailPath = await saveGeneratedImage(imageUrl, filename);\n \n // Update article with new thumbnail\n const updatedArticle = await storage.updateArticleThumbnail(id, thumbnailPath);\n if (!updatedArticle) {\n throw new Error('Failed to update article thumbnail');\n }\n\n res.json({\n success: true,\n thumbnailPath,\n message: \"Thumbnail generated and saved successfully\"\n });\n\n } catch (error) {\n console.error(\"Error generating article thumbnail:\", error);\n res.status(500).json({ error: \"Failed to generate thumbnail\" });\n }\n });\n\n // Generate thumbnails for all articles that need them\n app.post(\"/api/articles/generate-thumbnails\", async (req, res) => {\n try {\n const { limit = 10 } = req.body; // Limit to prevent overwhelming the API\n \n // Get all articles\n const articles = await storage.getAllArticles();\n \n // Filter articles that need thumbnails\n const articlesNeedingThumbnails = articles\n .filter(needsThumbnail)\n .slice(0, Math.min(limit, 20)); // Cap at 20 to prevent abuse\n\n if (articlesNeedingThumbnails.length === 0) {\n return res.json({\n success: true,\n message: \"No articles need thumbnail generation\",\n processed: 0\n });\n }\n\n const results = [];\n const errors = [];\n\n // Process articles sequentially to avoid overwhelming OpenAI API\n for (const article of articlesNeedingThumbnails) {\n try {\n // Get the outlet for context\n const outlet = await storage.getOutletById(article.outletId);\n \n // Generate image prompt\n const prompt = await generateImagePrompt(article, outlet || undefined);\n \n // Generate image with OpenAI\n const response = await openai.images.generate({\n model: \"dall-e-3\",\n prompt,\n n: 1,\n size: \"1792x1024\",\n quality: \"standard\",\n });\n\n const imageData = response.data?.[0];\n if (!imageData) {\n throw new Error('No image data received from OpenAI');\n }\n \n const imageUrl = imageData.url || (imageData.b64_json ? `data:image/png;base64,${imageData.b64_json}` : null);\n if (!imageUrl) {\n throw new Error('No image URL or data received from OpenAI');\n }\n\n // Create filename\n const timestamp = Date.now();\n const randomId = Math.random().toString(36).substring(2, 8);\n const filename = `${article.title.replace(/[^a-zA-Z0-9]/g, '_').substring(0, 50)}_${timestamp}_${randomId}`;\n\n // Save image and get thumbnail path\n const thumbnailPath = await saveGeneratedImage(imageUrl, filename);\n \n // Update article with new thumbnail\n await storage.updateArticleThumbnail(article.id, thumbnailPath);\n\n results.push({\n articleId: article.id,\n title: article.title,\n thumbnailPath,\n success: true\n });\n\n // Small delay to avoid rate limiting\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n } catch (error) {\n console.error(`Error generating thumbnail for article ${article.id}:`, error);\n errors.push({\n articleId: article.id,\n title: article.title,\n error: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n }\n\n res.json({\n success: true,\n processed: results.length,\n failed: errors.length,\n results,\n errors,\n message: `Generated ${results.length} thumbnails, ${errors.length} failed`\n });\n\n } catch (error) {\n console.error(\"Error in batch thumbnail generation:\", error);\n res.status(500).json({ error: \"Failed to generate thumbnails\" });\n }\n });\n\n // AI-powered article enhancement\n app.post(\"/api/enhance-article\", async (req, res) => {\n try {\n const { title, summary, content } = req.body;\n \n if (!title || !content) {\n return res.status(400).json({ error: \"Title and content required\" });\n }\n\n const response = await openai.chat.completions.create({\n model: \"gpt-4o\", // Using gpt-4o as it's widely available\n messages: [\n {\n role: \"system\",\n content: \"You are a professional news editor. Enhance the given article by improving clarity, flow, and journalistic quality while maintaining the original facts and tone. Respond with JSON containing enhanced title, summary, and body.\"\n },\n {\n role: \"user\",\n content: `Please enhance this article:\nTitle: ${title}\nSummary: ${summary || \"\"}\nContent: ${content}\n\nProvide enhanced versions in JSON format: { \"title\": \"...\", \"summary\": \"...\", \"body\": \"...\" }`\n }\n ],\n response_format: { type: \"json_object\" },\n });\n\n // Robust parsing with validation\n const messageContent = response.choices?.[0]?.message?.content;\n if (!messageContent) {\n throw new Error('No content received from OpenAI');\n }\n \n let enhanced;\n try {\n enhanced = JSON.parse(messageContent);\n } catch (parseError) {\n console.error('Failed to parse OpenAI response:', messageContent);\n throw new Error('Invalid JSON response from AI');\n }\n \n // Validate required fields\n const result = {\n title: enhanced.title || title,\n summary: enhanced.summary || summary || '',\n body: enhanced.body || content\n };\n \n res.json(result);\n } catch (error) {\n console.error(\"Error enhancing article:\", error);\n res.status(500).json({ error: \"Failed to enhance article\" });\n }\n });\n\n // Generate AI-powered summary from article content\n app.post(\"/api/generate-summary\", async (req, res) => {\n try {\n const { content, title } = req.body;\n \n if (!content) {\n return res.status(400).json({ error: \"Content is required\" });\n }\n\n // Generate AI-powered summary with fallback to basic method\n let summary = '';\n \n try {\n const response = await openai.chat.completions.create({\n model: \"gpt-4o-mini\", // Using mini model for cost-effectiveness\n messages: [\n {\n role: \"system\",\n content: \"You are a professional news summarizer. Create a concise, engaging summary (maximum 2-3 sentences, 150 characters max) that captures the key points and newsworthiness of the article. Focus on who, what, when, where, why. Make it compelling but factual.\"\n },\n {\n role: \"user\",\n content: `Title: ${title || \"No title\"}\nArticle Content: ${content.substring(0, 2000)}`\n }\n ],\n max_tokens: 100,\n temperature: 0.3 // Lower temperature for more consistent, factual output\n });\n\n const aiSummary = response.choices?.[0]?.message?.content?.trim();\n if (aiSummary && aiSummary.length > 10) {\n summary = aiSummary;\n } else {\n throw new Error('AI summary too short or empty');\n }\n } catch (aiError) {\n console.warn(\"AI summary generation failed, falling back to basic method:\", aiError);\n \n // Fallback to basic summary generation (improved version)\n const sentences = content.replace(/^This article was originally published at .+?\\.\\n\\n/, '').split(/[.!?]+/);\n let basicSummary = '';\n \n for (const sentence of sentences) {\n const trimmed = sentence.trim();\n if (trimmed.length < 10) continue; // Skip very short sentences\n if (basicSummary.length + trimmed.length > 150) break;\n basicSummary += (basicSummary ? '. ' : '') + trimmed;\n }\n \n summary = basicSummary + (basicSummary ? '.' : 'Content not available.');\n }\n\n res.json({ summary: summary.substring(0, 150) }); // Ensure max 150 chars\n } catch (error) {\n console.error(\"Error generating summary:\", error);\n \n // Final fallback - return a generic summary\n const basicSummary = req.body.content.substring(0, 100).trim() + '...';\n res.json({ summary: basicSummary });\n }\n });\n\n // AI-powered Text-to-Speech for articles with professional anchor style\n app.post(\"/api/articles/:id/speech\", async (req, res) => {\n try {\n const { id } = req.params;\n const { voice = 'nova', speed = 1.0 } = req.body;\n \n // Get the article\n const article = await storage.getArticleById(id);\n if (!article) {\n return res.status(404).json({ error: \"Article not found\" });\n }\n \n // Prepare the text for speech synthesis with professional anchor style\n const speechText = `Here's today's news from ${article.outletName || 'our newsroom'}. ${article.title}. \n\n ${article.summary || ''}\n \n ${article.body || 'Content not available.'}\n \n This has been your news update. Thank you for listening.`;\n \n // Use OpenAI's text-to-speech with professional voice settings\n const response = await openai.audio.speech.create({\n model: \"tts-1-hd\", // High-quality model for professional sound\n voice: voice as any, // nova, alloy, echo, fable, onyx, shimmer\n input: speechText.substring(0, 4000), // Limit text length for API\n speed: Math.max(0.25, Math.min(4.0, speed)), // Ensure speed is within valid range\n response_format: \"mp3\"\n });\n \n // Stream the audio response\n res.setHeader('Content-Type', 'audio/mpeg');\n res.setHeader('Content-Disposition', `inline; filename=\"article_${id}_speech.mp3\"`);\n res.setHeader('Cache-Control', 'public, max-age=3600'); // Cache for 1 hour\n \n // Convert response to buffer and send\n const buffer = Buffer.from(await response.arrayBuffer());\n res.send(buffer);\n \n } catch (error) {\n console.error(\"Error generating speech:\", error);\n res.status(500).json({ \n error: \"Failed to generate speech\",\n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Statistics route\n app.get(\"/api/stats\", async (req, res) => {\n try {\n const outlets = await storage.getAllOutlets();\n const articles = await storage.getAllArticles();\n \n const categoryStats = outlets.reduce((acc, outlet) => {\n acc[outlet.category] = (acc[outlet.category] || 0) + 1;\n return acc;\n }, {} as Record);\n\n res.json({\n totalOutlets: outlets.length,\n totalArticles: articles.length,\n categoriesBreakdown: categoryStats,\n recentArticlesCount: articles.slice(0, 5).length\n });\n } catch (error) {\n console.error(\"Error fetching stats:\", error);\n res.status(500).json({ error: \"Failed to fetch statistics\" });\n }\n });\n\n // YouTube-style feed endpoint\n app.get(\"/api/feed\", async (req, res) => {\n try {\n const { cursor, limit, filter } = req.query;\n const params = {\n cursor: cursor as string,\n limit: limit ? parseInt(limit as string) : 10,\n filter: (filter as 'all' | 'people' | 'topics' | 'companies') || 'all'\n };\n \n const feed = await storage.listFeed(params);\n res.json(feed);\n } catch (error) {\n console.error(\"Error fetching feed:\", error);\n res.status(500).json({ error: \"Failed to fetch feed\" });\n }\n });\n\n // Increment article view count\n app.post(\"/api/articles/:id/view\", async (req, res) => {\n try {\n await storage.incrementView(req.params.id);\n res.json({ success: true });\n } catch (error) {\n console.error(\"Error incrementing view:\", error);\n res.status(500).json({ error: \"Failed to increment view\" });\n }\n });\n\n // Remove duplicate articles within outlets\n app.post(\"/api/articles/remove-duplicates\", async (req, res) => {\n try {\n console.log(\"Starting duplicate article removal...\");\n const result = await storage.removeDuplicateArticles();\n \n res.json({\n success: true,\n removedCount: result.removedCount,\n details: result.details,\n message: `Successfully removed ${result.removedCount} duplicate articles across ${result.details.length} outlets`\n });\n } catch (error) {\n console.error(\"Error removing duplicate articles:\", error);\n res.status(500).json({ \n error: \"Failed to remove duplicate articles\",\n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Comment API routes\n app.get(\"/api/articles/:articleId/comments\", async (req, res) => {\n try {\n const { articleId } = req.params;\n const { limit = 10, offset = 0 } = req.query;\n \n const result = await storage.getCommentsByArticle(articleId, {\n limit: parseInt(limit as string),\n offset: parseInt(offset as string)\n });\n \n res.json(result);\n } catch (error) {\n console.error(\"Error fetching comments:\", error);\n res.status(500).json({ error: \"Failed to fetch comments\" });\n }\n });\n\n app.get(\"/api/comments/:commentId/replies\", async (req, res) => {\n try {\n const { commentId } = req.params;\n const { limit = 5, offset = 0 } = req.query;\n \n const result = await storage.getCommentReplies(commentId, {\n limit: parseInt(limit as string),\n offset: parseInt(offset as string)\n });\n \n res.json(result);\n } catch (error) {\n console.error(\"Error fetching replies:\", error);\n res.status(500).json({ error: \"Failed to fetch replies\" });\n }\n });\n\n app.post(\"/api/articles/:articleId/comments\", async (req, res) => {\n try {\n const { articleId } = req.params;\n const { content, nickname, avatar, parentId } = req.body;\n \n if (!content || !nickname) {\n return res.status(400).json({ error: \"Content and nickname are required\" });\n }\n \n const comment = await storage.createComment({\n articleId,\n content,\n nickname,\n avatar,\n parentId: parentId || null\n });\n \n res.json(comment);\n } catch (error) {\n console.error(\"Error creating comment:\", error);\n res.status(500).json({ error: \"Failed to create comment\" });\n }\n });\n\n app.post(\"/api/comments/:commentId/reactions\", async (req, res) => {\n try {\n const { commentId } = req.params;\n const { reactionType, userIdentifier } = req.body;\n \n if (!reactionType || !userIdentifier) {\n return res.status(400).json({ error: \"Reaction type and user identifier are required\" });\n }\n \n if (!['like', 'dislike'].includes(reactionType)) {\n return res.status(400).json({ error: \"Invalid reaction type\" });\n }\n \n const result = await storage.toggleCommentReaction(commentId, userIdentifier, reactionType);\n res.json(result);\n } catch (error) {\n console.error(\"Error toggling reaction:\", error);\n res.status(500).json({ error: \"Failed to toggle reaction\" });\n }\n });\n\n app.get(\"/api/comments/:commentId/reactions/:userIdentifier\", async (req, res) => {\n try {\n const { commentId, userIdentifier } = req.params;\n \n const reaction = await storage.getUserCommentReaction(commentId, userIdentifier);\n res.json(reaction || null);\n } catch (error) {\n console.error(\"Error fetching user reaction:\", error);\n res.status(500).json({ error: \"Failed to fetch user reaction\" });\n }\n });\n\n // Web scraping endpoint for adding new articles from URLs\n app.post(\"/api/scrape\", async (req, res) => {\n try {\n const { url, outletId } = req.body;\n \n if (!url || !outletId) {\n return res.status(400).json({ error: \"URL and outletId are required\" });\n }\n\n // Fetch the web page content\n const response = await fetch(url);\n const html = await response.text();\n \n // Parse content using simple regex patterns (basic implementation)\n const titleMatch = html.match(/]*>([^<]+)<\\/title>/i);\n const metaDescMatch = html.match(/]*name=[\"\\']description[\"\\'][^>]*content=[\"\\']([^\"']+)[\"\\'][^>]*>/i);\n \n // Extract title and clean it\n let title = titleMatch ? titleMatch[1].trim() : 'Scraped Article';\n title = title.replace(/\\s+/g, ' ').substring(0, 200); // Clean and limit length\n \n // Extract description/summary\n let summary = metaDescMatch ? metaDescMatch[1].trim() : 'Article scraped from ' + new URL(url).hostname;\n summary = summary.replace(/\\s+/g, ' ').substring(0, 500);\n \n // Create basic article body from summary\n let body = summary;\n if (body.length < 200) {\n body += `\\n\\nThis content discusses recent developments and market insights related to the subject matter. The article provides detailed analysis and current information about the industry trends and key developments.`;\n }\n \n // Generate a simple thumbnail placeholder (we'll improve this later)\n const defaultThumbnail = '/api/assets/default-article.png';\n \n // Create the article\n const articleData = {\n outletId,\n title,\n summary,\n body,\n thumbnail: defaultThumbnail,\n publishedAt: generateVariedPublishedAt(title + summary),\n tags: [] as string[],\n viewCount: 0\n };\n \n const article = await storage.createArticle(articleData);\n \n res.json({ \n success: true, \n article,\n message: `Successfully scraped and added article: ${title}`\n });\n \n } catch (error) {\n console.error(\"Error scraping article:\", error);\n res.status(500).json({ \n error: \"Failed to scrape article\", \n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Batch scraping endpoint for multiple URLs\n app.post(\"/api/scrape-batch\", async (req, res) => {\n try {\n const { urls, outletId } = req.body;\n \n if (!urls || !Array.isArray(urls) || !outletId) {\n return res.status(400).json({ error: \"URLs array and outletId are required\" });\n }\n\n const results = [];\n const errors = [];\n\n // Process URLs one by one to avoid overwhelming the server\n for (const url of urls.slice(0, 10)) { // Limit to 10 URLs per batch\n try {\n // Fetch and parse each URL\n const response = await fetch(url);\n const html = await response.text();\n \n const titleMatch = html.match(/]*>([^<]+)<\\/title>/i);\n const metaDescMatch = html.match(/]*name=[\"\\']description[\"\\'][^>]*content=[\"\\']([^\"']+)[\"\\'][^>]*>/i);\n \n let title = titleMatch ? titleMatch[1].trim() : `Article from ${new URL(url).hostname}`;\n title = title.replace(/\\s+/g, ' ').substring(0, 200);\n \n let summary = metaDescMatch ? metaDescMatch[1].trim() : `Article scraped from ${new URL(url).hostname}`;\n summary = summary.replace(/\\s+/g, ' ').substring(0, 500);\n \n let body = summary;\n if (body.length < 200) {\n body += `\\n\\nThis content provides insights and analysis on current industry developments and trends.`;\n }\n \n const articleData = {\n outletId,\n title,\n summary,\n body,\n thumbnail: '/api/assets/default-article.png',\n publishedAt: generateVariedPublishedAt(title + summary),\n tags: [] as string[],\n viewCount: 0\n };\n \n const article = await storage.createArticle(articleData);\n results.push({ url, article, success: true });\n \n // Small delay to be respectful to target servers\n await new Promise(resolve => setTimeout(resolve, 500));\n \n } catch (error) {\n console.error(`Error scraping ${url}:`, error);\n errors.push({ \n url, \n error: error instanceof Error ? error.message : 'Unknown error' \n });\n }\n }\n \n res.json({\n success: true,\n results,\n errors,\n message: `Processed ${results.length} articles successfully, ${errors.length} errors`\n });\n \n } catch (error) {\n console.error(\"Error in batch scraping:\", error);\n res.status(500).json({ \n error: \"Failed to process batch scraping\", \n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Advanced web scraping routes\n app.post(\"/api/scrape/advanced\", async (req, res) => {\n try {\n const { urls, outletId, maxConcurrency = 3 } = req.body;\n \n if (!urls || !Array.isArray(urls) || urls.length === 0) {\n return res.status(400).json({ error: \"URLs array is required\" });\n }\n \n if (!outletId) {\n return res.status(400).json({ error: \"Outlet ID is required\" });\n }\n \n // Verify outlet exists\n const outlet = await storage.getOutletById(outletId);\n if (!outlet) {\n return res.status(404).json({ error: \"Outlet not found\" });\n }\n \n const scraper = new WebScraper();\n console.log(`Starting advanced scraping of ${urls.length} URLs for outlet ${outlet.name}`);\n \n const results = [];\n const errors = [];\n \n // Process URLs in batches with concurrency control\n const { successes: scrapedArticles, failures: scrapingFailures } = await scraper.scrapeMultipleArticles(urls, maxConcurrency);\n \n // Add scraping failures to errors\n for (const failure of scrapingFailures) {\n errors.push({\n url: failure.url,\n error: failure.error\n });\n }\n \n for (const scrapedArticle of scrapedArticles) {\n try {\n // Download and process images if available\n let thumbnailPath = '/api/assets/default-article.png';\n if (scrapedArticle.imageUrl) {\n try {\n const imageFilename = `scraped_${Date.now()}_${Math.random().toString(36).substring(7)}.jpg`;\n const downloadedImage = await scraper.downloadImage(scrapedArticle.imageUrl, imageFilename);\n if (downloadedImage) {\n // Create thumbnail\n const thumbnailFilename = `thumb_${imageFilename}`;\n const thumbnailSuccess = await scraper.createThumbnail(\n join(process.cwd(), 'attached_assets', 'scraped', imageFilename),\n join(process.cwd(), 'attached_assets', 'scraped', thumbnailFilename),\n 300\n );\n if (thumbnailSuccess) {\n thumbnailPath = `/api/assets/scraped/${thumbnailFilename}`;\n }\n }\n } catch (imageError) {\n console.warn(`Failed to process image for ${scrapedArticle.url}:`, imageError);\n }\n }\n \n // Create article with scraped data\n const articleData = {\n outletId,\n title: scrapedArticle.title.substring(0, 200),\n summary: scrapedArticle.summary.substring(0, 500),\n body: scrapedArticle.body,\n thumbnail: thumbnailPath,\n publishedAt: scrapedArticle.publishedAt,\n tags: scrapedArticle.tags,\n viewCount: 0,\n sourceUrl: scrapedArticle.url,\n author: scrapedArticle.author || null,\n originalImageUrl: scrapedArticle.imageUrl || null,\n scrapedAt: new Date(),\n isScraped: 1\n };\n \n const article = await storage.createArticle(articleData);\n results.push({ \n url: scrapedArticle.url, \n article: {\n id: article.id,\n title: article.title,\n summary: article.summary\n }, \n success: true \n });\n \n } catch (error) {\n console.error(`Error saving scraped article from ${scrapedArticle.url}:`, error);\n errors.push({ \n url: scrapedArticle.url, \n error: error instanceof Error ? error.message : 'Failed to save article' \n });\n }\n }\n \n res.json({\n success: true,\n results,\n errors,\n message: `Successfully scraped and saved ${results.length} articles, ${errors.length} errors`,\n outlet: outlet.name,\n totalProcessed: urls.length\n });\n \n } catch (error) {\n console.error(\"Error in advanced scraping:\", error);\n res.status(500).json({ \n error: \"Failed to process advanced scraping\", \n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Batch scrape all outlets from attached file\n app.post(\"/api/scrape/batch-all\", async (req, res) => {\n try {\n const { maxPerOutlet = 5, maxConcurrency = 2 } = req.body;\n \n console.log(\"Starting batch scraping of all outlets from attached file...\");\n \n // Parse the attached outlet file\n const parsedOutlets = parseAttachedOutletFile();\n console.log(`Parsed ${parsedOutlets.total} outlets from file`);\n \n // Convert to outlet format\n const outletsData = OutletParser.convertToOutletFormat(parsedOutlets);\n \n const scraper = new WebScraper();\n const allResults = [];\n const allErrors = [];\n \n let processedOutlets = 0;\n \n for (const outletData of outletsData) {\n try {\n processedOutlets++;\n console.log(`Processing outlet ${processedOutlets}/${outletsData.length}: ${outletData.name}`);\n \n // Create or update outlet\n let outlet;\n try {\n outlet = await storage.getOutletById(outletData.id);\n if (!outlet) {\n outlet = await storage.createOutlet({\n name: outletData.name,\n description: outletData.description,\n category: outletData.category,\n focusSubject: outletData.focusSubject,\n avatar: outletData.avatar,\n profileImage: outletData.profileImage,\n bio: outletData.bio,\n fullBio: outletData.fullBio\n });\n }\n } catch (outletError) {\n console.error(`Error creating/updating outlet ${outletData.name}:`, outletError);\n allErrors.push({\n outlet: outletData.name,\n error: `Failed to create outlet: ${outletError instanceof Error ? outletError.message : 'Unknown error'}`\n });\n continue;\n }\n \n // Take limited number of URLs per outlet\n const urlsToScrape = outletData.urls.slice(0, maxPerOutlet);\n console.log(`Scraping ${urlsToScrape.length} URLs for ${outlet.name}`);\n \n // Scrape articles for this outlet\n const { successes: scrapedArticles, failures: scrapingFailures } = await scraper.scrapeMultipleArticles(urlsToScrape, maxConcurrency);\n \n // Add scraping failures to errors\n for (const failure of scrapingFailures) {\n allErrors.push({\n outlet: outlet.name,\n url: failure.url,\n error: failure.error\n });\n }\n \n let savedCount = 0;\n \n for (const scrapedArticle of scrapedArticles) {\n try {\n // Process thumbnail\n let thumbnailPath = '/api/assets/default-article.png';\n if (scrapedArticle.imageUrl) {\n try {\n const imageFilename = `scraped_${outletData.id}_${Date.now()}_${Math.random().toString(36).substring(7)}.jpg`;\n const downloadedImage = await scraper.downloadImage(scrapedArticle.imageUrl, imageFilename);\n if (downloadedImage) {\n const thumbnailFilename = `thumb_${imageFilename}`;\n const thumbnailSuccess = await scraper.createThumbnail(\n join(process.cwd(), 'attached_assets', 'scraped', imageFilename),\n join(process.cwd(), 'attached_assets', 'scraped', thumbnailFilename),\n 300\n );\n if (thumbnailSuccess) {\n thumbnailPath = `/api/assets/scraped/${thumbnailFilename}`;\n }\n }\n } catch (imageError) {\n console.warn(`Failed to process image for ${scrapedArticle.url}:`, imageError);\n }\n }\n \n // Save article\n const articleData = {\n outletId: outlet.id,\n title: scrapedArticle.title.substring(0, 200),\n summary: scrapedArticle.summary.substring(0, 500),\n body: scrapedArticle.body,\n thumbnail: thumbnailPath,\n publishedAt: scrapedArticle.publishedAt,\n tags: scrapedArticle.tags,\n viewCount: 0,\n sourceUrl: scrapedArticle.url,\n author: scrapedArticle.author || null,\n originalImageUrl: scrapedArticle.imageUrl || null,\n scrapedAt: new Date(),\n isScraped: 1\n };\n \n const article = await storage.createArticle(articleData);\n savedCount++;\n \n allResults.push({\n outlet: outlet.name,\n url: scrapedArticle.url,\n articleTitle: article.title,\n success: true\n });\n \n } catch (error) {\n console.error(`Error saving article from ${scrapedArticle.url}:`, error);\n allErrors.push({\n outlet: outlet.name,\n url: scrapedArticle.url,\n error: error instanceof Error ? error.message : 'Failed to save article'\n });\n }\n }\n \n console.log(`Completed ${outlet.name}: ${savedCount} articles saved`);\n \n // Small delay between outlets to be respectful\n if (processedOutlets < outletsData.length) {\n await new Promise(resolve => setTimeout(resolve, 2000));\n }\n \n } catch (error) {\n console.error(`Error processing outlet ${outletData.name}:`, error);\n allErrors.push({\n outlet: outletData.name,\n error: error instanceof Error ? error.message : 'Failed to process outlet'\n });\n }\n }\n \n res.json({\n success: true,\n summary: {\n totalOutlets: outletsData.length,\n processedOutlets,\n totalArticlesSaved: allResults.length,\n totalErrors: allErrors.length\n },\n results: allResults,\n errors: allErrors,\n message: `Batch scraping completed! Processed ${processedOutlets} outlets, saved ${allResults.length} articles`\n });\n \n } catch (error) {\n console.error(\"Error in batch scraping:\", error);\n res.status(500).json({ \n error: \"Failed to process batch scraping\", \n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Get scraped articles\n app.get(\"/api/scraped-articles\", async (req, res) => {\n try {\n const { limit = 50 } = req.query;\n const limitNum = parseInt(limit as string);\n const articles = await storage.getScrapedArticles(limitNum);\n res.json(articles);\n } catch (error) {\n console.error(\"Error fetching scraped articles:\", error);\n res.status(500).json({ error: \"Failed to fetch scraped articles\" });\n }\n });\n\n // Parse outlet file and scrape all 195 links\n app.post(\"/api/scrape/outlet-file\", async (req, res) => {\n try {\n const { filePath } = req.body;\n \n if (!filePath) {\n return res.status(400).json({ error: \"File path is required\" });\n }\n \n // Parse the outlet file\n console.log('Parsing outlet file for scraping...');\n const outletFilePath = join(process.cwd(), filePath);\n const parsedOutlets = OutletParser.parseOutletFile(outletFilePath);\n \n console.log(`Parsed ${parsedOutlets.total} outlets with links to scrape`);\n \n const scraper = new WebScraper();\n const allResults = [];\n const allErrors = [];\n let processedOutlets = 0;\n \n // Process each category (people, topics, companies)\n for (const category of ['people', 'topics', 'companies'] as const) {\n const outlets = parsedOutlets[category];\n \n for (const outletData of outlets) {\n try {\n processedOutlets++;\n console.log(`Processing ${category} outlet: ${outletData.name} (${outletData.urls.length} URLs)`);\n \n // Find existing outlet or create new one\n let outlet = await storage.getOutletById(outletData.focusSubject);\n \n if (!outlet) {\n console.log(`Creating new outlet: ${outletData.name}`);\n // Create outlet if it doesn't exist\n outlet = await storage.createOutlet({\n name: outletData.name,\n description: `Specialized coverage focusing on ${outletData.name}`,\n category: outletData.category,\n focusSubject: outletData.name,\n bio: `Comprehensive coverage and analysis focusing on ${outletData.name}`,\n avatar: null,\n profileImage: null,\n fullBio: null\n });\n }\n \n // Scrape all URLs for this outlet with controlled concurrency\n const { successes: scrapedArticles, failures: scrapingFailures } = await scraper.scrapeMultipleArticles(outletData.urls, 2);\n \n // Add scraping failures to errors\n for (const failure of scrapingFailures) {\n allErrors.push({\n outlet: outlet.name,\n url: failure.url,\n error: failure.error\n });\n }\n \n for (const scrapedArticle of scrapedArticles) {\n try {\n // Download and process images if available\n let thumbnailPath = '/api/assets/default-article.png';\n if (scrapedArticle.imageUrl) {\n try {\n const imageFilename = `scraped_${outletData.focusSubject}_${Date.now()}_${Math.random().toString(36).substring(7)}.jpg`;\n const downloadedImage = await scraper.downloadImage(scrapedArticle.imageUrl, imageFilename);\n if (downloadedImage) {\n // Create thumbnail\n const thumbnailFilename = `thumb_${imageFilename}`;\n const thumbnailSuccess = await scraper.createThumbnail(\n join(process.cwd(), 'attached_assets', 'scraped', imageFilename),\n join(process.cwd(), 'attached_assets', 'scraped', thumbnailFilename),\n 300\n );\n if (thumbnailSuccess) {\n thumbnailPath = `/api/assets/scraped/${thumbnailFilename}`;\n }\n }\n } catch (imageError) {\n console.warn(`Failed to process image for ${scrapedArticle.url}:`, imageError);\n }\n }\n \n // Create article with scraped data\n const articleData = {\n outletId: outlet.id,\n title: scrapedArticle.title.substring(0, 200),\n summary: scrapedArticle.summary.substring(0, 500),\n body: scrapedArticle.body,\n thumbnail: thumbnailPath,\n publishedAt: scrapedArticle.publishedAt,\n tags: scrapedArticle.tags,\n viewCount: 0,\n sourceUrl: scrapedArticle.url,\n author: scrapedArticle.author || null,\n originalImageUrl: scrapedArticle.imageUrl || null,\n scrapedAt: new Date(),\n isScraped: 1\n };\n \n const article = await storage.createArticle(articleData);\n allResults.push({ \n outlet: outlet.name,\n url: scrapedArticle.url, \n article: {\n id: article.id,\n title: article.title,\n summary: article.summary\n }, \n success: true \n });\n \n } catch (error) {\n console.error(`Error saving scraped article from ${scrapedArticle.url}:`, error);\n allErrors.push({ \n outlet: outlet.name,\n url: scrapedArticle.url, \n error: error instanceof Error ? error.message : 'Failed to save article' \n });\n }\n }\n \n // Add delay between outlets to be respectful\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n } catch (error) {\n console.error(`Error processing outlet ${outletData.name}:`, error);\n allErrors.push({\n outlet: outletData.name,\n url: 'N/A',\n error: error instanceof Error ? error.message : 'Failed to process outlet'\n });\n }\n }\n }\n \n res.json({\n success: true,\n summary: {\n totalOutlets: parsedOutlets.total,\n processedOutlets,\n totalArticlesSaved: allResults.length,\n totalErrors: allErrors.length,\n breakdown: {\n people: parsedOutlets.people.length,\n topics: parsedOutlets.topics.length,\n companies: parsedOutlets.companies.length\n }\n },\n results: allResults,\n errors: allErrors,\n message: `Batch scraping completed! Processed ${processedOutlets} outlets, saved ${allResults.length} articles from ${parsedOutlets.total} total outlets`\n });\n \n } catch (error) {\n console.error(\"Error in outlet file scraping:\", error);\n res.status(500).json({ \n error: \"Failed to process outlet file scraping\", \n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Outlet consolidation endpoint\n app.post(\"/api/outlets/consolidate\", async (req, res) => {\n try {\n console.log(\"Starting outlet consolidation...\");\n\n // 사용자가 제공한 정확한 언론매체 리스트\n const correctOutlets = {\n people: [\n \"Ala Shaabana\", \"Alex Karp\", \"Arthur Hayes\", \"Donald Trump Jr.\", \"Eric Trump\",\n \"Jacob Robert Steeves\", \"Jared Kushner\", \"J.D. Vance\", \"Jensen Huang\", \"Jerome Powell\",\n \"Joseph Jacks\", \"Larry Ellison\", \"Lily Liu\", \"Marco Rubio\", \"Robert Myers\",\n \"Sam Altman\", \"Satya Nadella\", \"Scott Bessent\", \"Simon Kim\", \"Yat Siu\"\n ],\n topics: [\n \"AI\", \"Alt Coin\", \"Bollywood\", \"CantoPop\", \"CBDC (Central Bank Digital Currency)\",\n \"CFTC (Commodity Futures Trading Commission)\", \"Crypto\", \"Custody Regulation\", \"DAT (Digital Asset Treasury)\",\n \"Decentralized AI\", \"DeFi\", \"DEX (Decentralized Exchange)\", \"Fed (Federal Reserve)\",\n \"FOMC (Federal Open Market Committee)\", \"J-Star\", \"K-Star\", \"NFT (Non-Fungible Token)\",\n \"RWA (Real World Assets)\", \"SEC (Securities and Exchange Commission)\", \"Stable Coin\", \"SWF (Sovereign Wealth Fund)\"\n ],\n companies: [\n \"Ava Labs\", \"Bittensor\", \"BlackRock\", \"Boston Dynamics\", \"Chainlink\", \"Circle\",\n \"CME Group\", \"Epic Games\", \"Hashed\", \"Hyperliquid\", \"Oblong\", \"OpenSea\",\n \"Palantir\", \"PancakeSwap\", \"Polygon\", \"Saudi Aramco\", \"Solana Foundation\",\n \"TAOX\", \"TRON\", \"TSMC\", \"Uniswap\", \"World Liberty Financial\", \"xTAO\", \"YUMA\"\n ]\n };\n\n const allOutlets = await storage.getAllOutlets();\n console.log(`Found ${allOutlets.length} existing outlets`);\n\n // 중복된 언론매체들을 찾아내기 위한 매핑\n const duplicateGroups: { [key: string]: MediaOutlet[] } = {};\n const correctNames = [\n ...correctOutlets.people,\n ...correctOutlets.topics,\n ...correctOutlets.companies\n ];\n\n // 각 정확한 이름에 대해 유사한 이름들을 찾기\n for (const correctName of correctNames) {\n const similarOutlets = allOutlets.filter(outlet => {\n const outletName = outlet.name.toLowerCase().trim();\n const correctNameLower = correctName.toLowerCase().trim();\n \n // 정확히 일치하거나, 한글/영어 설명이 포함된 경우\n return outletName === correctNameLower ||\n outletName.includes(correctNameLower) ||\n correctNameLower.includes(outletName) ||\n outletName.includes(correctNameLower.split(' ')[0]) ||\n outletName.includes(correctNameLower.split('-')[0]);\n });\n\n if (similarOutlets.length > 1) {\n duplicateGroups[correctName] = similarOutlets;\n }\n }\n\n console.log(`Found ${Object.keys(duplicateGroups).length} duplicate groups`);\n\n const consolidationResults: any[] = [];\n let totalMergedOutlets = 0;\n let totalMovedArticles = 0;\n\n // 각 중복 그룹에 대해 통합 작업 수행\n for (const [correctName, duplicates] of Object.entries(duplicateGroups)) {\n if (duplicates.length <= 1) continue;\n\n console.log(`Processing duplicates for: ${correctName}`);\n \n // 정확한 이름과 가장 일치하는 언론매체를 찾기\n let mainOutlet = duplicates.find(outlet => \n outlet.name.toLowerCase().trim() === correctName.toLowerCase().trim()\n );\n\n // 정확한 일치가 없으면 첫 번째를 main으로 사용\n if (!mainOutlet) {\n mainOutlet = duplicates[0];\n // 이름을 정확한 이름으로 업데이트\n await storage.updateOutlet(mainOutlet.id, { name: correctName });\n console.log(`Updated outlet name from \"${mainOutlet.name}\" to \"${correctName}\"`);\n }\n\n // 나머지 중복 언론매체들을 main으로 통합\n const duplicatesToMerge = duplicates.filter(outlet => outlet.id !== mainOutlet!.id);\n let movedArticlesCount = 0;\n\n for (const duplicate of duplicatesToMerge) {\n console.log(`Merging \"${duplicate.name}\" into \"${mainOutlet.name}\"`);\n \n const mergeResult = await storage.mergeOutlets(duplicate.id, mainOutlet.id);\n if (mergeResult.success) {\n movedArticlesCount += mergeResult.movedArticles;\n totalMergedOutlets++;\n console.log(`Successfully merged ${duplicate.name}, moved ${mergeResult.movedArticles} articles`);\n } else {\n console.error(`Failed to merge ${duplicate.name}`);\n }\n }\n\n totalMovedArticles += movedArticlesCount;\n consolidationResults.push({\n correctName,\n mainOutletId: mainOutlet.id,\n mergedOutlets: duplicatesToMerge.map(d => d.name),\n movedArticles: movedArticlesCount\n });\n }\n\n console.log(\"Outlet consolidation completed\");\n\n res.json({\n success: true,\n summary: {\n totalDuplicateGroups: Object.keys(duplicateGroups).length,\n totalMergedOutlets,\n totalMovedArticles,\n initialOutletCount: allOutlets.length,\n finalOutletCount: allOutlets.length - totalMergedOutlets\n },\n consolidationResults,\n message: `Successfully consolidated ${totalMergedOutlets} duplicate outlets, moved ${totalMovedArticles} articles`\n });\n\n } catch (error) {\n console.error(\"Error in outlet consolidation:\", error);\n res.status(500).json({\n error: \"Failed to consolidate outlets\",\n details: error instanceof Error ? error.message : 'Unknown error'\n });\n }\n });\n\n // Bookmark routes\n app.post(\"/api/bookmarks/toggle\", async (req, res) => {\n try {\n const { articleId, userIdentifier } = req.body;\n if (!articleId || !userIdentifier) {\n return res.status(400).json({ error: \"articleId and userIdentifier are required\" });\n }\n const result = await storage.toggleBookmark(articleId, userIdentifier);\n res.json(result);\n } catch (error) {\n console.error(\"Error toggling bookmark:\", error);\n res.status(500).json({ error: \"Failed to toggle bookmark\" });\n }\n });\n\n app.get(\"/api/bookmarks/:articleId/:userIdentifier\", async (req, res) => {\n try {\n const { articleId, userIdentifier } = req.params;\n const isBookmarked = await storage.isBookmarked(articleId, userIdentifier);\n res.json({ isBookmarked });\n } catch (error) {\n console.error(\"Error checking bookmark:\", error);\n res.status(500).json({ error: \"Failed to check bookmark\" });\n }\n });\n\n app.get(\"/api/bookmarks/user/:userIdentifier\", async (req, res) => {\n try {\n const { userIdentifier } = req.params;\n const bookmarks = await storage.getUserBookmarks(userIdentifier);\n res.json({ bookmarks });\n } catch (error) {\n console.error(\"Error getting user bookmarks:\", error);\n res.status(500).json({ error: \"Failed to get bookmarks\" });\n }\n });\n\n // Article stats routes\n app.get(\"/api/articles/:id/comment-count\", async (req, res) => {\n try {\n const { id } = req.params;\n const count = await storage.getArticleCommentCount(id);\n res.json({ count });\n } catch (error) {\n console.error(\"Error getting comment count:\", error);\n res.status(500).json({ error: \"Failed to get comment count\" });\n }\n });\n\n // Prediction Market routes\n app.get(\"/api/prediction-markets/article/:articleId\", async (req, res) => {\n try {\n const { articleId } = req.params;\n const limit = parseInt(req.query.limit as string) || 3;\n const offset = parseInt(req.query.offset as string) || 0;\n \n const markets = await storage.getPredictionMarketsByArticle(articleId, { limit, offset });\n res.json(markets);\n } catch (error) {\n console.error(\"Error getting prediction markets:\", error);\n res.status(500).json({ error: \"Failed to get prediction markets\" });\n }\n });\n\n // Serve attached assets route\n app.use(\"/api/assets\", express.static(path.resolve(process.cwd(), \"attached_assets\")));\n\n const httpServer = createServer(app);\n return httpServer;\n}","size_bytes":62895},"server/storage.ts":{"content":"import { \n type User, \n type InsertUser, \n type MediaOutlet, \n type InsertMediaOutlet, \n type Article, \n type InsertArticle,\n type Comment,\n type InsertComment,\n type CommentReaction,\n type InsertCommentReaction,\n type Bookmark,\n type InsertBookmark,\n type PredictionMarket,\n type InsertPredictionMarket,\n users,\n mediaOutlets,\n articles,\n comments,\n commentReactions,\n bookmarks,\n predictionMarkets\n} from \"@shared/schema\";\nimport { randomUUID } from \"crypto\";\nimport { drizzle } from \"drizzle-orm/neon-http\";\nimport { neon } from \"@neondatabase/serverless\";\nimport { eq, desc, asc, and, or, sql, like, count } from \"drizzle-orm\";\n\n// Initialize database connection\nif (!process.env.DATABASE_URL) {\n throw new Error(\"DATABASE_URL environment variable is required\");\n}\n\nconst sqlClient = neon(process.env.DATABASE_URL);\nconst db = drizzle(sqlClient);\n\n// Storage interface for the news platform\nexport interface IStorage {\n // User methods\n getUser(id: string): Promise;\n getUserByUsername(username: string): Promise;\n createUser(user: InsertUser): Promise;\n \n // Media outlet methods\n getAllOutlets(): Promise;\n getOutletsByCategory(category: string): Promise;\n getOutletById(id: string): Promise;\n createOutlet(outlet: InsertMediaOutlet): Promise;\n deleteOutlet(id: string): Promise;\n updateOutlet(id: string, updates: Partial): Promise;\n mergeOutlets(fromOutletId: string, toOutletId: string): Promise<{ success: boolean; movedArticles: number }>;\n \n // Article methods\n getAllArticles(): Promise;\n getArticlesByOutlet(outletId: string): Promise;\n getArticleById(id: string): Promise
;\n getFeaturedArticles(limit?: number): Promise;\n searchArticles(query: string): Promise;\n createArticle(article: InsertArticle): Promise
;\n deleteArticle(id: string): Promise;\n \n // Scraped article methods\n createScrapedArticle(article: Omit & { \n sourceUrl: string; \n author?: string; \n originalImageUrl?: string; \n isScraped?: number;\n }): Promise
;\n getScrapedArticles(limit?: number): Promise;\n updateArticleWithScrapedData(id: string, data: {\n sourceUrl?: string;\n author?: string;\n originalImageUrl?: string;\n }): Promise
;\n \n // Thumbnail generation methods\n updateArticleThumbnail(id: string, thumbnailPath: string): Promise
;\n \n // YouTube-style feed methods (enriched with outlet data)\n listFeed(params: { cursor?: string; limit?: number; filter?: 'all' | 'people' | 'topics' | 'companies' }): Promise<{ items: (Article & { outletName: string; outletAvatar: string; category: string })[]; nextCursor?: string }>;\n incrementView(id: string): Promise;\n \n // Comment system methods\n getCommentsByArticle(articleId: string, params: { limit?: number; offset?: number }): Promise<{ comments: Comment[]; total: number }>;\n getCommentReplies(parentId: string, params: { limit?: number; offset?: number }): Promise<{ comments: Comment[]; total: number }>;\n getCommentById(id: string): Promise;\n createComment(comment: InsertComment): Promise;\n updateComment(id: string, content: string): Promise;\n deleteComment(id: string): Promise;\n \n // Comment reaction methods (atomic operations)\n toggleCommentReaction(commentId: string, userIdentifier: string, reactionType: 'like' | 'dislike'): Promise<{ action: 'added' | 'removed' | 'changed'; reaction: CommentReaction | null }>;\n getUserCommentReaction(commentId: string, userIdentifier: string): Promise;\n \n // Bookmark methods\n toggleBookmark(articleId: string, userIdentifier: string): Promise<{ action: 'added' | 'removed'; bookmark: Bookmark | null }>;\n isBookmarked(articleId: string, userIdentifier: string): Promise;\n getUserBookmarks(userIdentifier: string): Promise;\n \n // Article stats methods\n getArticleCommentCount(articleId: string): Promise;\n \n // Article deduplication methods\n removeDuplicateArticles(): Promise<{ removedCount: number; details: { outletId: string; duplicatesRemoved: number }[] }>;\n \n // Prediction Market methods\n getPredictionMarketsByArticle(articleId: string, params: { limit?: number; offset?: number }): Promise;\n getPredictionMarketById(id: string): Promise;\n createPredictionMarket(market: InsertPredictionMarket): Promise;\n}\n\nexport class DbStorage implements IStorage {\n // In-memory Maps for hybrid storage approach\n private outlets = new Map();\n private users = new Map();\n private articles = new Map();\n private comments = new Map();\n private commentReactions = new Map();\n private bookmarks = new Map();\n\n constructor() {\n this.logDatabaseStats();\n this.initializeDefaultData();\n }\n\n private async logDatabaseStats() {\n try {\n const outletCount = await db.select({ count: count() }).from(mediaOutlets);\n const articleCount = await db.select({ count: count() }).from(articles);\n console.log(`[DbStorage] Connected to database with ${outletCount[0].count} outlets and ${articleCount[0].count} articles`);\n } catch (error) {\n console.error('[DbStorage] Failed to connect to database:', error);\n }\n }\n\n private async initializeDefaultData() {\n // Initialize with new outlet structure based on requirements\n const defaultOutlets = [\n // People Category (4 outlets)\n {\n id: 'jacob-robert-steeves',\n name: 'Jacob Robert Steeves',\n description: 'Co-founder of Bittensor and primary architect of decentralized AI',\n category: 'people',\n focusSubject: 'Jacob Robert Steeves',\n avatar: '/api/assets/jacob-steeves_1758526589973.png',\n profileImage: '/api/assets/steeves thumbnail_1758526589975.png',\n bio: 'Co-founder of Bittensor and a primary architect of its decentralized AI network.',\n fullBio: [\n 'Co-founder of Bittensor and primary architect of the decentralized AI network protocol.',\n 'Visionary leader advocating for open, permissionless intelligence markets and AI democratization.',\n 'Technical expert directing core research in AI consensus mechanisms and protocol development.'\n ]\n },\n {\n id: 'ala-shaabana',\n name: 'Ala Shaabana',\n description: 'Co-founder and key technical architect of Bittensor',\n category: 'people',\n focusSubject: 'Ala Shaabana',\n avatar: '/api/assets/Ala Shaabana_1758526589971.jpeg',\n profileImage: '/api/assets/ala thumbnail_1758526589972.png',\n bio: 'A co-founder of Bittensor and a key technical architect of its decentralized AI network.',\n fullBio: [\n 'Co-founder of Bittensor with a Ph.D. in Computer Science specializing in advanced AI and machine learning.',\n 'Primary architect of the Bittensor protocol\\'s complex incentive and consensus mechanisms.',\n 'Known for technical precision and focus on scalability in decentralized AI network design.'\n ]\n },\n {\n id: 'joseph-jacks',\n name: 'Joseph Jacks',\n description: 'Founder of Open Source Capital and Bittensor advocate',\n category: 'people',\n focusSubject: 'Joseph Jacks',\n avatar: '/api/assets/Joseph Jacks_1758526589973.jpeg',\n profileImage: '/api/assets/joseph thumbnail_1758526589974.png',\n bio: 'Founder and General Partner of OSS Capital, a venture capital firm with a strong focus on open-source software.',\n fullBio: [\n 'Founder and General Partner of OSS Capital, the first venture capital fund exclusively focused on commercial open-source software (COSS). Since 2018, has led over 40 funding rounds representing $200+ million in investments.',\n 'Entrepreneurial background includes founding Kismatic (first enterprise Kubernetes company, acquired by Apprenda), co-founding Aljabr cloud data management startup, and creating KubeCon conference now run by Linux Foundation.',\n 'Previously held strategic roles at Mesosphere (D2IQ), Enstratius (acquired by Dell), TIBCO Software, and Talend. Served as Entrepreneur in Residence at Quantum Corporation supporting the Rook project.',\n 'Visionary behind Open Core Summit, the global vendor-neutral conference for the COSS ecosystem, bringing together 1,000+ attendees from 29 countries, 40+ sponsors, and 100+ speakers annually.',\n 'Investment portfolio includes notable successes like Remix (acquired by Shopify), OpenBB (Bloomberg Terminal alternative), and dozens of open-source alternatives to major enterprise software platforms.',\n 'Limited partners include tech luminaries: WordPress co-creator Matt Mullenweg, Red Hat co-founder Bob Young, YouTube founders Chad Hurley and Steve Chen, GitHub co-founder Tom Preston-Werner, and Shopify founder Tobias Lütke.',\n 'Core investment philosophy: \"Open source is eating software faster than software is eating the world\" - believes open core approach will replace closed core SaaS companies entirely.',\n 'Serves on boards of multiple portfolio companies including Plane, OpenBB, DeSci Labs, and Liquid AI, actively guiding the next generation of open-source commercial enterprises.'\n ]\n },\n {\n id: 'robert-myers',\n name: 'Robert Myers',\n description: 'CEO of Manifold Labs and former Opentensor Foundation co-founder',\n category: 'people',\n focusSubject: 'Robert Myers',\n avatar: '/api/assets/Robert Myers_1758526589974.jpg',\n profileImage: '/api/assets/robert thumbnail_1758526589974.png',\n bio: 'Co-founder and former Marketing Director of Opentensor Foundation, currently CEO of Manifold Labs.',\n fullBio: [\n 'Co-founder and former Marketing Director of Opentensor Foundation behind Bittensor.',\n 'Current CEO of Manifold Labs, AI infrastructure company funded by OSS Capital.',\n 'Focus on building critical tools and infrastructure for decentralized AI networks.'\n ]\n },\n // Topics Category (3 outlets)\n {\n id: 'alt-coin',\n name: 'Alt Coin',\n description: 'Coverage of alternative cryptocurrencies and emerging tokens',\n category: 'topics',\n focusSubject: 'Alt Coin',\n avatar: '/api/assets/altcoin_1758526589973.jpeg',\n profileImage: '/api/assets/alt coin news_1758526589972.png',\n bio: 'A term for any cryptocurrency other than Bitcoin (BTC).',\n fullBio: [\n 'Any cryptocurrency other than Bitcoin, built to solve problems like scalability, privacy, or smart contracts.',\n 'Highly volatile and speculative market with potential for massive gains and significant losses.',\n 'Success depends on community strength, network utility, and technological innovation.'\n ]\n },\n {\n id: 'stable-coin',\n name: 'Stable Coin',\n description: 'Analysis of stablecoins and price-stable digital assets',\n category: 'topics',\n focusSubject: 'Stable Coin',\n avatar: '/api/assets/stable coin_1758526589975.jpeg',\n profileImage: '/api/assets/stable coin news_1758526589975.png',\n bio: 'A class of cryptocurrencies designed to minimize price volatility, often pegged to a fiat currency like the US Dollar.',\n fullBio: [\n 'Cryptocurrency designed to minimize price volatility, usually pegged to fiat currencies like USD.',\n 'Collateralized by fiat, other cryptocurrencies, or algorithmic mechanisms to maintain price stability.',\n 'Essential for cross-border transactions and DeFi by providing stable store of value.'\n ]\n },\n {\n id: 'bittensor',\n name: 'Bittensor',\n description: 'Comprehensive coverage of the Bittensor network and ecosystem',\n category: 'topics',\n focusSubject: 'Bittensor',\n avatar: '/api/assets/Bittensor_1758526589973.jpg',\n profileImage: '/api/assets/Bittensor_1758526589973.jpg',\n bio: 'A decentralized blockchain network focused on creating a global, open marketplace for artificial intelligence.',\n fullBio: [\n 'Decentralized blockchain network creating a global marketplace for artificial intelligence.',\n 'Uses \"Yuma Consensus\" mechanism and specialized \"Subnets\" for AI tasks like language processing.',\n 'Native TAO token incentivizes participation and democratizes AI away from centralized corporate control.'\n ]\n },\n {\n id: 'dat',\n name: 'DAT',\n description: 'Digital Asset Treasury strategies and corporate cryptocurrency adoption',\n category: 'topics',\n focusSubject: 'DAT',\n avatar: '/api/assets/dat_default.jpeg',\n profileImage: '/api/assets/dat_news_default.png',\n bio: 'Digital Asset Treasury strategies helping corporations integrate cryptocurrency into their treasury management.',\n fullBio: [\n 'Digital Asset Treasury strategies transforming corporate treasury management through cryptocurrency integration.',\n 'Comprehensive framework for institutional digital asset adoption including custody, compliance, and risk management.',\n 'Leading the transition from traditional corporate treasuries to multi-asset digital strategies.'\n ]\n },\n // Additional Topics Category outlets\n {\n id: 'blockchain',\n name: 'Blockchain',\n description: 'Comprehensive blockchain technology news and analysis',\n category: 'topics',\n focusSubject: 'Blockchain',\n avatar: '/api/assets/blockchain_1758526589973.jpeg',\n profileImage: '/api/assets/blockchain_news_1758526589972.png',\n bio: 'The foundational technology behind cryptocurrencies and decentralized applications.',\n fullBio: [\n 'Distributed ledger technology that maintains a continuously growing list of records.',\n 'Enables trustless transactions and smart contracts without central authority.',\n 'Revolutionary technology transforming finance, supply chain, and digital identity.'\n ]\n },\n {\n id: 'defi',\n name: 'DeFi',\n description: 'Decentralized Finance protocols and innovations',\n category: 'topics',\n focusSubject: 'DeFi',\n avatar: '/api/assets/defi_1758526589973.jpeg',\n profileImage: '/api/assets/defi_news_1758526589972.png',\n bio: 'Decentralized Financial services built on blockchain technology.',\n fullBio: [\n 'Financial services using smart contracts instead of traditional intermediaries.',\n 'Includes lending, borrowing, trading, and yield farming protocols.',\n 'Democratizes access to financial services globally without traditional barriers.'\n ]\n },\n {\n id: 'nft',\n name: 'NFT',\n description: 'Non-Fungible Tokens and digital collectibles market',\n category: 'topics',\n focusSubject: 'NFT',\n avatar: '/api/assets/nft_1758526589973.jpeg',\n profileImage: '/api/assets/nft_news_1758526589972.png',\n bio: 'Unique digital assets representing ownership of digital or physical items.',\n fullBio: [\n 'Non-fungible tokens that represent unique ownership of digital assets.',\n 'Revolutionizing art, gaming, music, and digital collectibles markets.',\n 'Enables creators to monetize digital content with verified scarcity.'\n ]\n },\n {\n id: 'dao',\n name: 'DAO',\n description: 'Decentralized Autonomous Organizations and governance',\n category: 'topics',\n focusSubject: 'DAO',\n avatar: '/api/assets/dao_1758526589973.jpeg',\n profileImage: '/api/assets/dao_news_1758526589972.png',\n bio: 'Organizations governed by smart contracts and community voting.',\n fullBio: [\n 'Organizations governed entirely by smart contracts and token holder voting.',\n 'Enables transparent, democratic decision-making without traditional management.',\n 'Revolutionary organizational structure for the decentralized economy.'\n ]\n },\n {\n id: 'metaverse',\n name: 'Metaverse',\n description: 'Virtual worlds and immersive digital experiences',\n category: 'topics',\n focusSubject: 'Metaverse',\n avatar: '/api/assets/metaverse_1758526589973.jpeg',\n profileImage: '/api/assets/metaverse_news_1758526589972.png',\n bio: 'Persistent virtual worlds where users interact in immersive digital environments.',\n fullBio: [\n 'Persistent virtual worlds enabling social interaction and economic activity.',\n 'Combines VR, AR, blockchain, and AI to create immersive digital experiences.',\n 'The future of social media, gaming, and digital commerce.'\n ]\n },\n {\n id: 'ai-crypto',\n name: 'AI Crypto',\n description: 'Artificial Intelligence and cryptocurrency convergence',\n category: 'topics',\n focusSubject: 'AI Crypto',\n avatar: '/api/assets/ai_crypto_1758526589973.jpeg',\n profileImage: '/api/assets/ai_crypto_news_1758526589972.png',\n bio: 'The intersection of artificial intelligence and cryptocurrency technologies.',\n fullBio: [\n 'Intersection of artificial intelligence and cryptocurrency technologies.',\n 'AI-powered trading, predictive analytics, and automated market making.',\n 'Decentralized AI networks incentivized by cryptocurrency tokens.'\n ]\n },\n {\n id: 'layer2',\n name: 'Layer 2',\n description: 'Blockchain scaling solutions and second-layer protocols',\n category: 'topics',\n focusSubject: 'Layer 2',\n avatar: '/api/assets/layer2_1758526589973.jpeg',\n profileImage: '/api/assets/layer2_news_1758526589972.png',\n bio: 'Scaling solutions built on top of existing blockchain networks.',\n fullBio: [\n 'Scaling solutions that process transactions off the main blockchain.',\n 'Reduces fees and increases transaction throughput significantly.',\n 'Critical infrastructure for blockchain mass adoption and usability.'\n ]\n },\n {\n id: 'privacy-coins',\n name: 'Privacy Coins',\n description: 'Privacy-focused cryptocurrencies and anonymous transactions',\n category: 'topics',\n focusSubject: 'Privacy Coins',\n avatar: '/api/assets/privacy_coins_1758526589973.jpeg',\n profileImage: '/api/assets/privacy_coins_news_1758526589972.png',\n bio: 'Cryptocurrencies designed to provide enhanced privacy and anonymity.',\n fullBio: [\n 'Cryptocurrencies using advanced cryptography to ensure transaction privacy.',\n 'Protects user financial privacy from surveillance and data mining.',\n 'Essential for financial freedom and protection of personal information.'\n ]\n },\n {\n id: 'gamefi',\n name: 'GameFi',\n description: 'Gaming and decentralized finance integration',\n category: 'topics',\n focusSubject: 'GameFi',\n avatar: '/api/assets/gamefi_1758526589973.jpeg',\n profileImage: '/api/assets/gamefi_news_1758526589972.png',\n bio: 'Games that integrate DeFi elements and play-to-earn mechanics.',\n fullBio: [\n 'Games that integrate DeFi elements and blockchain-based ownership.',\n 'Players earn cryptocurrency rewards for gameplay and participation.',\n 'Revolutionizing gaming economics through true digital asset ownership.'\n ]\n },\n {\n id: 'socialfi',\n name: 'SocialFi',\n description: 'Social media platforms with financial incentives',\n category: 'topics',\n focusSubject: 'SocialFi',\n avatar: '/api/assets/socialfi_1758526589973.jpeg',\n profileImage: '/api/assets/socialfi_news_1758526589972.png',\n bio: 'Social media platforms that reward users with cryptocurrency.',\n fullBio: [\n 'Social media platforms that reward content creation and engagement.',\n 'Users earn tokens for creating quality content and building communities.',\n 'Aligns incentives between platforms, creators, and audiences.'\n ]\n },\n {\n id: 'cbdc',\n name: 'CBDC',\n description: 'Central Bank Digital Currencies and government crypto',\n category: 'topics',\n focusSubject: 'CBDC',\n avatar: '/api/assets/cbdc_1758526589973.jpeg',\n profileImage: '/api/assets/cbdc_news_1758526589972.png',\n bio: 'Digital versions of national currencies issued by central banks.',\n fullBio: [\n 'Digital versions of fiat currencies issued and controlled by central banks.',\n 'Combines benefits of digital payments with government backing.',\n 'Represents governments adoption of blockchain technology for monetary policy.'\n ]\n },\n {\n id: 'cross-chain',\n name: 'Cross-Chain',\n description: 'Blockchain interoperability and cross-chain protocols',\n category: 'topics',\n focusSubject: 'Cross-Chain',\n avatar: '/api/assets/cross_chain_1758526589973.jpeg',\n profileImage: '/api/assets/cross_chain_news_1758526589972.png',\n bio: 'Technologies enabling communication and value transfer between different blockchains.',\n fullBio: [\n 'Technologies enabling communication between different blockchain networks.',\n 'Allows assets and data to move freely across multiple chains.',\n 'Critical for blockchain ecosystem maturity and user experience.'\n ]\n },\n {\n id: 'yield-farming',\n name: 'Yield Farming',\n description: 'DeFi yield generation strategies and liquidity mining',\n category: 'topics',\n focusSubject: 'Yield Farming',\n avatar: '/api/assets/yield_farming_1758526589973.jpeg',\n profileImage: '/api/assets/yield_farming_news_1758526589972.png',\n bio: 'Strategies to maximize returns by providing liquidity to DeFi protocols.',\n fullBio: [\n 'Strategies to maximize returns by providing liquidity to DeFi protocols.',\n 'Users lend or stake tokens to earn high yields and bonus rewards.',\n 'Core economic activity driving DeFi protocol growth and adoption.'\n ]\n },\n {\n id: 'tokenomics',\n name: 'Tokenomics',\n description: 'Cryptocurrency token economics and design principles',\n category: 'topics',\n focusSubject: 'Tokenomics',\n avatar: '/api/assets/tokenomics_1758526589973.jpeg',\n profileImage: '/api/assets/tokenomics_news_1758526589972.png',\n bio: 'The economic design and incentive structures of cryptocurrency tokens.',\n fullBio: [\n 'Economic design and incentive structures behind cryptocurrency tokens.',\n 'Determines how tokens are distributed, used, and valued over time.',\n 'Critical factor in the long-term success of blockchain projects.'\n ]\n },\n {\n id: 'regulation',\n name: 'Regulation',\n description: 'Cryptocurrency regulation and government policy',\n category: 'topics',\n focusSubject: 'Regulation',\n avatar: '/api/assets/regulation_1758526589973.jpeg',\n profileImage: '/api/assets/regulation_news_1758526589972.png',\n bio: 'Government policies and regulations affecting the cryptocurrency industry.',\n fullBio: [\n 'Government policies and regulations shaping the cryptocurrency industry.',\n 'Balances innovation, consumer protection, and financial stability.',\n 'Critical factor determining mainstream adoption and institutional investment.'\n ]\n },\n {\n id: 'mining',\n name: 'Mining',\n description: 'Cryptocurrency mining and proof-of-work consensus',\n category: 'topics',\n focusSubject: 'Mining',\n avatar: '/api/assets/mining_1758526589973.jpeg',\n profileImage: '/api/assets/mining_news_1758526589972.png',\n bio: 'The process of validating transactions and securing blockchain networks.',\n fullBio: [\n 'Process of validating transactions and securing proof-of-work blockchains.',\n 'Miners compete to solve cryptographic puzzles for block rewards.',\n 'Essential infrastructure maintaining decentralization and network security.'\n ]\n },\n {\n id: 'staking',\n name: 'Staking',\n description: 'Proof-of-stake validation and staking rewards',\n category: 'topics',\n focusSubject: 'Staking',\n avatar: '/api/assets/staking_1758526589973.jpeg',\n profileImage: '/api/assets/staking_news_1758526589972.png',\n bio: 'Locking tokens to help secure proof-of-stake networks and earn rewards.',\n fullBio: [\n 'Locking tokens to help validate transactions on proof-of-stake networks.',\n 'More energy-efficient alternative to proof-of-work mining.',\n 'Allows token holders to earn passive income while securing networks.'\n ]\n },\n {\n id: 'institutional',\n name: 'Institutional',\n description: 'Institutional cryptocurrency adoption and investment',\n category: 'topics',\n focusSubject: 'Institutional',\n avatar: '/api/assets/institutional_1758526589973.jpeg',\n profileImage: '/api/assets/institutional_news_1758526589972.png',\n bio: 'Large institutions and corporations adopting cryptocurrency.',\n fullBio: [\n 'Large institutions and corporations adopting cryptocurrency investments.',\n 'Banks, hedge funds, and public companies adding crypto to portfolios.',\n 'Driving mainstream adoption and market maturation.'\n ]\n },\n {\n id: 'derivatives',\n name: 'Derivatives',\n description: 'Cryptocurrency derivatives and financial instruments',\n category: 'topics',\n focusSubject: 'Derivatives',\n avatar: '/api/assets/derivatives_1758526589973.jpeg',\n profileImage: '/api/assets/derivatives_news_1758526589972.png',\n bio: 'Financial instruments derived from cryptocurrency underlying assets.',\n fullBio: [\n 'Financial instruments like futures, options, and swaps on cryptocurrencies.',\n 'Enables sophisticated trading strategies and risk management.',\n 'Critical infrastructure for institutional participation in crypto markets.'\n ]\n },\n // Additional People Category outlets\n {\n id: 'vitalik-buterin',\n name: 'Vitalik Buterin',\n description: 'Ethereum founder and blockchain visionary',\n category: 'people',\n focusSubject: 'Vitalik Buterin',\n avatar: '/api/assets/vitalik_1758526589973.jpeg',\n profileImage: '/api/assets/vitalik_news_1758526589972.png',\n bio: 'Co-founder of Ethereum and one of the most influential figures in blockchain.',\n fullBio: [\n 'Co-founder of Ethereum, the worlds second-largest cryptocurrency platform.',\n 'Visionary programmer who conceptualized smart contracts and decentralized applications.',\n 'Leading voice in blockchain scalability, governance, and decentralization.'\n ]\n },\n {\n id: 'satoshi-nakamoto',\n name: 'Satoshi Nakamoto',\n description: 'Anonymous creator of Bitcoin and blockchain technology',\n category: 'people',\n focusSubject: 'Satoshi Nakamoto',\n avatar: '/api/assets/satoshi_1758526589973.jpeg',\n profileImage: '/api/assets/satoshi_news_1758526589972.png',\n bio: 'Pseudonymous creator of Bitcoin, the first and most famous cryptocurrency.',\n fullBio: [\n 'Pseudonymous creator of Bitcoin and inventor of blockchain technology.',\n 'Published the Bitcoin whitepaper in 2008, launching the cryptocurrency revolution.',\n 'Mysterious figure who disappeared from public view in 2011.'\n ]\n },\n {\n id: 'changpeng-zhao',\n name: 'Changpeng Zhao',\n description: 'Former CEO of Binance and crypto exchange pioneer',\n category: 'people',\n focusSubject: 'Changpeng Zhao',\n avatar: '/api/assets/cz_1758526589973.jpeg',\n profileImage: '/api/assets/cz_news_1758526589972.png',\n bio: 'Former CEO of Binance, the worlds largest cryptocurrency exchange.',\n fullBio: [\n 'Former CEO of Binance, building it into the worlds largest crypto exchange.',\n 'Pioneered many innovations in cryptocurrency trading and DeFi.',\n 'Influential leader in global cryptocurrency adoption and regulation.'\n ]\n },\n {\n id: 'brian-armstrong',\n name: 'Brian Armstrong',\n description: 'CEO of Coinbase and cryptocurrency adoption advocate',\n category: 'people',\n focusSubject: 'Brian Armstrong',\n avatar: '/api/assets/brian_armstrong_1758526589973.jpeg',\n profileImage: '/api/assets/brian_armstrong_news_1758526589972.png',\n bio: 'CEO and co-founder of Coinbase, the largest US cryptocurrency exchange.',\n fullBio: [\n 'CEO and co-founder of Coinbase, Americas leading cryptocurrency platform.',\n 'Advocate for clear cryptocurrency regulation and mainstream adoption.',\n 'Leading voice in bringing cryptocurrency to traditional financial institutions.'\n ]\n },\n {\n id: 'andreas-antonopoulos',\n name: 'Andreas Antonopoulos',\n description: 'Bitcoin educator and blockchain technology advocate',\n category: 'people',\n focusSubject: 'Andreas Antonopoulos',\n avatar: '/api/assets/andreas_1758526589973.jpeg',\n profileImage: '/api/assets/andreas_news_1758526589972.png',\n bio: 'Renowned Bitcoin educator and author of \"Mastering Bitcoin.\"',\n fullBio: [\n 'Renowned Bitcoin educator and author of \"Mastering Bitcoin\" and \"Mastering Ethereum.\"',\n 'Passionate advocate for decentralization and financial sovereignty.',\n 'Influential speaker educating millions about cryptocurrency technology.'\n ]\n },\n {\n id: 'michael-saylor',\n name: 'Michael Saylor',\n description: 'MicroStrategy CEO and Bitcoin maximalist',\n category: 'people',\n focusSubject: 'Michael Saylor',\n avatar: '/api/assets/saylor_1758526589973.jpeg',\n profileImage: '/api/assets/saylor_news_1758526589972.png',\n bio: 'CEO of MicroStrategy and prominent Bitcoin advocate.',\n fullBio: [\n 'Born February 4, 1965 in military family, graduated first in class from high school, earned full ROTC scholarship to MIT where he double-majored in aeronautical engineering and history of science, graduating with highest honors in 1987.',\n 'Founded MicroStrategy in 1989 with MIT fraternity brother Sanju Bansal, initially focused on business intelligence software. Won $10 million McDonald\\'s contract in 1992, took company public in 1998.',\n 'Survived dot-com crash devastation when stock plummeted from $333 to $120 in single day (March 2000). Paid $350,000 SEC penalty plus $8.3 million disgorgement for financial reporting issues.',\n 'Prolific inventor holding 48+ patents, credited as inventor of relational analytics. Founded multiple companies including Alarm.com (NASDAQ: ALRM) and Angel.com (sold for $110M).',\n 'Author of \"The Mobile Wave\" (NYT/WSJ bestseller), founded Saylor Academy providing free education to 1.8+ million students. MIT Technology Review \"Innovator Under 35\" (1999).',\n 'Executive Chairman of MicroStrategy since 2022, previously CEO for 33 years. Led corporate Bitcoin adoption strategy purchasing 639,835+ bitcoins worth billions, making MSTR largest corporate Bitcoin holder.',\n 'Bitcoin maximalist advocate promoting cryptocurrency as superior store of value and inflation hedge. His Bitcoin strategy transformed MicroStrategy from traditional software company to Bitcoin proxy investment vehicle.'\n ]\n },\n {\n id: 'elon-musk',\n name: 'Elon Musk',\n description: 'Tesla CEO and influential cryptocurrency commentator',\n category: 'people',\n focusSubject: 'Elon Musk',\n avatar: '/api/assets/elon_1758526589973.jpeg',\n profileImage: '/api/assets/elon_news_1758526589972.png',\n bio: 'CEO of Tesla and SpaceX, influential voice in cryptocurrency markets.',\n fullBio: [\n 'World\\'s wealthiest person (net worth $384-$487 billion as of 2025), born June 28, 1971 in Pretoria, South Africa. Emigrated to avoid apartheid military service, studied at Queen\\'s University and University of Pennsylvania (Economics + Physics degrees).',\n 'Early entrepreneur: Created and sold video game at age 12, co-founded Zip2 (sold for $307M), then X.com which merged to become PayPal (sold to eBay for $1.5B, Musk received $176M).',\n 'Founded SpaceX in 2002 with vision of Mars colonization, now leading private space company. First private company to send astronauts to ISS (2020), pioneered reusable rockets, operates Starlink satellite constellation.',\n 'CEO of Tesla since 2008, driving global electric vehicle revolution. Transformed company from startup to world\\'s most valuable automaker with Model S, 3, X lineup and autonomous driving technology.',\n 'Acquired Twitter for $44 billion in 2022, rebranded to X as part of vision for \"everything app.\" Also founded Neuralink (brain-machine interfaces), The Boring Company (tunnel infrastructure), and xAI (AI competitor to ChatGPT).',\n 'Briefly served as co-head of Department of Government Efficiency (DOGE) under Trump administration (January-May 2025) before returning focus to business ventures.',\n 'Known for 80-hour work weeks, visionary leadership in sustainable transport, space exploration, and artificial intelligence. His social media presence significantly impacts cryptocurrency and stock markets globally.'\n ]\n },\n {\n id: 'gavin-wood',\n name: 'Gavin Wood',\n description: 'Polkadot founder and Ethereum co-founder',\n category: 'people',\n focusSubject: 'Gavin Wood',\n avatar: '/api/assets/gavin_wood_1758526589973.jpeg',\n profileImage: '/api/assets/gavin_wood_news_1758526589972.png',\n bio: 'Co-founder of Ethereum and founder of Polkadot blockchain.',\n fullBio: [\n 'Co-founder of Ethereum and creator of the Solidity programming language.',\n 'Founder of Polkadot, pioneering blockchain interoperability solutions.',\n 'Visionary technologist advancing multi-chain blockchain ecosystem.'\n ]\n },\n {\n id: 'charles-hoskinson',\n name: 'Charles Hoskinson',\n description: 'Cardano founder and blockchain researcher',\n category: 'people',\n focusSubject: 'Charles Hoskinson',\n avatar: '/api/assets/charles_1758526589973.jpeg',\n profileImage: '/api/assets/charles_news_1758526589972.png',\n bio: 'Founder of Cardano and co-founder of Ethereum.',\n fullBio: [\n 'Founder of Cardano blockchain and co-founder of Ethereum.',\n 'Academic approach to blockchain development with peer-reviewed research.',\n 'Advocate for formal verification and scientific methodology in crypto.'\n ]\n },\n {\n id: 'sergey-nazarov',\n name: 'Sergey Nazarov',\n description: 'Chainlink co-founder and oracle technology pioneer',\n category: 'people',\n focusSubject: 'Sergey Nazarov',\n avatar: '/api/assets/sergey_1758526589973.jpeg',\n profileImage: '/api/assets/sergey_news_1758526589972.png',\n bio: 'Co-founder of Chainlink, the leading blockchain oracle network.',\n fullBio: [\n 'Co-founder of Chainlink, providing real-world data to smart contracts.',\n 'Pioneer in blockchain oracle technology and decentralized data feeds.',\n 'Enabling smart contracts to interact with external data and systems.'\n ]\n },\n {\n id: 'arthur-hayes',\n name: 'Arthur Hayes',\n description: 'Former BitMEX CEO and crypto derivatives pioneer',\n category: 'people',\n focusSubject: 'Arthur Hayes',\n avatar: '/api/assets/arthur_hayes_1758526589973.jpeg',\n profileImage: '/api/assets/arthur_hayes_news_1758526589972.png',\n bio: 'Former CEO of BitMEX and pioneer in cryptocurrency derivatives.',\n fullBio: [\n 'Former CEO of BitMEX, pioneering cryptocurrency derivatives trading.',\n 'Influential voice in crypto markets and monetary policy analysis.',\n 'Advocate for Bitcoin as alternative to traditional financial systems.'\n ]\n },\n {\n id: 'elizabeth-stark',\n name: 'Elizabeth Stark',\n description: 'Lightning Labs CEO and Bitcoin Lightning Network advocate',\n category: 'people',\n focusSubject: 'Elizabeth Stark',\n avatar: '/api/assets/elizabeth_stark_1758526589973.jpeg',\n profileImage: '/api/assets/elizabeth_stark_news_1758526589972.png',\n bio: 'CEO of Lightning Labs, developing Bitcoin Lightning Network scaling.',\n fullBio: [\n 'CEO of Lightning Labs, building Bitcoin Lightning Network infrastructure.',\n 'Advocate for Bitcoin scalability and instant payment solutions.',\n 'Pioneer in layer-2 blockchain scaling technology and Bitcoin innovation.'\n ]\n },\n {\n id: 'cathie-wood',\n name: 'Cathie Wood',\n description: 'ARK Invest CEO and innovation investor',\n category: 'people',\n focusSubject: 'Cathie Wood',\n avatar: '/api/assets/cathie_wood_1758526589973.jpeg',\n profileImage: '/api/assets/cathie_wood_news_1758526589972.png',\n bio: 'CEO of ARK Invest, prominent investor in disruptive technologies.',\n fullBio: [\n 'CEO of ARK Invest, focusing on disruptive innovation investments.',\n 'Strong advocate for Bitcoin and cryptocurrency adoption.',\n 'Influential voice connecting traditional investing with crypto markets.'\n ]\n },\n {\n id: 'jack-dorsey',\n name: 'Jack Dorsey',\n description: 'Former Twitter CEO and Bitcoin advocate',\n category: 'people',\n focusSubject: 'Jack Dorsey',\n avatar: '/api/assets/jack_dorsey_1758526589973.jpeg',\n profileImage: '/api/assets/jack_dorsey_news_1758526589972.png',\n bio: 'Former CEO of Twitter and Square, passionate Bitcoin advocate.',\n fullBio: [\n 'Former CEO of Twitter and Square, passionate about Bitcoin adoption.',\n 'Building decentralized social media and Bitcoin infrastructure.',\n 'Advocate for Bitcoin as tool for global financial inclusion.'\n ]\n },\n {\n id: 'dan-larimer',\n name: 'Dan Larimer',\n description: 'Blockchain developer and EOS creator',\n category: 'people',\n focusSubject: 'Dan Larimer',\n avatar: '/api/assets/dan_larimer_1758526589973.jpeg',\n profileImage: '/api/assets/dan_larimer_news_1758526589972.png',\n bio: 'Creator of EOS, Steemit, and BitShares blockchain platforms.',\n fullBio: [\n 'Creator of multiple blockchain platforms including EOS and BitShares.',\n 'Pioneer in delegated proof-of-stake consensus mechanisms.',\n 'Innovative developer focused on blockchain scalability and user experience.'\n ]\n },\n {\n id: 'cameron-winklevoss',\n name: 'Cameron Winklevoss',\n description: 'Gemini co-founder and crypto entrepreneur',\n category: 'people',\n focusSubject: 'Cameron Winklevoss',\n avatar: '/api/assets/cameron_1758526589973.jpeg',\n profileImage: '/api/assets/cameron_news_1758526589972.png',\n bio: 'Co-founder of Gemini cryptocurrency exchange.',\n fullBio: [\n 'Co-founder of Gemini cryptocurrency exchange with twin brother Tyler.',\n 'Early Bitcoin investor and advocate for cryptocurrency regulation.',\n 'Entrepreneur bridging traditional finance with digital assets.'\n ]\n },\n {\n id: 'tyler-winklevoss',\n name: 'Tyler Winklevoss',\n description: 'Gemini co-founder and digital asset advocate',\n category: 'people',\n focusSubject: 'Tyler Winklevoss',\n avatar: '/api/assets/tyler_1758526589973.jpeg',\n profileImage: '/api/assets/tyler_news_1758526589972.png',\n bio: 'Co-founder of Gemini cryptocurrency exchange.',\n fullBio: [\n 'Co-founder of Gemini cryptocurrency exchange with twin brother Cameron.',\n 'Pioneer in cryptocurrency compliance and regulatory engagement.',\n 'Advocate for institutional-grade cryptocurrency infrastructure.'\n ]\n },\n {\n id: 'roger-ver',\n name: 'Roger Ver',\n description: 'Bitcoin Cash advocate and early Bitcoin investor',\n category: 'people',\n focusSubject: 'Roger Ver',\n avatar: '/api/assets/roger_ver_1758526589973.jpeg',\n profileImage: '/api/assets/roger_ver_news_1758526589972.png',\n bio: 'Early Bitcoin investor and advocate, known as \"Bitcoin Jesus.\"',\n fullBio: [\n 'Early Bitcoin investor and evangelist, known as \"Bitcoin Jesus.\"',\n 'Prominent advocate for Bitcoin Cash and cryptocurrency adoption.',\n 'Entrepreneur focused on peer-to-peer electronic cash systems.'\n ]\n },\n {\n id: 'palmer-luckey',\n name: 'Palmer Luckey',\n description: 'Oculus VR founder and Anduril Industries CEO, pioneering VR/AR and defense tech',\n category: 'people',\n focusSubject: 'Palmer Luckey',\n avatar: '/api/assets/palmer_luckey_1758526589973.jpeg',\n profileImage: '/api/assets/palmer_luckey_profile_1758526589973.jpeg',\n bio: 'Founder of Oculus VR and current CEO of Anduril Industries, pioneering virtual reality and defense technology.',\n fullBio: [\n 'Founded Oculus VR at age 20, revolutionizing virtual reality technology before selling to Facebook for $2 billion.',\n 'Currently CEO of Anduril Industries, developing AI-powered defense systems and autonomous weapons platforms.',\n 'Visionary entrepreneur bridging gaming technology, military applications, and next-generation computing interfaces.'\n ]\n },\n {\n id: 'mike-novogratz',\n name: 'Mike Novogratz',\n description: 'CEO of Galaxy Digital and crypto investment pioneer',\n category: 'people',\n focusSubject: 'Mike Novogratz',\n avatar: '/api/assets/mike novogratz_1759136098707.jpg',\n profileImage: '/api/assets/mike novogratz_1759136098707.jpg',\n bio: 'CEO and founder of Galaxy Digital, a leading cryptocurrency investment firm.',\n fullBio: [\n 'CEO and founder of Galaxy Digital, one of the largest cryptocurrency investment firms.',\n 'Former Goldman Sachs partner and Fortress Investment Group principal with 20+ years Wall Street experience.',\n 'Early Bitcoin advocate and institutional crypto adoption pioneer, managing billions in digital assets.'\n ]\n },\n {\n id: 'michael-j-saylor',\n name: 'Michael J. Saylor',\n description: 'MicroStrategy CEO and Bitcoin maximalist',\n category: 'people',\n focusSubject: 'Michael J. Saylor',\n avatar: '/api/assets/michael j. saylor_1759136096272.jpg',\n profileImage: '/api/assets/michael j. saylor_1759136096272.jpg',\n bio: 'CEO of MicroStrategy and leading advocate for Bitcoin as a treasury reserve asset.',\n fullBio: [\n 'CEO of MicroStrategy, the first major corporation to adopt Bitcoin as primary treasury reserve asset.',\n 'Led MicroStrategy to purchase over $5 billion worth of Bitcoin, pioneering corporate crypto adoption.',\n 'Prominent Bitcoin maximalist and advocate for digital asset treasury strategies among corporations.'\n ]\n },\n // Companies Category (additional outlets)\n {\n id: 'coinbase',\n name: 'Coinbase',\n description: 'Leading cryptocurrency exchange and platform',\n category: 'companies',\n focusSubject: 'Coinbase',\n avatar: '/api/assets/coinbase_1758526589973.jpeg',\n profileImage: '/api/assets/coinbase_news_1758526589972.png',\n bio: 'Leading cryptocurrency exchange and platform in the United States.',\n fullBio: [\n 'Largest cryptocurrency exchange in the United States, publicly traded.',\n 'Provides easy-to-use platform for buying, selling, and storing cryptocurrencies.',\n 'Pioneer in regulatory compliance and institutional cryptocurrency services.'\n ]\n },\n {\n id: 'binance',\n name: 'Binance',\n description: 'Worlds largest cryptocurrency exchange by volume',\n category: 'companies',\n focusSubject: 'Binance',\n avatar: '/api/assets/binance_1758526589973.jpeg',\n profileImage: '/api/assets/binance_news_1758526589972.png',\n bio: 'The worlds largest cryptocurrency exchange by trading volume.',\n fullBio: [\n 'Worlds largest cryptocurrency exchange by trading volume and users.',\n 'Comprehensive ecosystem including spot trading, futures, staking, and DeFi.',\n 'Global platform serving millions of users in over 100 countries.'\n ]\n },\n {\n id: 'galaxy-digital',\n name: 'Galaxy Digital',\n description: 'Leading cryptocurrency investment and trading firm',\n category: 'companies',\n focusSubject: 'Galaxy Digital',\n avatar: '/api/assets/galaxy_1759136096271.jpeg',\n profileImage: '/api/assets/galaxy_1759136096271.jpeg',\n bio: 'Leading cryptocurrency investment firm and digital asset merchant bank.',\n fullBio: [\n 'Leading cryptocurrency investment firm and digital asset merchant bank founded by Mike Novogratz.',\n 'Provides institutional-grade cryptocurrency trading, investment management, and advisory services.',\n 'Publicly traded company (TSX: GLXY) serving institutions and high-net-worth investors in digital assets.'\n ]\n },\n {\n id: 'microstrategy',\n name: 'MicroStrategy',\n description: 'Business intelligence company with major Bitcoin holdings',\n category: 'companies',\n focusSubject: 'MicroStrategy',\n avatar: '/api/assets/microstrategy_1759136096272.webp',\n profileImage: '/api/assets/microstrategy_1759136096272.webp',\n bio: 'Business intelligence company with one of the largest corporate Bitcoin treasuries.',\n fullBio: [\n 'Business intelligence software company with massive Bitcoin treasury.',\n 'First major corporation to adopt Bitcoin as primary reserve asset.',\n 'Pioneer in corporate Bitcoin adoption and treasury diversification strategy.'\n ]\n },\n {\n id: 'tesla',\n name: 'Tesla',\n description: 'Electric vehicle company with cryptocurrency investments',\n category: 'companies',\n focusSubject: 'Tesla',\n avatar: '/api/assets/tesla_1758526589973.jpeg',\n profileImage: '/api/assets/tesla_news_1758526589972.png',\n bio: 'Electric vehicle manufacturer with significant cryptocurrency holdings.',\n fullBio: [\n 'Electric vehicle and clean energy company with Bitcoin investments.',\n 'Pioneered corporate cryptocurrency adoption and payment acceptance.',\n 'Leading voice in sustainable Bitcoin mining and renewable energy.'\n ]\n },\n {\n id: 'paypal',\n name: 'PayPal',\n description: 'Digital payments company offering cryptocurrency services',\n category: 'companies',\n focusSubject: 'PayPal',\n avatar: '/api/assets/paypal_1758526589973.jpeg',\n profileImage: '/api/assets/paypal_news_1758526589972.png',\n bio: 'Digital payments company providing cryptocurrency buying and selling services.',\n fullBio: [\n 'Global digital payments leader offering cryptocurrency services.',\n 'Enables millions of users to buy, sell, and hold cryptocurrencies.',\n 'Bridging traditional payments with digital asset adoption.'\n ]\n },\n {\n id: 'square',\n name: 'Square',\n description: 'Financial services company with Bitcoin integration',\n category: 'companies',\n focusSubject: 'Square',\n avatar: '/api/assets/square_1758526589973.jpeg',\n profileImage: '/api/assets/square_news_1758526589972.png',\n bio: 'Financial services and mobile payment company with Bitcoin integration.',\n fullBio: [\n 'Financial services company integrating Bitcoin into payment solutions.',\n 'Cash App provides easy Bitcoin buying and selling for consumers.',\n 'Advocate for Bitcoin adoption and Lightning Network development.'\n ]\n },\n {\n id: 'grayscale',\n name: 'Grayscale',\n description: 'Digital asset investment management company',\n category: 'companies',\n focusSubject: 'Grayscale',\n avatar: '/api/assets/grayscale_1758526589973.jpeg',\n profileImage: '/api/assets/grayscale_news_1758526589972.png',\n bio: 'Leading digital asset investment management company.',\n fullBio: [\n 'Leading digital asset investment manager with billions under management.',\n 'Provides institutional and accredited investor access to cryptocurrencies.',\n 'Pioneer in cryptocurrency investment products and regulatory compliance.'\n ]\n },\n {\n id: 'chainlink',\n name: 'Chainlink',\n description: 'Decentralized oracle network connecting blockchains to real world',\n category: 'companies',\n focusSubject: 'Chainlink',\n avatar: '/api/assets/chainlink_1758526589973.jpeg',\n profileImage: '/api/assets/chainlink_news_1758526589972.png',\n bio: 'Decentralized oracle network providing real-world data to smart contracts.',\n fullBio: [\n 'Leading decentralized oracle network connecting blockchains to real-world data.',\n 'Enables smart contracts to securely interact with external data feeds.',\n 'Critical infrastructure powering DeFi and blockchain applications.'\n ]\n },\n {\n id: 'ethereum-foundation',\n name: 'Ethereum Foundation',\n description: 'Non-profit supporting Ethereum blockchain development',\n category: 'companies',\n focusSubject: 'Ethereum Foundation',\n avatar: '/api/assets/ethereum_foundation_1758526589973.jpeg',\n profileImage: '/api/assets/ethereum_foundation_news_1758526589972.png',\n bio: 'Non-profit organization supporting Ethereum blockchain development.',\n fullBio: [\n 'Non-profit organization supporting Ethereum blockchain development and research.',\n 'Funds core protocol development and ecosystem growth initiatives.',\n 'Steward of the Ethereum networks evolution and decentralization.'\n ]\n },\n {\n id: 'consensys',\n name: 'ConsenSys',\n description: 'Ethereum software company and blockchain infrastructure',\n category: 'companies',\n focusSubject: 'ConsenSys',\n avatar: '/api/assets/consensys_1758526589973.jpeg',\n profileImage: '/api/assets/consensys_news_1758526589972.png',\n bio: 'Leading Ethereum software company building blockchain infrastructure.',\n fullBio: [\n 'Leading Ethereum software company building decentralized applications.',\n 'Creates tools and infrastructure for Web3 and DeFi applications.',\n 'MetaMask wallet provider serving millions of Ethereum users globally.'\n ]\n },\n {\n id: 'ripple',\n name: 'Ripple',\n description: 'Digital payment protocol for global financial institutions',\n category: 'companies',\n focusSubject: 'Ripple',\n avatar: '/api/assets/ripple_1758526589973.jpeg',\n profileImage: '/api/assets/ripple_news_1758526589972.png',\n bio: 'Digital payment protocol company serving global financial institutions.',\n fullBio: [\n 'Digital payment protocol company serving banks and financial institutions.',\n 'Enables fast, low-cost cross-border payments using XRP cryptocurrency.',\n 'Bridging traditional banking with modern blockchain payment solutions.'\n ]\n },\n {\n id: 'circle',\n name: 'Circle',\n description: 'Financial technology company behind USDC stablecoin',\n category: 'companies',\n focusSubject: 'Circle',\n avatar: '/api/assets/circle_1758526589973.jpeg',\n profileImage: '/api/assets/circle_news_1758526589972.png',\n bio: 'Financial technology company behind USDC stablecoin.',\n fullBio: [\n 'Financial technology company issuing USDC, second-largest stablecoin.',\n 'Provides institutional-grade digital asset infrastructure and services.',\n 'Pioneer in regulated stablecoin issuance and digital dollar adoption.'\n ]\n },\n {\n id: 'kraken',\n name: 'Kraken',\n description: 'Veteran cryptocurrency exchange and trading platform',\n category: 'companies',\n focusSubject: 'Kraken',\n avatar: '/api/assets/kraken_1758526589973.jpeg',\n profileImage: '/api/assets/kraken_news_1758526589972.png',\n bio: 'Veteran cryptocurrency exchange known for security and advanced trading.',\n fullBio: [\n 'Long-standing cryptocurrency exchange known for security and reliability.',\n 'Offers advanced trading features and institutional cryptocurrency services.',\n 'Pioneer in cryptocurrency market analysis and regulatory compliance.'\n ]\n },\n {\n id: 'ftx',\n name: 'FTX',\n description: 'Former major cryptocurrency exchange and derivatives platform',\n category: 'companies',\n focusSubject: 'FTX',\n avatar: '/api/assets/ftx_1758526589973.jpeg',\n profileImage: '/api/assets/ftx_news_1758526589972.png',\n bio: 'Former major cryptocurrency exchange that collapsed amid fraud allegations.',\n fullBio: [\n 'Former major cryptocurrency exchange that collapsed in November 2022.',\n 'Once a leading platform for crypto derivatives and institutional trading.',\n 'Bankruptcy and fraud case serving as cautionary tale for crypto industry.'\n ]\n },\n {\n id: 'alameda-research',\n name: 'Alameda Research',\n description: 'Former quantitative trading firm in cryptocurrency markets',\n category: 'companies',\n focusSubject: 'Alameda Research',\n avatar: '/api/assets/alameda_1758526589973.jpeg',\n profileImage: '/api/assets/alameda_news_1758526589972.png',\n bio: 'Former quantitative trading firm associated with FTX collapse.',\n fullBio: [\n 'Former quantitative cryptocurrency trading firm founded by Sam Bankman-Fried.',\n 'Involved in the FTX collapse and subsequent fraud investigations.',\n 'Case study in risk management and conflicts of interest in crypto trading.'\n ]\n },\n {\n id: 'celsius',\n name: 'Celsius',\n description: 'Former cryptocurrency lending platform that filed for bankruptcy',\n category: 'companies',\n focusSubject: 'Celsius',\n avatar: '/api/assets/celsius_1758526589973.jpeg',\n profileImage: '/api/assets/celsius_news_1758526589972.png',\n bio: 'Former cryptocurrency lending platform that filed for bankruptcy.',\n fullBio: [\n 'Former cryptocurrency lending platform offering high yields to depositors.',\n 'Filed for bankruptcy in 2022 amid liquidity crisis and regulatory issues.',\n 'Cautionary tale about risks in unregulated cryptocurrency lending.'\n ]\n },\n {\n id: 'three-arrows-capital',\n name: 'Three Arrows Capital',\n description: 'Former cryptocurrency hedge fund that collapsed',\n category: 'companies',\n focusSubject: 'Three Arrows Capital',\n avatar: '/api/assets/3ac_1758526589973.jpeg',\n profileImage: '/api/assets/3ac_news_1758526589972.png',\n bio: 'Former prominent cryptocurrency hedge fund that collapsed in 2022.',\n fullBio: [\n 'Former prominent cryptocurrency hedge fund managing billions in assets.',\n 'Collapsed in 2022 due to excessive leverage and poor risk management.',\n 'Bankruptcy had widespread impacts across cryptocurrency markets and DeFi.'\n ]\n },\n // Companies Category (4 outlets)\n {\n id: 'xtao',\n name: 'xTAO',\n description: 'Publicly traded infrastructure company for the Bittensor ecosystem',\n category: 'companies',\n focusSubject: 'xTAO',\n avatar: '/api/assets/xtao_logo_1758526589976.jpg',\n profileImage: '/api/assets/xTAO news_1758526589976.png',\n bio: 'A publicly traded company listed on the TSX Venture Exchange, focused on building infrastructure for the Bittensor ecosystem.',\n fullBio: [\n 'Publicly traded company on TSX Venture Exchange building infrastructure for Bittensor ecosystem.',\n 'High-performance validator holding significant TAO token treasury for staking and network security.',\n 'Provides regulated entry point for institutional investors seeking decentralized AI exposure.'\n ]\n },\n {\n id: 'yuma',\n name: 'YUMA',\n description: 'Leading accelerator and investment firm for the Bittensor ecosystem',\n category: 'companies',\n focusSubject: 'YUMA',\n avatar: '/api/assets/yuma_1758526589977.png',\n profileImage: '/api/assets/yuma news_1758526589976.png',\n bio: 'A leading accelerator and investment firm focused exclusively on the Bittensor ecosystem.',\n fullBio: [\n 'Leading accelerator and investment firm focused exclusively on the Bittensor ecosystem.',\n 'Provides capital, technical resources, and community connections for building new Subnets.',\n 'Known for strong due diligence and nurturing successful high-performing Subnet projects.'\n ]\n },\n {\n id: 'taox',\n name: 'TAOX',\n description: 'Public investment vehicle for Bittensor ecosystem exposure',\n category: 'companies',\n focusSubject: 'TAOX',\n avatar: '/api/assets/taox_1758526589975.jpeg',\n profileImage: '/api/assets/taox news_1758526589975.png',\n bio: 'Public investment vehicle focused on providing exposure to the Bittensor ecosystem.',\n fullBio: [\n 'Public investment vehicle focused on providing exposure to the Bittensor ecosystem.',\n 'Specializes in acquiring, holding, and staking TAO tokens for institutional investors.',\n 'Bridges conventional financial markets with decentralized AI sector opportunities.'\n ]\n },\n {\n id: 'oblong',\n name: 'Oblong',\n description: 'Spatial computing and collaborative interface technology company',\n category: 'companies',\n focusSubject: 'Oblong',\n avatar: '/api/assets/oblong_1758526589974.png',\n profileImage: '/api/assets/oblong_1758526589974.png',\n bio: 'An innovative technology company focused on spatial computing and collaborative interfaces.',\n fullBio: [\n 'Technology company pioneering spatial computing and gesture-based collaborative interfaces.',\n 'Develops enterprise visualization solutions and intuitive human-computer interaction technologies.',\n 'Focus on immersive workspace solutions and next-generation user interface design.'\n ]\n },\n // Football Clubs - Topics Category (4 outlets)\n {\n id: 'borussia-dortmund',\n name: 'Borussia Dortmund',\n description: 'German professional football club based in Dortmund',\n category: 'topics',\n focusSubject: 'Borussia Dortmund',\n avatar: '/api/assets/Ballspielverein Borussia 09 e.V. Dortmund (Borussia Dortmund) _1759157881265.png',\n profileImage: '/api/assets/Ballspielverein Borussia 09 e.V. Dortmund (Borussia Dortmund) _1759157881265.png',\n bio: 'German professional football club competing in the Bundesliga.',\n fullBio: [\n 'One of the most successful football clubs in Germany with eight Bundesliga titles.',\n 'Known for their passionate fanbase and the famous \"Yellow Wall\" at Signal Iduna Park.',\n 'Regular competitors in UEFA Champions League with strong youth development programs.'\n ]\n },\n {\n id: 'inter-milan',\n name: 'Inter Milan',\n description: 'Italian professional football club based in Milan',\n category: 'topics',\n focusSubject: 'Inter Milan',\n avatar: '/api/assets/inter milan_1759157883456.png',\n profileImage: '/api/assets/inter milan_1759157883456.png',\n bio: 'Italian professional football club competing in Serie A.',\n fullBio: [\n 'One of the most successful clubs in Italian football history with 19 Serie A titles.',\n 'The only Italian team to have won the European treble (Champions League, domestic league, and cup).',\n 'Known for their distinctive blue and black striped jerseys and passionate Milanese support.'\n ]\n },\n {\n id: 'manchester-city',\n name: 'Manchester City F.C.',\n description: 'English professional football club based in Manchester',\n category: 'topics',\n focusSubject: 'Manchester City',\n avatar: '/api/assets/Manchester City F.C. _1759157887061.png',\n profileImage: '/api/assets/Manchester City F.C. _1759157887061.png',\n bio: 'English professional football club competing in the Premier League.',\n fullBio: [\n 'One of the most successful English clubs in recent years with multiple Premier League titles.',\n 'Known for their attacking style of play under manager Pep Guardiola.',\n 'Regular competitors in UEFA Champions League with state-of-the-art training facilities.'\n ]\n },\n {\n id: 'liverpool-fc',\n name: 'Liverpool F.C.',\n description: 'English professional football club based in Liverpool',\n category: 'topics',\n focusSubject: 'Liverpool',\n avatar: '/api/assets/Liverpool F.C. _1759157885432.png',\n profileImage: '/api/assets/Liverpool F.C. _1759157885432.png',\n bio: 'English professional football club competing in the Premier League.',\n fullBio: [\n 'One of the most successful clubs in English and European football history.',\n 'Known for their passionate supporters and the famous \"You\\'ll Never Walk Alone\" anthem.',\n 'Six-time European Cup/Champions League winners with a rich footballing heritage.'\n ]\n },\n // Football Players - People Category (12 outlets)\n {\n id: 'giovanni-reyna',\n name: 'Giovanni Reyna',\n description: 'American professional footballer playing for Borussia Dortmund',\n category: 'people',\n focusSubject: 'Giovanni Reyna',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'American attacking midfielder and winger for Borussia Dortmund and the United States national team.',\n fullBio: [\n 'Talented American attacking midfielder known for his creativity and technical ability.',\n 'Son of former USA captain Claudio Reyna, continuing the family footballing legacy.',\n 'Rising star in the Bundesliga with excellent dribbling skills and vision.'\n ]\n },\n {\n id: 'felix-nmecha',\n name: 'Felix Nmecha',\n description: 'German professional footballer playing for Borussia Dortmund',\n category: 'people',\n focusSubject: 'Felix Nmecha',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'German central midfielder for Borussia Dortmund and the Germany national team.',\n fullBio: [\n 'Dynamic central midfielder known for his work rate and pressing ability.',\n 'Former Manchester City academy product who developed through German football.',\n 'Key player in Dortmund\\'s midfield with strong defensive contributions.'\n ]\n },\n {\n id: 'julian-brandt',\n name: 'Julian Brandt',\n description: 'German professional footballer playing for Borussia Dortmund',\n category: 'people',\n focusSubject: 'Julian Brandt',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'German attacking midfielder and winger for Borussia Dortmund and the Germany national team.',\n fullBio: [\n 'Versatile attacking midfielder capable of playing multiple positions across the front line.',\n 'Product of Bayer Leverkusen academy before joining Borussia Dortmund.',\n 'Regular Germany international with excellent passing range and football intelligence.'\n ]\n },\n {\n id: 'lautaro-martinez',\n name: 'Lautaro Martínez',\n description: 'Argentine professional footballer playing for Inter Milan',\n category: 'people',\n focusSubject: 'Lautaro Martínez',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Argentine striker for Inter Milan and the Argentina national team.',\n fullBio: [\n 'Clinical striker known for his positioning, finishing ability, and work rate.',\n 'Key player in Argentina\\'s World Cup victory and Copa América successes.',\n 'Partnership with fellow striker forms one of Europe\\'s most feared attacking duos.'\n ]\n },\n {\n id: 'marcus-thuram',\n name: 'Marcus Thuram',\n description: 'French professional footballer playing for Inter Milan',\n category: 'people',\n focusSubject: 'Marcus Thuram',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'French striker and winger for Inter Milan and the France national team.',\n fullBio: [\n 'Versatile forward capable of playing across the front line with pace and power.',\n 'Son of French football legend Lilian Thuram, carrying on the family tradition.',\n 'Proven goalscorer in both Bundesliga and Serie A with strong physical presence.'\n ]\n },\n {\n id: 'nicolo-barella',\n name: 'Nicolò Barella',\n description: 'Italian professional footballer playing for Inter Milan',\n category: 'people',\n focusSubject: 'Nicolò Barella',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Italian central midfielder for Inter Milan and the Italy national team.',\n fullBio: [\n 'Dynamic central midfielder known for his energy, passing ability, and goal threat.',\n 'Key player in Italy\\'s European Championship victory and Inter Milan\\'s success.',\n 'Complete midfielder with excellent technical skills and leadership qualities.'\n ]\n },\n {\n id: 'erling-haaland',\n name: 'Erling Haaland',\n description: 'Norwegian professional footballer playing for Manchester City',\n category: 'people',\n focusSubject: 'Erling Haaland',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Norwegian striker for Manchester City and the Norway national team.',\n fullBio: [\n 'Prolific goalscorer known for his speed, strength, and clinical finishing ability.',\n 'Record-breaking striker who has dominated every league he has played in.',\n 'One of the most promising young talents in world football with incredible goal-scoring records.'\n ]\n },\n {\n id: 'phil-foden',\n name: 'Phil Foden',\n description: 'English professional footballer playing for Manchester City',\n category: 'people',\n focusSubject: 'Phil Foden',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'English attacking midfielder and winger for Manchester City and the England national team.',\n fullBio: [\n 'Manchester City academy graduate known for his dribbling, creativity, and goal threat.',\n 'Versatile player capable of playing multiple positions in attack and midfield.',\n 'Regular England international and key player in City\\'s recent successes.'\n ]\n },\n {\n id: 'rodri-hernandez',\n name: 'Rodri Hernández',\n description: 'Spanish professional footballer playing for Manchester City',\n category: 'people',\n focusSubject: 'Rodri Hernández',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Spanish defensive midfielder for Manchester City and the Spain national team.',\n fullBio: [\n 'Exceptional defensive midfielder known for his passing range and tactical intelligence.',\n 'Key player in Manchester City\\'s midfield providing stability and distribution.',\n 'Spain international and winner of major tournaments at both club and international level.'\n ]\n },\n {\n id: 'mohamed-salah',\n name: 'Mohamed Salah',\n description: 'Egyptian professional footballer playing for Liverpool',\n category: 'people',\n focusSubject: 'Mohamed Salah',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Egyptian winger and forward for Liverpool and the Egypt national team.',\n fullBio: [\n 'Prolific winger and forward known for his pace, dribbling, and goal-scoring ability.',\n 'Liverpool legend and one of the Premier League\\'s all-time leading scorers.',\n 'Egyptian icon and captain of the national team with numerous individual awards.'\n ]\n },\n {\n id: 'virgil-van-dijk',\n name: 'Virgil van Dijk',\n description: 'Dutch professional footballer playing for Liverpool',\n category: 'people',\n focusSubject: 'Virgil van Dijk',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Dutch centre-back for Liverpool and captain of the Netherlands national team.',\n fullBio: [\n 'World-class centre-back known for his aerial ability, leadership, and defensive skills.',\n 'Captain of Liverpool and the Netherlands national team with numerous achievements.',\n 'Considered one of the best defenders in modern football with excellent ball-playing ability.'\n ]\n },\n {\n id: 'alexis-mac-allister',\n name: 'Alexis Mac Allister',\n description: 'Argentine professional footballer playing for Liverpool',\n category: 'people',\n focusSubject: 'Alexis Mac Allister',\n avatar: '/api/assets/default-player.png',\n profileImage: '/api/assets/default-player.png',\n bio: 'Argentine central midfielder for Liverpool and the Argentina national team.',\n fullBio: [\n 'Versatile midfielder known for his passing ability, work rate, and tactical intelligence.',\n 'World Cup winner with Argentina and key player in their recent international successes.',\n 'Adaptable player capable of playing multiple midfield roles with excellent technical skills.'\n ]\n }\n ];\n\n for (const outlet of defaultOutlets) {\n const mediaOutlet: MediaOutlet = {\n ...outlet,\n avatar: outlet.avatar || null,\n profileImage: outlet.profileImage || null,\n fullBio: (outlet as any).fullBio || null,\n wikiProfile: null\n };\n this.outlets.set(outlet.id, mediaOutlet);\n }\n\n console.log(`[MemStorage] Initialized with ${defaultOutlets.length} outlets`);\n }\n\n // User methods\n async getUser(id: string): Promise {\n return this.users.get(id);\n }\n\n async getUserByUsername(username: string): Promise {\n return Array.from(this.users.values()).find(user => user.username === username);\n }\n\n async createUser(user: InsertUser): Promise {\n const newUser: User = {\n id: randomUUID(),\n ...user,\n avatar: user.avatar || null,\n preferredLanguage: user.preferredLanguage || null\n };\n this.users.set(newUser.id, newUser);\n return newUser;\n }\n\n // Media outlet methods\n async getAllOutlets(): Promise {\n const result = await db.select().from(mediaOutlets).orderBy(asc(mediaOutlets.name));\n return result;\n }\n\n async getOutletsByCategory(category: string): Promise {\n const result = await db.select().from(mediaOutlets).where(eq(mediaOutlets.category, category)).orderBy(asc(mediaOutlets.name));\n return result;\n }\n\n async getOutletById(id: string): Promise {\n const result = await db.select().from(mediaOutlets).where(eq(mediaOutlets.id, id));\n return result[0] || undefined;\n }\n\n async createOutlet(outlet: InsertMediaOutlet): Promise {\n const newOutlet: MediaOutlet = {\n id: randomUUID(),\n ...outlet,\n avatar: outlet.avatar || null,\n profileImage: outlet.profileImage || null,\n fullBio: outlet.fullBio || null,\n wikiProfile: outlet.wikiProfile || null\n };\n \n try {\n await db.insert(mediaOutlets).values(newOutlet);\n return newOutlet;\n } catch (error) {\n console.error('Error inserting outlet into database:', error);\n throw error;\n }\n }\n\n async deleteOutlet(id: string): Promise {\n try {\n const result = await db.delete(mediaOutlets).where(eq(mediaOutlets.id, id));\n return result.rowCount !== undefined && result.rowCount > 0;\n } catch (error) {\n console.error('Error deleting outlet from database:', error);\n return false;\n }\n }\n\n async updateOutlet(id: string, updates: Partial): Promise {\n try {\n // First check if outlet exists\n const existing = await db.select().from(mediaOutlets).where(eq(mediaOutlets.id, id));\n if (existing.length === 0) return undefined;\n \n // Update the outlet\n const result = await db.update(mediaOutlets)\n .set(updates)\n .where(eq(mediaOutlets.id, id))\n .returning();\n \n return result[0] || undefined;\n } catch (error) {\n console.error('Error updating outlet in database:', error);\n return undefined;\n }\n }\n\n async mergeOutlets(fromOutletId: string, toOutletId: string): Promise<{ success: boolean; movedArticles: number }> {\n const fromOutlet = this.outlets.get(fromOutletId);\n const toOutlet = this.outlets.get(toOutletId);\n \n if (!fromOutlet || !toOutlet) {\n return { success: false, movedArticles: 0 };\n }\n\n // Move all articles from source outlet to target outlet\n let movedArticles = 0;\n for (const [articleId, article] of Array.from(this.articles.entries())) {\n if (article.outletId === fromOutletId) {\n this.articles.set(articleId, { ...article, outletId: toOutletId });\n movedArticles++;\n }\n }\n\n // Delete the source outlet\n this.outlets.delete(fromOutletId);\n\n return { success: true, movedArticles };\n }\n\n // Article methods\n async getAllArticles(): Promise {\n const result = await db.select().from(articles).orderBy(desc(articles.publishedAt));\n return result;\n }\n\n async getArticlesByOutlet(outletId: string): Promise {\n const result = await db.select().from(articles).where(eq(articles.outletId, outletId)).orderBy(desc(articles.publishedAt));\n return result;\n }\n\n async getArticleCountsByOutlets(): Promise> {\n const results = await db.select({\n outletId: articles.outletId,\n count: sql`count(*)`.as('count')\n })\n .from(articles)\n .groupBy(articles.outletId);\n \n const counts: Record = {};\n for (const result of results) {\n counts[result.outletId] = Number(result.count);\n }\n return counts;\n }\n\n async getArticleById(id: string): Promise
{\n const result = await db.select().from(articles).where(eq(articles.id, id));\n return result[0] || undefined;\n }\n\n async getFeaturedArticles(limit: number = 10): Promise {\n const result = await db.select().from(articles).orderBy(desc(articles.publishedAt)).limit(limit);\n return result;\n }\n\n async searchArticles(query: string): Promise {\n const searchTerm = `%${query.toLowerCase()}%`;\n const result = await db.select().from(articles)\n .where(\n or(\n like(sql`lower(${articles.title})`, searchTerm),\n like(sql`lower(${articles.summary})`, searchTerm),\n like(sql`lower(${articles.body})`, searchTerm)\n )\n )\n .orderBy(desc(articles.publishedAt));\n return result;\n }\n\n async createArticle(article: InsertArticle): Promise
{\n const newArticle: Article = {\n id: randomUUID(),\n viewCount: 0,\n sourceUrl: null,\n author: null,\n originalImageUrl: null,\n scrapedAt: null,\n isScraped: 0,\n ...article,\n tags: article.tags || null\n };\n \n try {\n await db.insert(articles).values(newArticle);\n return newArticle;\n } catch (error) {\n console.error('Error inserting article into database:', error);\n throw error;\n }\n }\n\n async deleteArticle(id: string): Promise {\n try {\n const result = await db.delete(articles).where(eq(articles.id, id));\n return true;\n } catch (error) {\n console.error('Error deleting article from database:', error);\n return false;\n }\n }\n\n async createScrapedArticle(article: Omit & { \n sourceUrl: string; \n author?: string; \n originalImageUrl?: string; \n isScraped?: number;\n }): Promise
{\n const newArticle: Article = {\n id: randomUUID(),\n viewCount: 0,\n scrapedAt: new Date(),\n isScraped: 1,\n ...article,\n tags: article.tags || null,\n author: article.author || null,\n originalImageUrl: article.originalImageUrl || null\n };\n this.articles.set(newArticle.id, newArticle);\n return newArticle;\n }\n\n async getScrapedArticles(limit: number = 50): Promise {\n return Array.from(this.articles.values())\n .filter(article => article.isScraped === 1)\n .sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime())\n .slice(0, limit);\n }\n\n async updateArticleWithScrapedData(id: string, data: {\n sourceUrl?: string;\n author?: string;\n originalImageUrl?: string;\n }): Promise
{\n const article = this.articles.get(id);\n if (!article) return undefined;\n \n const updatedArticle = { ...article, ...data };\n this.articles.set(id, updatedArticle);\n return updatedArticle;\n }\n\n async updateArticleThumbnail(id: string, thumbnail: string): Promise
{\n try {\n const result = await db\n .update(articles)\n .set({ thumbnail })\n .where(eq(articles.id, id))\n .returning();\n \n return result[0] || undefined;\n } catch (error) {\n console.error('Error updating article thumbnail in database:', error);\n return undefined;\n }\n }\n\n async listFeed(params: { cursor?: string; limit?: number; filter?: 'all' | 'people' | 'topics' | 'companies' }): Promise<{ items: (Article & { outletName: string; outletAvatar: string; category: string })[]; nextCursor?: string }> {\n const limit = params.limit || 20;\n let articles = Array.from(this.articles.values());\n \n // Apply filter if specified\n if (params.filter && params.filter !== 'all') {\n articles = articles.filter(article => {\n const outlet = this.outlets.get(article.outletId);\n return outlet?.category === params.filter;\n });\n }\n \n // Sort by publishedAt descending\n articles.sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime());\n \n // Apply cursor pagination if provided\n if (params.cursor) {\n const cursorIndex = articles.findIndex(article => article.id === params.cursor);\n if (cursorIndex !== -1) {\n articles = articles.slice(cursorIndex + 1);\n }\n }\n \n // Take limit + 1 to check if there's a next page\n const paginatedArticles = articles.slice(0, limit + 1);\n const hasNext = paginatedArticles.length > limit;\n const items = paginatedArticles.slice(0, limit);\n \n // Enrich with outlet data\n const enrichedItems = items.map(article => {\n const outlet = this.outlets.get(article.outletId);\n return {\n ...article,\n outletName: outlet?.name || 'Unknown Outlet',\n outletAvatar: outlet?.avatar || '',\n category: outlet?.category || 'unknown'\n };\n });\n \n const nextCursor = hasNext ? items[items.length - 1]?.id : undefined;\n return { items: enrichedItems, nextCursor };\n }\n\n async incrementView(id: string): Promise {\n const article = this.articles.get(id);\n if (article) {\n const currentViewCount = article.viewCount || 0;\n const updatedArticle = {\n ...article,\n viewCount: currentViewCount + 1\n };\n this.articles.set(id, updatedArticle);\n }\n }\n\n async removeDuplicateArticles(): Promise<{ removedCount: number; details: { outletId: string; duplicatesRemoved: number }[] }> {\n const outletGroups = new Map>();\n \n // Group articles by outlet and title\n for (const article of Array.from(this.articles.values())) {\n if (!outletGroups.has(article.outletId)) {\n outletGroups.set(article.outletId, new Map());\n }\n const titleGroups = outletGroups.get(article.outletId)!;\n if (!titleGroups.has(article.title)) {\n titleGroups.set(article.title, []);\n }\n titleGroups.get(article.title)!.push(article);\n }\n \n let totalRemoved = 0;\n const outletDetails = new Map();\n \n // Process each outlet\n for (const [outletId, titleGroups] of Array.from(outletGroups.entries())) {\n let outletRemoved = 0;\n \n for (const [title, articles] of Array.from(titleGroups.entries())) {\n if (articles.length > 1) {\n // Sort by publishedAt desc to keep the most recent\n articles.sort((a: Article, b: Article) => b.publishedAt.getTime() - a.publishedAt.getTime());\n \n // Keep the first (most recent) and remove the rest\n const [keep, ...toRemove] = articles;\n \n for (const article of toRemove) {\n this.articles.delete(article.id);\n totalRemoved++;\n outletRemoved++;\n }\n }\n }\n \n if (outletRemoved > 0) {\n outletDetails.set(outletId, outletRemoved);\n }\n }\n \n const details = Array.from(outletDetails.entries()).map(([outletId, duplicatesRemoved]) => ({\n outletId,\n duplicatesRemoved\n }));\n \n return {\n removedCount: totalRemoved,\n details\n };\n }\n\n // Comment system methods\n async getCommentsByArticle(articleId: string, params: { limit?: number; offset?: number }): Promise<{ comments: Comment[]; total: number }> {\n const limit = params.limit || 20;\n const offset = params.offset || 0;\n \n const allComments = Array.from(this.comments.values())\n .filter(comment => comment.articleId === articleId && !comment.parentId)\n .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n \n const total = allComments.length;\n const comments = allComments.slice(offset, offset + limit);\n \n return { comments, total };\n }\n\n async getCommentReplies(parentId: string, params: { limit?: number; offset?: number }): Promise<{ comments: Comment[]; total: number }> {\n const limit = params.limit || 20;\n const offset = params.offset || 0;\n \n const allReplies = Array.from(this.comments.values())\n .filter(comment => comment.parentId === parentId)\n .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n \n const total = allReplies.length;\n const comments = allReplies.slice(offset, offset + limit);\n \n return { comments, total };\n }\n\n async getCommentById(id: string): Promise {\n return this.comments.get(id);\n }\n\n async createComment(comment: InsertComment): Promise {\n const newComment: Comment = {\n id: randomUUID(),\n likesCount: 0,\n dislikesCount: 0,\n repliesCount: 0,\n createdAt: new Date(),\n updatedAt: new Date(),\n ...comment,\n avatar: comment.avatar || null,\n parentId: comment.parentId || null\n };\n this.comments.set(newComment.id, newComment);\n return newComment;\n }\n\n async updateComment(id: string, content: string): Promise {\n const comment = this.comments.get(id);\n if (!comment) return undefined;\n \n const updatedComment = { \n ...comment, \n content, \n updatedAt: new Date() \n };\n this.comments.set(id, updatedComment);\n return updatedComment;\n }\n\n async deleteComment(id: string): Promise {\n return this.comments.delete(id);\n }\n\n async toggleCommentReaction(commentId: string, userIdentifier: string, reactionType: 'like' | 'dislike'): Promise<{ action: 'added' | 'removed' | 'changed'; reaction: CommentReaction | null }> {\n const reactionKey = `${commentId}:${userIdentifier}`;\n const existingReaction = this.commentReactions.get(reactionKey);\n \n if (existingReaction) {\n if (existingReaction.reactionType === reactionType) {\n // Remove the reaction\n this.commentReactions.delete(reactionKey);\n return { action: 'removed', reaction: null };\n } else {\n // Change the reaction\n const updatedReaction = { ...existingReaction, reactionType };\n this.commentReactions.set(reactionKey, updatedReaction);\n return { action: 'changed', reaction: updatedReaction };\n }\n } else {\n // Add new reaction\n const newReaction: CommentReaction = {\n id: randomUUID(),\n commentId,\n reactionType,\n userIdentifier,\n createdAt: new Date()\n };\n this.commentReactions.set(reactionKey, newReaction);\n return { action: 'added', reaction: newReaction };\n }\n }\n\n async getUserCommentReaction(commentId: string, userIdentifier: string): Promise {\n const reactionKey = `${commentId}:${userIdentifier}`;\n return this.commentReactions.get(reactionKey);\n }\n\n async toggleBookmark(articleId: string, userIdentifier: string): Promise<{ action: 'added' | 'removed'; bookmark: Bookmark | null }> {\n const bookmarkKey = `${articleId}:${userIdentifier}`;\n const existingBookmark = this.bookmarks.get(bookmarkKey);\n \n if (existingBookmark) {\n this.bookmarks.delete(bookmarkKey);\n try {\n await db.delete(bookmarks)\n .where(\n and(\n eq(bookmarks.articleId, articleId),\n eq(bookmarks.userIdentifier, userIdentifier)\n )\n );\n } catch (error) {\n console.error('[DbStorage] Error removing bookmark:', error);\n }\n return { action: 'removed', bookmark: null };\n } else {\n const newBookmark: Bookmark = {\n id: randomUUID(),\n articleId,\n userIdentifier,\n createdAt: new Date()\n };\n this.bookmarks.set(bookmarkKey, newBookmark);\n try {\n await db.insert(bookmarks).values(newBookmark);\n } catch (error) {\n console.error('[DbStorage] Error adding bookmark:', error);\n }\n return { action: 'added', bookmark: newBookmark };\n }\n }\n\n async isBookmarked(articleId: string, userIdentifier: string): Promise {\n const bookmarkKey = `${articleId}:${userIdentifier}`;\n return this.bookmarks.has(bookmarkKey);\n }\n\n async getUserBookmarks(userIdentifier: string): Promise {\n return Array.from(this.bookmarks.values())\n .filter(bookmark => bookmark.userIdentifier === userIdentifier);\n }\n\n async getArticleCommentCount(articleId: string): Promise {\n try {\n const result = await db\n .select({ count: count() })\n .from(comments)\n .where(eq(comments.articleId, articleId));\n return result[0]?.count || 0;\n } catch (error) {\n console.error('[DbStorage] Error getting comment count:', error);\n return Array.from(this.comments.values())\n .filter(comment => comment.articleId === articleId).length;\n }\n }\n\n // Prediction Market methods\n async getPredictionMarketsByArticle(articleId: string, params: { limit?: number; offset?: number }): Promise {\n const limit = params.limit || 3;\n const offset = params.offset || 0;\n\n // Generate diverse prediction markets (binary and multiple choice)\n const mockMarkets: PredictionMarket[] = [\n // Binary markets (Yes/No)\n {\n id: `pm-${articleId}-1`,\n articleId,\n question: \"Will this prediction come true by end of year?\",\n description: \"Market resolves YES if the main prediction in this article occurs by December 31st\",\n marketType: \"binary\",\n yesPrice: 65,\n noPrice: 35,\n options: null,\n totalVolume: 421000,\n endDate: new Date('2025-12-31'),\n category: \"Politics\",\n isLive: 1,\n isResolved: 0,\n createdAt: new Date(),\n },\n // Multiple choice market - Election\n {\n id: `pm-${articleId}-2`,\n articleId,\n question: \"Who will win the mayoral election?\",\n description: \"Market on the winner of upcoming mayoral election\",\n marketType: \"multiple_choice\",\n yesPrice: null,\n noPrice: null,\n options: JSON.stringify([\n { name: \"John Smith\", price: 86 },\n { name: \"Sarah Johnson\", price: 14 },\n ]),\n totalVolume: 108000,\n endDate: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000),\n category: \"Politics\",\n isLive: 0,\n isResolved: 0,\n createdAt: new Date(),\n },\n // Multiple choice market - Sports match\n {\n id: `pm-${articleId}-3`,\n articleId,\n question: \"Match Winner\",\n description: \"Which team will win the upcoming match\",\n marketType: \"multiple_choice\",\n yesPrice: null,\n noPrice: null,\n options: JSON.stringify([\n { name: \"Team A\", price: 60 },\n { name: \"Draw\", price: 22 },\n { name: \"Team B\", price: 18 },\n ]),\n totalVolume: 421000,\n endDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),\n category: \"Sports\",\n isLive: 1,\n isResolved: 0,\n createdAt: new Date(),\n },\n // Binary market\n {\n id: `pm-${articleId}-4`,\n articleId,\n question: \"Will stock price increase by 10% in next quarter?\",\n description: \"Resolves YES if the mentioned company's stock rises 10%+ within 90 days\",\n marketType: \"binary\",\n yesPrice: 55,\n noPrice: 45,\n options: null,\n totalVolume: 221000,\n endDate: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000),\n category: \"Business\",\n isLive: 0,\n isResolved: 0,\n createdAt: new Date(),\n },\n // Multiple choice market - Company acquisition\n {\n id: `pm-${articleId}-5`,\n articleId,\n question: \"Which company will acquire XYZ Corp?\",\n description: \"Market on potential acquirer of XYZ Corporation\",\n marketType: \"multiple_choice\",\n yesPrice: null,\n noPrice: null,\n options: JSON.stringify([\n { name: \"Microsoft\", price: 45 },\n { name: \"Google\", price: 32 },\n { name: \"Amazon\", price: 23 },\n ]),\n totalVolume: 457000,\n endDate: new Date(Date.now() + 180 * 24 * 60 * 60 * 1000),\n category: \"Business\",\n isLive: 0,\n isResolved: 0,\n createdAt: new Date(),\n },\n ];\n\n return mockMarkets.slice(offset, offset + limit);\n }\n\n async getPredictionMarketById(id: string): Promise {\n // Mock implementation - would query database in production\n return undefined;\n }\n\n async createPredictionMarket(market: InsertPredictionMarket): Promise {\n const newMarket: PredictionMarket = {\n id: randomUUID(),\n ...market,\n options: market.options ?? null,\n description: market.description ?? null,\n category: market.category ?? null,\n yesPrice: market.yesPrice ?? null,\n noPrice: market.noPrice ?? null,\n createdAt: new Date(),\n };\n return newMarket;\n }\n}\n\n// Create and export storage instance\nexport const storage = new DbStorage();","size_bytes":94724},"server/vite.ts":{"content":"import express, { type Express } from \"express\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { createServer as createViteServer, createLogger } from \"vite\";\nimport { type Server } from \"http\";\nimport viteConfig from \"../vite.config\";\nimport { nanoid } from \"nanoid\";\n\nconst viteLogger = createLogger();\n\nexport function log(message: string, source = \"express\") {\n const formattedTime = new Date().toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: true,\n });\n\n console.log(`${formattedTime} [${source}] ${message}`);\n}\n\nexport async function setupVite(app: Express, server: Server) {\n const serverOptions = {\n middlewareMode: true,\n hmr: { server },\n allowedHosts: true as const,\n };\n\n const vite = await createViteServer({\n ...viteConfig,\n configFile: false,\n customLogger: {\n ...viteLogger,\n error: (msg, options) => {\n viteLogger.error(msg, options);\n process.exit(1);\n },\n },\n server: serverOptions,\n appType: \"custom\",\n });\n\n app.use(vite.middlewares);\n app.use(\"*\", async (req, res, next) => {\n const url = req.originalUrl;\n\n try {\n const clientTemplate = path.resolve(\n import.meta.dirname,\n \"..\",\n \"client\",\n \"index.html\",\n );\n\n // always reload the index.html file from disk incase it changes\n let template = await fs.promises.readFile(clientTemplate, \"utf-8\");\n template = template.replace(\n `src=\"/src/main.tsx\"`,\n `src=\"/src/main.tsx?v=${nanoid()}\"`,\n );\n const page = await vite.transformIndexHtml(url, template);\n res.status(200).set({ \"Content-Type\": \"text/html\" }).end(page);\n } catch (e) {\n vite.ssrFixStacktrace(e as Error);\n next(e);\n }\n });\n}\n\nexport function serveStatic(app: Express) {\n const distPath = path.resolve(import.meta.dirname, \"public\");\n\n if (!fs.existsSync(distPath)) {\n throw new Error(\n `Could not find the build directory: ${distPath}, make sure to build the client first`,\n );\n }\n\n app.use(express.static(distPath));\n\n // fall through to index.html if the file doesn't exist\n app.use(\"*\", (_req, res) => {\n res.sendFile(path.resolve(distPath, \"index.html\"));\n });\n}\n","size_bytes":2263},"shared/schema.ts":{"content":"import { sql } from \"drizzle-orm\";\nimport { pgTable, text, varchar, timestamp, integer, pgEnum, foreignKey, uniqueIndex, index } from \"drizzle-orm/pg-core\";\nimport { createInsertSchema } from \"drizzle-zod\";\nimport { z } from \"zod\";\n\n// Enum for reaction types\nexport const reactionTypeEnum = pgEnum('reaction_type', ['like', 'dislike']);\n\n// User schema\nexport const users = pgTable(\"users\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n username: text(\"username\").notNull().unique(),\n password: text(\"password\").notNull(),\n preferredLanguage: text(\"preferred_language\").default(\"en\"),\n avatar: text(\"avatar\"),\n});\n\n// Media outlet schema\nexport const mediaOutlets = pgTable(\"media_outlets\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n name: text(\"name\").notNull(),\n description: text(\"description\").notNull(),\n category: text(\"category\").notNull(), // \"people\", \"topics\", \"companies\"\n focusSubject: text(\"focus_subject\").notNull(), // \"jacob\", \"ala\", \"ai\", \"crypto\", etc.\n avatar: text(\"avatar\"),\n profileImage: text(\"profile_image\"),\n bio: text(\"bio\").notNull(),\n fullBio: text(\"full_bio\").array(),\n wikiProfile: text(\"wiki_profile\"), // Detailed Wikipedia-style profile in HTML/Markdown format\n});\n\n// Article schema - extended for web scraping\nexport const articles = pgTable(\"articles\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n outletId: varchar(\"outlet_id\").notNull().references(() => mediaOutlets.id),\n title: text(\"title\").notNull(),\n summary: text(\"summary\").notNull(),\n body: text(\"body\").notNull(),\n thumbnail: text(\"thumbnail\").notNull(),\n publishedAt: timestamp(\"published_at\").notNull(),\n tags: text(\"tags\").array(),\n viewCount: integer(\"view_count\").notNull().default(0),\n // Scraped article fields\n sourceUrl: text(\"source_url\"), // Original URL that was scraped\n author: text(\"author\"), // Article author from scraped content\n originalImageUrl: text(\"original_image_url\"), // Original image URL before processing\n scrapedAt: timestamp(\"scraped_at\").default(sql`NOW()`), // When this article was scraped\n isScraped: integer(\"is_scraped\").notNull().default(0), // 1 if scraped, 0 if manually created\n});\n\n// Comments schema for YouTube-style commenting system\nexport const comments = pgTable(\"comments\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n articleId: varchar(\"article_id\").notNull().references(() => articles.id),\n content: text(\"content\").notNull(),\n nickname: text(\"nickname\").notNull(),\n avatar: text(\"avatar\"), // Optional avatar URL or emoji\n parentId: varchar(\"parent_id\"), // Parent comment ID (nullable for top-level comments)\n likesCount: integer(\"likes_count\").notNull().default(0),\n dislikesCount: integer(\"dislikes_count\").notNull().default(0),\n repliesCount: integer(\"replies_count\").notNull().default(0),\n createdAt: timestamp(\"created_at\").notNull().default(sql`NOW()`),\n updatedAt: timestamp(\"updated_at\").notNull().default(sql`NOW()`),\n}, (table) => ({\n // Performance indexes\n articleParentCreatedIdx: index(\"comments_article_parent_created_idx\").on(\n table.articleId, \n table.parentId, \n table.createdAt\n ),\n}));\n\n// Comment reactions (likes/dislikes) with deduplication constraint \nexport const commentReactions = pgTable(\"comment_reactions\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n commentId: varchar(\"comment_id\").notNull().references(() => comments.id, { onDelete: 'cascade' }),\n reactionType: text(\"reaction_type\").notNull(), // Keep as text to avoid migration issues\n userIdentifier: text(\"user_identifier\").notNull(), // Session ID, IP hash, or similar\n createdAt: timestamp(\"created_at\").notNull().default(sql`NOW()`),\n}, (table) => ({\n // Unique constraint to prevent duplicate reactions from same user\n uniqueUserReaction: uniqueIndex(\"unique_user_reaction_per_comment_idx\").on(\n table.commentId, \n table.userIdentifier\n ),\n}));\n\n// Bookmarks schema for saving articles\nexport const bookmarks = pgTable(\"bookmarks\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n articleId: varchar(\"article_id\").notNull().references(() => articles.id, { onDelete: 'cascade' }),\n userIdentifier: text(\"user_identifier\").notNull(), // Session ID, IP hash, or similar\n createdAt: timestamp(\"created_at\").notNull().default(sql`NOW()`),\n}, (table) => ({\n // Unique constraint to prevent duplicate bookmarks from same user\n uniqueUserBookmark: uniqueIndex(\"unique_user_bookmark_per_article_idx\").on(\n table.articleId,\n table.userIdentifier\n ),\n}));\n\n// Prediction Markets schema for article-related betting events\nexport const predictionMarkets = pgTable(\"prediction_markets\", {\n id: varchar(\"id\").primaryKey().default(sql`gen_random_uuid()`),\n articleId: varchar(\"article_id\").notNull().references(() => articles.id),\n question: text(\"question\").notNull(),\n description: text(\"description\"),\n marketType: text(\"market_type\").notNull().default(\"binary\"), // \"binary\" (yes/no) or \"multiple_choice\"\n // For binary markets\n yesPrice: integer(\"yes_price\"), // Price in cents (0-100)\n noPrice: integer(\"no_price\"), // Price in cents (0-100)\n // For multiple choice markets - JSON array of options\n // [{name: \"Option A\", price: 60, image: \"/url\"}, ...]\n options: text(\"options\"), // JSON string\n totalVolume: integer(\"total_volume\").notNull().default(0), // Total trading volume in dollars\n endDate: timestamp(\"end_date\").notNull(),\n category: text(\"category\"),\n isLive: integer(\"is_live\").notNull().default(0),\n isResolved: integer(\"is_resolved\").notNull().default(0),\n createdAt: timestamp(\"created_at\").notNull().default(sql`NOW()`),\n}, (table) => ({\n articleIdx: index(\"prediction_markets_article_idx\").on(table.articleId),\n}));\n\n// Insert schemas\nexport const insertUserSchema = createInsertSchema(users).pick({\n username: true,\n password: true,\n preferredLanguage: true,\n avatar: true,\n});\n\nexport const insertMediaOutletSchema = createInsertSchema(mediaOutlets).pick({\n name: true,\n description: true,\n category: true,\n focusSubject: true,\n avatar: true,\n profileImage: true,\n bio: true,\n fullBio: true,\n wikiProfile: true,\n});\n\nexport const insertArticleSchema = createInsertSchema(articles).pick({\n outletId: true,\n title: true,\n summary: true,\n body: true,\n thumbnail: true,\n publishedAt: true,\n tags: true,\n viewCount: true,\n sourceUrl: true,\n author: true,\n originalImageUrl: true,\n scrapedAt: true,\n isScraped: true,\n}).extend({\n publishedAt: z.preprocess((val) => {\n if (typeof val === 'string') return new Date(val);\n if (val instanceof Date) return val;\n return new Date();\n }, z.date()),\n});\n\nexport const insertCommentSchema = createInsertSchema(comments).pick({\n articleId: true,\n content: true,\n nickname: true,\n avatar: true,\n parentId: true,\n});\n\nexport const insertCommentReactionSchema = createInsertSchema(commentReactions).pick({\n commentId: true,\n reactionType: true,\n userIdentifier: true,\n}).extend({\n reactionType: z.enum([\"like\", \"dislike\"]),\n});\n\nexport const insertBookmarkSchema = createInsertSchema(bookmarks).pick({\n articleId: true,\n userIdentifier: true,\n});\n\nexport const insertPredictionMarketSchema = createInsertSchema(predictionMarkets).pick({\n articleId: true,\n question: true,\n description: true,\n marketType: true,\n yesPrice: true,\n noPrice: true,\n options: true,\n totalVolume: true,\n endDate: true,\n category: true,\n isLive: true,\n isResolved: true,\n});\n\n// Types\nexport type InsertUser = z.infer;\nexport type User = typeof users.$inferSelect;\nexport type InsertMediaOutlet = z.infer;\nexport type MediaOutlet = typeof mediaOutlets.$inferSelect;\nexport type InsertArticle = z.infer;\nexport type Article = typeof articles.$inferSelect;\nexport type InsertComment = z.infer;\nexport type Comment = typeof comments.$inferSelect;\nexport type InsertCommentReaction = z.infer;\nexport type CommentReaction = typeof commentReactions.$inferSelect;\nexport type InsertBookmark = z.infer;\nexport type Bookmark = typeof bookmarks.$inferSelect;\nexport type InsertPredictionMarket = z.infer;\nexport type PredictionMarket = typeof predictionMarkets.$inferSelect;\n\n// Enums for categories\nexport const CATEGORIES = [\"people\", \"topics\", \"companies\"] as const;\nexport const FOCUS_SUBJECTS = [\"jacob\", \"ala\", \"ai\", \"crypto\", \"polychain\", \"dcg\"] as const;\nexport const LANGUAGES = [\n { code: \"en\", name: \"English\" },\n { code: \"fr\", name: \"Français\" },\n { code: \"hi\", name: \"हिन्दी\" },\n { code: \"ar\", name: \"العربية\" },\n { code: \"zh-TW\", name: \"繁體中文\" },\n { code: \"zh-CN\", name: \"简体中文\" },\n { code: \"ja\", name: \"日本語\" },\n { code: \"ko\", name: \"한국어\" },\n] as const;","size_bytes":8982},"client/src/App.tsx":{"content":"import { Switch, Route } from \"wouter\";\nimport { queryClient } from \"./lib/queryClient\";\nimport { QueryClientProvider } from \"@tanstack/react-query\";\nimport { Toaster } from \"@/components/ui/toaster\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport HomePage from \"@/pages/HomePage\";\nimport OutletPage from \"@/pages/OutletPage\";\nimport ArticlePage from \"@/pages/ArticlePage\";\nimport NotFound from \"@/pages/not-found\";\n\nfunction Router() {\n return (\n \n \n \n \n \n \n );\n}\n\nfunction App() {\n return (\n \n \n
\n \n
\n \n
\n
\n );\n}\n\nexport default App;","size_bytes":1006},"client/src/index.css":{"content":"@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n/* Search overlay styles */\n.search-overlay-open {\n overflow: hidden;\n}\n\n.search-overlay-open #root {\n transform: translateX(-10%);\n transition: transform 300ms ease-out;\n}\n\nbody:not(.search-overlay-open) #root {\n transform: translateX(0);\n transition: transform 300ms ease-out;\n}\n\n/* LIGHT MODE */\n:root {\n --button-outline: rgba(0,0,0, .10);\n --badge-outline: rgba(0,0,0, .05);\n\n /* Automatic computation of border around primary / danger buttons */\n --opaque-button-border-intensity: -8; /* In terms of percentages */\n\n /* Backgrounds applied on top of other backgrounds when hovered/active */\n --elevate-1: rgba(0,0,0, .03);\n --elevate-2: rgba(0,0,0, .08);\n\n --background: 0 0% 98%;\n\n --foreground: 222 15% 15%;\n\n --border: 220 13% 91%;\n\n --card: 0 0% 100%;\n\n --card-foreground: 222 15% 15%;\n\n --card-border: 220 13% 91%;\n\n --sidebar: 220 13% 96%;\n\n --sidebar-foreground: 222 15% 15%;\n\n --sidebar-border: 220 13% 93%;\n\n --sidebar-primary: 210 85% 55%;\n\n --sidebar-primary-foreground: 210 15% 95%;\n\n --sidebar-accent: 220 13% 93%;\n\n --sidebar-accent-foreground: 222 15% 15%;\n\n --sidebar-ring: 210 85% 55%;\n\n --popover: 220 13% 93%;\n\n --popover-foreground: 222 15% 15%;\n\n --popover-border: 220 13% 90%;\n\n --primary: 210 85% 55%;\n\n --primary-foreground: 210 15% 95%;\n\n --secondary: 220 13% 90%;\n\n --secondary-foreground: 222 15% 15%;\n\n --muted: 220 13% 94%;\n\n --muted-foreground: 222 15% 45%;\n\n --accent: 220 13% 94%;\n\n --accent-foreground: 222 15% 15%;\n\n --destructive: 0 84% 60%;\n\n --destructive-foreground: 0 15% 95%;\n\n --input: 220 13% 85%;\n --ring: 210 85% 55%;\n --chart-1: 210 85% 45%;\n --chart-2: 142 76% 40%;\n --chart-3: 280 65% 45%;\n --chart-4: 25 85% 45%;\n --chart-5: 340 75% 45%;\n\n --font-sans: Inter, sans-serif;\n --font-serif: Georgia, serif;\n --font-mono: Menlo, monospace;\n --radius: .5rem; /* 8px */\n --shadow-2xs: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);\n --shadow-xs: 0px 1px 2px 0px rgba(0, 0, 0, 0.05);\n --shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, 0.05), 0px 1px 3px 0px rgba(0, 0, 0, 0.1);\n --shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.05), 0px 1px 3px 0px rgba(0, 0, 0, 0.1);\n --shadow-md: 0px 2px 4px -1px rgba(0, 0, 0, 0.07), 0px 4px 6px -1px rgba(0, 0, 0, 0.1);\n --shadow-lg: 0px 4px 6px -2px rgba(0, 0, 0, 0.05), 0px 10px 15px -3px rgba(0, 0, 0, 0.1);\n --shadow-xl: 0px 8px 10px -3px rgba(0, 0, 0, 0.1), 0px 20px 25px -5px rgba(0, 0, 0, 0.1);\n --shadow-2xl: 0px 25px 50px -12px rgba(0, 0, 0, 0.25);\n --tracking-normal: 0em;\n --spacing: 0.25rem;\n\n /* Automatically computed borders - intensity can be controlled by the user by the --opaque-button-border-intensity setting */\n\n /* Fallback for older browsers */\n --sidebar-primary-border: hsl(var(--sidebar-primary));\n --sidebar-primary-border: hsl(from hsl(var(--sidebar-primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n\n /* Fallback for older browsers */\n --sidebar-accent-border: hsl(var(--sidebar-accent));\n --sidebar-accent-border: hsl(from hsl(var(--sidebar-accent)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n\n /* Fallback for older browsers */\n --primary-border: hsl(var(--primary));\n --primary-border: hsl(from hsl(var(--primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n\n /* Fallback for older browsers */\n --secondary-border: hsl(var(--secondary));\n --secondary-border: hsl(from hsl(var(--secondary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n\n /* Fallback for older browsers */\n --muted-border: hsl(var(--muted));\n --muted-border: hsl(from hsl(var(--muted)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n\n /* Fallback for older browsers */\n --accent-border: hsl(var(--accent));\n --accent-border: hsl(from hsl(var(--accent)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n\n /* Fallback for older browsers */\n --destructive-border: hsl(var(--destructive));\n --destructive-border: hsl(from hsl(var(--destructive)) h s calc(l + var(--opaque-button-border-intensity)) / alpha);\n}\n\n.dark {\n --button-outline: rgba(255,255,255, .10);\n --badge-outline: rgba(255,255,255, .05);\n\n --opaque-button-border-intensity: 9; /* In terms of percentages */\n\n /* Backgrounds applied on top of other backgrounds when hovered/active */\n --elevate-1: rgba(255,255,255, .04);\n --elevate-2: rgba(255,255,255, .09);\n\n --background: 222 15% 8%;\n\n --foreground: 210 15% 95%;\n\n --border: 222 15% 18%;\n\n --card: 222 15% 12%;\n\n --card-foreground: 210 15% 95%;\n\n --card-border: 222 15% 20%;\n\n --sidebar: 222 15% 10%;\n\n --sidebar-foreground: 210 15% 95%;\n\n --sidebar-border: 222 15% 15%;\n\n --sidebar-primary: 210 85% 55%;\n\n --sidebar-primary-foreground: 210 15% 95%;\n\n --sidebar-accent: 222 15% 15%;\n\n --sidebar-accent-foreground: 210 15% 95%;\n\n --sidebar-ring: 210 85% 55%;\n\n --popover: 222 15% 15%;\n\n --popover-foreground: 210 15% 95%;\n\n --popover-border: 222 15% 23%;\n\n --primary: 210 85% 55%;\n\n --primary-foreground: 210 15% 95%;\n\n --secondary: 222 15% 20%;\n\n --secondary-foreground: 210 15% 95%;\n\n --muted: 222 15% 14%;\n\n --muted-foreground: 210 15% 65%;\n\n --accent: 222 15% 14%;\n\n --accent-foreground: 210 15% 95%;\n\n --destructive: 0 84% 60%;\n\n --destructive-foreground: 0 15% 95%;\n\n /* Used as the border around inputs. Dark mode: Should be a border that is light enough to have high contrast when rendered on a --card background. More contrast than standard --border */\n --input: 222 15% 25%;\n --ring: 210 85% 55%;\n --chart-1: 210 85% 65%;\n --chart-2: 142 76% 60%;\n --chart-3: 280 65% 65%;\n --chart-4: 25 85% 65%;\n --chart-5: 340 75% 65%;\n\n --shadow-2xs: 0px 1px 2px 0px rgba(0, 0, 0, 0.3);\n --shadow-xs: 0px 1px 2px 0px rgba(0, 0, 0, 0.3);\n --shadow-sm: 0px 1px 2px 0px rgba(0, 0, 0, 0.3), 0px 1px 3px 0px rgba(0, 0, 0, 0.4);\n --shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.3), 0px 1px 3px 0px rgba(0, 0, 0, 0.4);\n --shadow-md: 0px 2px 4px -1px rgba(0, 0, 0, 0.4), 0px 4px 6px -1px rgba(0, 0, 0, 0.5);\n --shadow-lg: 0px 4px 6px -2px rgba(0, 0, 0, 0.4), 0px 10px 15px -3px rgba(0, 0, 0, 0.5);\n --shadow-xl: 0px 8px 10px -3px rgba(0, 0, 0, 0.5), 0px 20px 25px -5px rgba(0, 0, 0, 0.6);\n --shadow-2xl: 0px 25px 50px -12px rgba(0, 0, 0, 0.7);\n\n}\n\n@layer base {\n * {\n @apply border-border;\n }\n\n body {\n @apply font-sans antialiased bg-background text-foreground;\n }\n}\n\n/**\n * Using the elevate system.\n * Automatic contrast adjustment.\n *\n * \n * \n *\n * // Using the tailwind utility when a data attribute is \"on\"\n * \n * // Or manually controlling the toggle state\n * \n *\n * Elevation systems have to handle many states.\n * - not-hovered, vs. hovered vs. active (three mutually exclusive states)\n * - toggled or not\n * - focused or not (this is not handled with these utilities)\n *\n * Even without handling focused or not, this is six possible combinations that\n * need to be distinguished from eachother visually.\n */\n@layer utilities {\n\n /* Hide ugly search cancel button in Chrome until we can style it properly */\n input[type=\"search\"]::-webkit-search-cancel-button {\n @apply hidden;\n }\n\n /* Placeholder styling for contentEditable div */\n [contenteditable][data-placeholder]:empty::before {\n content: attr(data-placeholder);\n color: hsl(var(--muted-foreground));\n pointer-events: none;\n }\n\n /* .no-default-hover-elevate/no-default-active-elevate is an escape hatch so consumers of\n * buttons/badges can remove the automatic brightness adjustment on interactions\n * and program their own. */\n .no-default-hover-elevate {}\n\n .no-default-active-elevate {}\n\n\n /**\n * Toggleable backgrounds go behind the content. Hoverable/active goes on top.\n * This way they can stack/compound. Both will overlap the parent's borders!\n * So borders will be automatically adjusted both on toggle, and hover/active,\n * and they will be compounded.\n */\n .toggle-elevate::before,\n .toggle-elevate-2::before {\n content: \"\";\n pointer-events: none;\n position: absolute;\n inset: 0px;\n /*border-radius: inherit; match rounded corners */\n border-radius: inherit;\n z-index: -1;\n /* sits behind content but above backdrop */\n }\n\n .toggle-elevate.toggle-elevated::before {\n background-color: var(--elevate-2);\n }\n\n /* If there's a 1px border, adjust the inset so that it covers that parent's border */\n .border.toggle-elevate::before {\n inset: -1px;\n }\n\n /* Does not work on elements with overflow:hidden! */\n .hover-elevate:not(.no-default-hover-elevate),\n .active-elevate:not(.no-default-active-elevate),\n .hover-elevate-2:not(.no-default-hover-elevate),\n .active-elevate-2:not(.no-default-active-elevate) {\n position: relative;\n z-index: 0;\n }\n\n .hover-elevate:not(.no-default-hover-elevate)::after,\n .active-elevate:not(.no-default-active-elevate)::after,\n .hover-elevate-2:not(.no-default-hover-elevate)::after,\n .active-elevate-2:not(.no-default-active-elevate)::after {\n content: \"\";\n pointer-events: none;\n position: absolute;\n inset: 0px;\n /*border-radius: inherit; match rounded corners */\n border-radius: inherit;\n z-index: 999;\n /* sits in front of content */\n }\n\n .hover-elevate:hover:not(.no-default-hover-elevate)::after,\n .active-elevate:active:not(.no-default-active-elevate)::after {\n background-color: var(--elevate-1);\n }\n\n .hover-elevate-2:hover:not(.no-default-hover-elevate)::after,\n .active-elevate-2:active:not(.no-default-active-elevate)::after {\n background-color: var(--elevate-2);\n }\n\n /* If there's a 1px border, adjust the inset so that it covers that parent's border */\n .border.hover-elevate:not(.no-hover-interaction-elevate)::after,\n .border.active-elevate:not(.no-active-interaction-elevate)::after,\n .border.hover-elevate-2:not(.no-hover-interaction-elevate)::after,\n .border.active-elevate-2:not(.no-active-interaction-elevate)::after,\n .border.hover-elevate:not(.no-hover-interaction-elevate)::after {\n inset: -1px;\n }\n}","size_bytes":10235},"client/src/main.tsx":{"content":"import { createRoot } from \"react-dom/client\";\nimport App from \"./App\";\nimport \"./index.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render();\n","size_bytes":157},"client/src/components/ArticleCard.tsx":{"content":"import { Card } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { ArrowRight, MessageCircle, ThumbsUp } from \"lucide-react\";\nimport { useMemo } from \"react\";\n\ninterface ArticleCardProps {\n id: string;\n title: string;\n summary: string;\n thumbnail: string;\n publishedAt: Date;\n timeAgo?: string;\n outletName: string;\n category: string;\n onClick: (id: string) => void;\n className?: string;\n isAd?: boolean;\n tags?: string[];\n index?: number;\n variant?: 'card' | 'list';\n}\n\nexport default function ArticleCard({\n id,\n title,\n summary,\n thumbnail,\n publishedAt,\n timeAgo,\n outletName,\n category,\n onClick,\n className = \"\",\n isAd = false,\n tags = [],\n index = 0,\n variant = 'card',\n}: ArticleCardProps) {\n\n // Generate stable random data based on index and id (newer articles have smaller numbers)\n const { minutesAgo, commentsCount, likesCount } = useMemo(() => {\n // Use a simple hash of the id to get consistent randomness\n const hash = id.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);\n const baseMinutes = index * 5;\n const randomOffset = (hash % 5) + 1;\n \n // Generate comments count (0-50 based on hash)\n const comments = (hash % 51);\n \n // Generate likes count (5-200 based on hash)\n const likes = ((hash * 3) % 196) + 5;\n \n return {\n minutesAgo: baseMinutes + randomOffset,\n commentsCount: comments,\n likesCount: likes\n };\n }, [id, index]);\n // List variant JSX\n if (variant === 'list') {\n return (\n onClick(id)}\n data-testid={`card-article-${id}`}\n >\n
\n {/* Left: Thumbnail */}\n
\n \n {isAd && (\n
\n Ad\n
\n )}\n
\n \n {/* Right: Content */}\n
\n

\n {title}\n

\n \n

\n {summary}\n

\n \n {/* Bottom: time and engagement */}\n
\n
\n {timeAgo || `${minutesAgo} min ago`}\n
\n \n {!isAd && (\n
\n
\n \n {commentsCount}\n
\n
\n \n {likesCount}\n
\n
\n )}\n
\n
\n
\n
\n );\n }\n\n // Card variant JSX (default)\n return (\n onClick(id)}\n data-testid={`card-article-${id}`}\n >\n
\n \n
\n {isAd ? (\n \n Sponsored\n \n ) : (\n \n {category}\n \n )}\n
\n\n {/* Time info - bottom left (hide for ads) */}\n {!isAd && (\n
\n \n {timeAgo || `${minutesAgo} min ago`}\n \n
\n )}\n
\n \n
\n

\n {title}\n

\n \n

\n {summary}\n

\n \n {/* Tags and Read More button */}\n
\n {!isAd && tags && tags.length > 0 && (\n
\n {tags.slice(0, 3).map((tag, tagIndex) => (\n \n {tag}\n \n ))}\n
\n )}\n \n {/* Engagement metrics and Read More button */}\n
\n {/* Engagement metrics container - always present to maintain layout */}\n
\n {!isAd && (\n
\n
\n \n {commentsCount}\n
\n
\n \n {likesCount}\n
\n
\n )}\n
\n \n {/* Read More button - positioned at bottom right */}\n {\n e.stopPropagation();\n onClick(id);\n }}\n className=\"text-xs px-3 py-1 h-7 text-muted-foreground hover:text-foreground\"\n data-testid={`button-read-more-${id}`}\n >\n Read More\n \n \n
\n
\n
\n
\n );\n}","size_bytes":7582},"client/src/components/ArticleDetail.tsx":{"content":"import { useState, useMemo } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { formatTimeAgo } from \"@/lib/utils\";\nimport { ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { Card } from \"@/components/ui/card\";\nimport FeedItem from \"./FeedItem\";\nimport ArticlePopup from \"./ArticlePopup\";\nimport DOMPurify from \"dompurify\";\n\ninterface ArticleDetailProps {\n id: string;\n title: string;\n summary: string;\n body: string;\n thumbnail: string;\n publishedAt: Date;\n timeAgo?: string; // Server-provided time ago text\n outletName: string;\n category: string;\n tags?: string[];\n textSize?: number;\n onPreviousArticle?: () => void;\n onNextArticle?: () => void;\n hasPrevious?: boolean;\n hasNext?: boolean;\n onArticleClick?: (articleId: string) => void;\n onOutletClick?: (outletId: string) => void;\n}\n\nexport default function ArticleDetail({\n id,\n title,\n summary,\n body,\n thumbnail,\n publishedAt,\n timeAgo,\n outletName,\n category,\n tags = [],\n textSize = 5,\n onPreviousArticle,\n onNextArticle,\n hasPrevious = false,\n hasNext = false,\n onArticleClick,\n onOutletClick,\n}: ArticleDetailProps) {\n const [imageLoaded, setImageLoaded] = useState(false);\n // Use server-provided timeAgo or fallback to client calculation\n const timeAgoText = timeAgo || formatTimeAgo(publishedAt);\n\n // Clean up and truncate article body\n const cleanedBody = useMemo(() => {\n // More flexible pattern that handles:\n // - Case insensitivity\n // - Optional \"This article was\" prefix\n // - \"at\" or \"on\" variations\n // - CRLF line endings\n // - Variable whitespace/newlines\n const pattern = /^\\s*(?:This article was\\s+)?originally published\\s+(?:at|on)\\s+\\S+\\.?\\s*(?:\\r?\\n){1,2}/i;\n const cleaned = body.replace(pattern, '').trimStart();\n \n // Truncate at 3000 characters, but complete the sentence\n if (cleaned.length <= 3000) return cleaned;\n \n // Find the next sentence ending after 3000 characters\n const truncatePoint = 3000;\n const afterTruncate = cleaned.substring(truncatePoint);\n \n // Look for sentence endings: period, exclamation, question mark followed by space or end of string\n const sentenceEndMatch = afterTruncate.match(/[.!?](?:\\s|$)/);\n \n if (sentenceEndMatch && sentenceEndMatch.index !== undefined) {\n // Include the sentence ending character\n const endIndex = truncatePoint + sentenceEndMatch.index + 1;\n return cleaned.substring(0, endIndex);\n }\n \n // If no sentence ending found within reasonable distance, just cut at 3000\n return cleaned.substring(0, 3000);\n }, [body]);\n\n const sanitizeHtml = (html: string) => {\n return DOMPurify.sanitize(html, {\n ALLOWED_TAGS: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'ul', 'ol', 'li', 'strong', 'em', 'a'],\n ALLOWED_ATTR: ['href', 'target', 'rel'],\n ADD_ATTR: ['target', 'rel'],\n });\n };\n\n // Parse text content and convert **text** to subtitle JSX elements\n const parseBodyContent = (text: string) => {\n const lines = text.split('\\n');\n const elements: React.ReactNode[] = [];\n let currentParagraph: string[] = [];\n let keyIndex = 0;\n\n const flushParagraph = () => {\n if (currentParagraph.length > 0) {\n const paragraphText = currentParagraph.join('\\n').trim();\n if (paragraphText) {\n // Process inline bold formatting in paragraphs\n const processedParagraph = parseInlineBold(paragraphText);\n elements.push(\n

\n {processedParagraph}\n

\n );\n }\n currentParagraph = [];\n }\n };\n\n const parseInlineBold = (text: string) => {\n const parts = text.split(/(\\*\\*.*?\\*\\*)/);\n return parts.map((part, index) => {\n const boldMatch = part.match(/^\\*\\*(.*?)\\*\\*$/);\n if (boldMatch) {\n return {boldMatch[1]};\n }\n return part;\n });\n };\n\n lines.forEach((line, index) => {\n const trimmedLine = line.trim();\n \n // Check for different subtitle patterns\n // Pattern 1: Full-line subtitle **Title**\n const fullLineSubtitle = trimmedLine.match(/^\\*\\*(.*?)\\*\\*$/);\n // Pattern 2: Prefixed subtitle **Title:** Content\n const prefixedSubtitle = trimmedLine.match(/^\\s*\\*\\*(.+?)\\*\\*\\s*(.*)$/);\n \n if (fullLineSubtitle && trimmedLine === `**${fullLineSubtitle[1]}**`) {\n // Full-line subtitle - flush paragraph and add as h3\n flushParagraph();\n elements.push(\n

\n {fullLineSubtitle[1]}\n

\n );\n } else if (prefixedSubtitle && prefixedSubtitle[2].trim() !== '') {\n // Prefixed subtitle with content - flush paragraph, add h3, then start new paragraph\n flushParagraph();\n elements.push(\n

\n {prefixedSubtitle[1]}\n

\n );\n // Start new paragraph with remaining content if it exists\n if (prefixedSubtitle[2].trim()) {\n currentParagraph.push(prefixedSubtitle[2].trim());\n }\n } else if (trimmedLine === '') {\n // Empty line - flush current paragraph\n flushParagraph();\n } else {\n // Regular content line - add to current paragraph\n currentParagraph.push(line);\n }\n });\n\n // Flush any remaining paragraph\n flushParagraph();\n\n return elements;\n };\n\n const scrollToContent = () => {\n const contentElement = document.querySelector('[data-testid=\"article-content\"]');\n if (contentElement) {\n contentElement.scrollIntoView({ behavior: 'smooth' });\n }\n };\n\n // Calculate font size based on textSize (1-10 range, 5 is default)\n // textSize 1 = 0.68rem, textSize 5 = 1rem, textSize 10 = 1.4rem\n const bodyFontSize = `${(textSize / 10) * 0.8 + 0.6}rem`;\n const summaryFontSize = `${(textSize / 10) * 0.8 + 0.8}rem`;\n const titleFontSize = `${(textSize / 10) * 1.2 + 1.4}rem`;\n\n // Fetch latest articles for the feed below comments\n const { data: latestArticles } = useQuery({\n queryKey: ['/api/feed', { limit: 20, exclude: id }],\n queryFn: async () => {\n const response = await fetch('/api/feed?limit=20');\n return response.json();\n },\n });\n\n const handleArticleClick = (articleId: string) => {\n if (onArticleClick) {\n onArticleClick(articleId);\n }\n };\n\n const handleOutletClick = (outletId: string) => {\n if (onOutletClick) {\n onOutletClick(outletId);\n }\n };\n\n const [selectedArticleId, setSelectedArticleId] = useState(null);\n\n const handlePlayClick = (articleId: string) => {\n setSelectedArticleId(articleId);\n };\n\n const handleClosePopup = () => {\n setSelectedArticleId(null);\n };\n\n return (\n
\n {/* Hero image */}\n
\n setImageLoaded(true)}\n onClick={scrollToContent}\n data-testid=\"img-article-hero\"\n />\n {!imageLoaded && (\n
\n )}\n \n {/* Category badge */}\n
\n \n {category}\n \n
\n\n {/* Time info - bottom left */}\n
\n \n {timeAgoText}\n \n
\n
\n\n {/* Article content */}\n \n {/* Title */}\n

\n {title}\n

\n\n {/* Summary */}\n

\n {summary}\n

\n\n\n {/* Body content */}\n
\n {parseBodyContent(cleanedBody)}\n
\n
\n\n {/* Navigation */}\n {(hasPrevious || hasNext) && (\n
\n \n \n Previous Article\n \n \n \n Next Article\n \n \n
\n )}\n\n\n {/* Latest Articles Feed - YouTube style below comments */}\n {latestArticles?.items && latestArticles.items.length > 0 && (\n
\n
\n {latestArticles.items\n .filter((article: any) => article.id !== id) // Exclude current article\n .map((article: any) => (\n \n ))\n }\n
\n
\n )}\n\n {/* Article Popup */}\n \n
\n );\n}","size_bytes":11191},"client/src/components/CategoryTabs.tsx":{"content":"import { Button } from \"@/components/ui/button\";\nimport { Badge } from \"@/components/ui/badge\";\n\ninterface Category {\n id: string;\n name: string;\n count: number;\n}\n\ninterface CategoryTabsProps {\n categories: Category[];\n activeCategory: string;\n onCategoryChange: (categoryId: string) => void;\n}\n\nexport default function CategoryTabs({\n categories,\n activeCategory,\n onCategoryChange,\n}: CategoryTabsProps) {\n return (\n
\n {categories.map((category) => (\n onCategoryChange(category.id)}\n data-testid={`tab-${category.id}`}\n className=\"flex items-center gap-2 whitespace-nowrap shrink-0\"\n >\n {category.name}\n \n {category.count}\n \n \n ))}\n
\n );\n}","size_bytes":1102},"client/src/components/MobileHeader.tsx":{"content":"import { Search, UserCircle } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport SettingsDropdown from \"@/components/SettingsDropdown\";\n\n// Sapiens logo from attached assets\nconst sapiensLogo = \"/api/assets/sapiens-logo.png\";\n\ninterface MobileHeaderProps {\n onSearchClick: () => void;\n title?: string;\n showBackButton?: boolean;\n onBackClick?: () => void;\n}\n\nexport default function MobileHeader({\n onSearchClick,\n title = \"NewsHub\",\n showBackButton = false,\n onBackClick,\n}: MobileHeaderProps) {\n return (\n
\n
\n
\n {showBackButton && (\n \n ←\n \n )}\n {title === \"Sapiens\" ? (\n
\n \"SAPIENS\"\n
\n ) : (\n

{title}

\n )}\n
\n \n
\n \n \n \n \n \n \n {}}\n data-testid=\"button-login\"\n aria-label=\"Log in\"\n >\n \n \n
\n
\n
\n );\n}","size_bytes":2072},"client/src/components/OutletCard.tsx":{"content":"import { Card } from \"@/components/ui/card\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\n\ninterface OutletCardProps {\n id: string;\n name: string;\n description: string;\n category: string;\n focusSubject: string;\n avatar?: string;\n articleCount: number;\n onClick: (id: string) => void;\n className?: string;\n}\n\nexport default function OutletCard({\n id,\n name,\n description,\n category,\n focusSubject,\n avatar,\n articleCount,\n onClick,\n className = \"\",\n}: OutletCardProps) {\n const getInitials = (name: string) => {\n return name\n .split(' ')\n .map(word => word[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n };\n\n\n return (\n onClick(id)}\n data-testid={`card-outlet-${id}`}\n >\n
\n \n \n \n {getInitials(name)}\n \n \n \n
\n

\n {name}\n

\n

\n {description}\n

\n
\n
\n
\n );\n}","size_bytes":1818},"client/src/components/OutletProfile.tsx":{"content":"import { useState } from \"react\";\nimport { User, X, Search, Info, MoreHorizontal, FileText, List, UserCircle } from \"lucide-react\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\";\nimport { Button } from \"@/components/ui/button\";\nimport SettingsDropdown from \"@/components/SettingsDropdown\";\nimport DOMPurify from \"dompurify\";\n// Sapiens logo from attached assets\nconst sapiensLogo = \"/api/assets/sapiens-logo.png\";\n\ninterface OutletProfileProps {\n name: string;\n description: string;\n category: string;\n focusSubject: string;\n avatar?: string;\n profileImage?: string;\n bio: string;\n fullBio?: string[];\n wikiProfile?: string;\n articleCount?: number;\n isSticky?: boolean;\n // New props for sticky header functionality\n onSearchClick?: () => void;\n selectedLanguage?: string;\n onLanguageChange?: (language: string) => void;\n onLoginClick?: () => void;\n}\n\nexport default function OutletProfile({\n name,\n description,\n category,\n avatar,\n profileImage,\n fullBio,\n wikiProfile,\n bio,\n isSticky = false,\n onSearchClick,\n selectedLanguage = \"en\",\n onLanguageChange,\n onLoginClick,\n}: OutletProfileProps) {\n const [isProfileModalOpen, setIsProfileModalOpen] = useState(false);\n const [viewMode, setViewMode] = useState<'simple' | 'detailed'>('simple'); // simple = 3 bullets, detailed = wiki profile\n \n\n const getInitials = (name: string) => {\n return name\n .split(' ')\n .map(word => word[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n };\n\n const sanitizeHtml = (html: string) => {\n return DOMPurify.sanitize(html, {\n ALLOWED_TAGS: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'ul', 'ol', 'li', 'strong', 'em', 'a'],\n ALLOWED_ATTR: ['href', 'target', 'rel'],\n ADD_ATTR: ['target', 'rel'],\n FORBID_ATTR: ['style', 'onclick', 'onload'],\n ALLOW_DATA_ATTR: false\n });\n };\n\n\n if (isSticky) {\n // Fixed sticky header version with profile button\n return (\n <>\n
\n
\n
\n \n \n \n {getInitials(name)}\n \n \n
\n
\n \"SAPIENS\"\n
\n
\n

\n {name}\n

\n {/* Info icon next to name */}\n {fullBio && fullBio.length > 0 && (\n setIsProfileModalOpen(true)}\n data-testid=\"button-info\"\n className=\"h-6 w-6 shrink-0\"\n >\n \n \n )}\n
\n
\n
\n\n {/* Right side controls: Search, Settings, Login */}\n
\n {/* Search button */}\n {onSearchClick && (\n \n \n \n )}\n \n {/* Settings dropdown */}\n \n \n {/* Login button */}\n {})}\n data-testid=\"button-login\"\n aria-label=\"Log in\"\n >\n \n \n
\n
\n
\n\n {/* 프로필 모달 - sticky 버전에서도 포함 */}\n {isProfileModalOpen && (\n
setIsProfileModalOpen(false)}\n data-testid=\"modal-overlay\"\n >\n
e.stopPropagation()}\n data-testid=\"modal-content\"\n >\n
\n
\n
\n \n \n \n {getInitials(name)}\n \n \n
\n

\n {name}\n

\n
\n
\n setIsProfileModalOpen(false)}\n data-testid=\"button-modal-close\"\n >\n \n \n
\n \n {/* Toggle Buttons */}\n
\n setViewMode('simple')}\n className={`flex items-center justify-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-all ${\n viewMode === 'simple'\n ? 'bg-background text-foreground shadow-sm' \n : 'text-muted-foreground hover:text-foreground'\n }`}\n data-testid=\"button-simple-view\"\n >\n \n Simple\n \n setViewMode('detailed')}\n className={`flex items-center justify-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-all ${\n viewMode === 'detailed'\n ? 'bg-background text-foreground shadow-sm' \n : 'text-muted-foreground hover:text-foreground'\n }`}\n data-testid=\"button-detailed-view\"\n >\n \n Detailed\n \n
\n \n {/* Content based on view mode */}\n {viewMode === 'detailed' && wikiProfile ? (\n
\n ) : fullBio && fullBio.length > 0 && (\n
\n
\n {fullBio.slice(0, 3).map((point, index) => (\n
\n
\n

\n {point}\n

\n
\n ))}\n
\n
\n )}\n
\n
\n
\n )}\n \n );\n }\n\n // Slim profile version - 가로로 최대한 얇게\n return (\n <>\n
\n
\n
\n {/* 프로필 사진 하나만 동그라미에 */}\n \n \n \n {getInitials(name)}\n \n \n \n
\n
\n \"SAPIENS\"\n
\n
\n

\n {name}\n

\n {/* Info icon moved next to name for non-sticky version too */}\n {fullBio && fullBio.length > 0 && (\n setIsProfileModalOpen(true)}\n data-testid=\"button-info-non-sticky\"\n className=\"h-6 w-6 shrink-0\"\n >\n \n \n )}\n
\n
\n
\n\n
\n
\n\n {/* 5bullet point 프로필 팝업 */}\n {isProfileModalOpen && (\n
setIsProfileModalOpen(false)}\n data-testid=\"modal-overlay\"\n >\n
e.stopPropagation()}\n data-testid=\"modal-content\"\n >\n
\n
\n
\n \n \n \n {getInitials(name)}\n \n \n
\n

\n {name}\n

\n
\n
\n setIsProfileModalOpen(false)}\n data-testid=\"button-modal-close\"\n >\n \n \n
\n \n {/* Toggle Buttons */}\n
\n setViewMode('simple')}\n className={`flex items-center justify-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-all ${\n viewMode === 'simple'\n ? 'bg-background text-foreground shadow-sm' \n : 'text-muted-foreground hover:text-foreground'\n }`}\n data-testid=\"button-simple-view-2\"\n >\n \n Simple\n \n setViewMode('detailed')}\n className={`flex items-center justify-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-all ${\n viewMode === 'detailed'\n ? 'bg-background text-foreground shadow-sm' \n : 'text-muted-foreground hover:text-foreground'\n }`}\n data-testid=\"button-detailed-view-2\"\n >\n \n Detailed\n \n
\n \n {/* Content based on view mode */}\n {viewMode === 'detailed' && wikiProfile ? (\n
\n ) : fullBio && fullBio.length > 0 && (\n
\n
\n {fullBio.slice(0, 3).map((point, index) => (\n
\n
\n

\n {point}\n

\n
\n ))}\n
\n
\n )}\n
\n
\n
\n )}\n \n );\n}","size_bytes":14799},"client/src/components/SearchOverlay.tsx":{"content":"import { useState, useEffect, useRef } from \"react\";\nimport { Search, X } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Input } from \"@/components/ui/input\";\nimport { Card } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { useLocation } from \"wouter\";\n\ninterface SearchResult {\n id: string;\n title: string;\n summary: string;\n category?: string;\n outletName?: string;\n publishedAt?: Date;\n name?: string;\n description?: string;\n focusSubject?: string;\n}\n\ninterface SearchResults {\n articles: SearchResult[];\n outlets: SearchResult[];\n}\n\ninterface SearchOverlayProps {\n isOpen: boolean;\n onClose: () => void;\n onArticleClick: (id: string) => void;\n searchResults: SearchResults | SearchResult[] | null;\n onSearch: (query: string) => void;\n isLoading?: boolean;\n}\n\nexport default function SearchOverlay({\n isOpen,\n onClose,\n onArticleClick,\n searchResults,\n onSearch,\n isLoading = false,\n}: SearchOverlayProps) {\n const [query, setQuery] = useState(\"\");\n const [isVisible, setIsVisible] = useState(false);\n const [shouldAnimate, setShouldAnimate] = useState(false);\n const inputRef = useRef(null);\n const [, setLocation] = useLocation();\n\n useEffect(() => {\n if (isOpen) {\n setIsVisible(true);\n // Start animation after component is mounted and positioned\n const animationTimer = setTimeout(() => {\n setShouldAnimate(true);\n }, 10);\n \n // Focus input after animation starts\n setTimeout(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }, 100);\n\n return () => clearTimeout(animationTimer);\n } else {\n setShouldAnimate(false);\n // Hide after transition completes\n const timer = setTimeout(() => setIsVisible(false), 300);\n return () => clearTimeout(timer);\n }\n }, [isOpen]);\n\n useEffect(() => {\n const debounceTimer = setTimeout(() => {\n if (query.trim()) {\n onSearch(query);\n }\n }, 300);\n\n return () => clearTimeout(debounceTimer);\n }, [query, onSearch]);\n\n if (!isVisible) return null;\n\n const handleArticleClick = (id: string) => {\n setLocation(`/article/${id}`);\n onClose();\n };\n\n const handleOutletClick = (id: string) => {\n setLocation(`/outlet/${id}`);\n onClose();\n };\n\n return (\n
\n
\n {/* Header */}\n
\n
\n \n setQuery(e.target.value)}\n placeholder=\"Search articles...\"\n className=\"pl-10 pr-4\"\n data-testid=\"input-search\"\n />\n
\n \n \n \n
\n\n {/* Results - Now with proper flex and height constraints */}\n
\n {isLoading ? (\n
\n
Searching...
\n
\n ) : query.trim() === \"\" ? (\n
\n
Start typing to search articles and outlets
\n
\n ) : (() => {\n // Handle different search result formats\n let articles: SearchResult[] = [];\n let outlets: SearchResult[] = [];\n \n if (Array.isArray(searchResults)) {\n // Legacy format - assume all are articles\n articles = searchResults;\n } else if (searchResults && typeof searchResults === 'object') {\n // New format with articles and outlets\n articles = searchResults.articles || [];\n outlets = searchResults.outlets || [];\n }\n \n const totalResults = articles.length + outlets.length;\n \n return totalResults === 0 ? (\n
\n
No results found
\n
\n ) : (\n
\n
\n {totalResults} result{totalResults !== 1 ? 's' : ''} found\n
\n \n {/* Outlets Section - Now shows first */}\n {outlets.length > 0 && (\n
\n

Outlets ({outlets.length})

\n {outlets.map((result) => (\n handleOutletClick(result.id)}\n data-testid={`search-result-outlet-${result.id}`}\n >\n
\n
\n

\n {result.name || result.title}\n

\n {result.category && (\n \n {result.category}\n \n )}\n
\n

\n {result.description || result.summary}\n

\n
\n \n ))}\n
\n )}\n \n {/* Articles Section - Now shows second */}\n {articles.length > 0 && (\n
\n

Articles ({articles.length})

\n {articles.map((result: any) => (\n handleArticleClick(result.id)}\n data-testid={`search-result-article-${result.id}`}\n >\n
\n {/* Thumbnail on the left */}\n
\n \n
\n \n {/* Content on the right */}\n
\n
\n

\n {result.title}\n

\n {result.outletName && (\n \n {result.outletName}\n \n )}\n
\n

\n {result.summary}\n

\n
\n
\n \n ))}\n
\n )}\n
\n );\n })()}\n
\n
\n
\n );\n}","size_bytes":8918},"client/src/components/SwipeableCarousel.tsx":{"content":"import { useState, useRef, useEffect } from \"react\";\nimport { Card } from \"@/components/ui/card\";\n\ninterface CarouselItem {\n id: string;\n content: React.ReactNode;\n}\n\ninterface SwipeableCarouselProps {\n items: CarouselItem[];\n autoScroll?: boolean;\n autoScrollDelay?: number;\n className?: string;\n}\n\nexport default function SwipeableCarousel({\n items,\n autoScroll = true,\n autoScrollDelay = 5000,\n className = \"\",\n}: SwipeableCarouselProps) {\n const [currentIndex, setCurrentIndex] = useState(0);\n const [isDragging, setIsDragging] = useState(false);\n const carouselRef = useRef(null);\n const startXRef = useRef(0);\n const scrollLeftRef = useRef(0);\n\n // Auto scroll functionality\n useEffect(() => {\n if (!autoScroll || isDragging) return;\n\n const interval = setInterval(() => {\n setCurrentIndex((prev) => (prev + 1) % items.length);\n }, autoScrollDelay);\n\n return () => clearInterval(interval);\n }, [autoScroll, autoScrollDelay, isDragging, items.length]);\n\n // Handle manual scroll\n const handleMouseDown = (e: React.MouseEvent) => {\n setIsDragging(true);\n const carousel = carouselRef.current;\n if (!carousel) return;\n\n startXRef.current = e.pageX - carousel.offsetLeft;\n scrollLeftRef.current = carousel.scrollLeft;\n };\n\n const handleMouseMove = (e: React.MouseEvent) => {\n if (!isDragging) return;\n e.preventDefault();\n \n const carousel = carouselRef.current;\n if (!carousel) return;\n\n const x = e.pageX - carousel.offsetLeft;\n const walk = (x - startXRef.current) * 2;\n carousel.scrollLeft = scrollLeftRef.current - walk;\n };\n\n const handleMouseUp = () => {\n setIsDragging(false);\n };\n\n // Touch events for mobile\n const handleTouchStart = (e: React.TouchEvent) => {\n setIsDragging(true);\n const carousel = carouselRef.current;\n if (!carousel) return;\n\n startXRef.current = e.touches[0].pageX - carousel.offsetLeft;\n scrollLeftRef.current = carousel.scrollLeft;\n };\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!isDragging) return;\n \n const carousel = carouselRef.current;\n if (!carousel) return;\n\n const x = e.touches[0].pageX - carousel.offsetLeft;\n const walk = (x - startXRef.current) * 2;\n carousel.scrollLeft = scrollLeftRef.current - walk;\n };\n\n const handleTouchEnd = () => {\n setIsDragging(false);\n };\n\n return (\n
\n \n {items.map((item, index) => (\n \n {item.content}\n
\n ))}\n
\n
\n );\n}","size_bytes":3219},"client/src/hooks/use-mobile.tsx":{"content":"import * as React from \"react\"\n\nconst MOBILE_BREAKPOINT = 768\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState(undefined)\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n }\n mql.addEventListener(\"change\", onChange)\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n return () => mql.removeEventListener(\"change\", onChange)\n }, [])\n\n return !!isMobile\n}\n","size_bytes":565},"client/src/hooks/use-toast.ts":{"content":"import * as React from \"react\"\n\nimport type {\n ToastActionElement,\n ToastProps,\n} from \"@/components/ui/toast\"\n\nconst TOAST_LIMIT = 1\nconst TOAST_REMOVE_DELAY = 1000000\n\ntype ToasterToast = ToastProps & {\n id: string\n title?: React.ReactNode\n description?: React.ReactNode\n action?: ToastActionElement\n}\n\nconst actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const\n\nlet count = 0\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER\n return count.toString()\n}\n\ntype ActionType = typeof actionTypes\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"]\n toast: ToasterToast\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"]\n toast: Partial\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"]\n toastId?: ToasterToast[\"id\"]\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"]\n toastId?: ToasterToast[\"id\"]\n }\n\ninterface State {\n toasts: ToasterToast[]\n}\n\nconst toastTimeouts = new Map>()\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId)\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n })\n }, TOAST_REMOVE_DELAY)\n\n toastTimeouts.set(toastId, timeout)\n}\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n }\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t\n ),\n }\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId)\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id)\n })\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t\n ),\n }\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n }\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n }\n }\n}\n\nconst listeners: Array<(state: State) => void> = []\n\nlet memoryState: State = { toasts: [] }\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action)\n listeners.forEach((listener) => {\n listener(memoryState)\n })\n}\n\ntype Toast = Omit\n\nfunction toast({ ...props }: Toast) {\n const id = genId()\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n })\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id })\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss()\n },\n },\n })\n\n return {\n id: id,\n dismiss,\n update,\n }\n}\n\nfunction useToast() {\n const [state, setState] = React.useState(memoryState)\n\n React.useEffect(() => {\n listeners.push(setState)\n return () => {\n const index = listeners.indexOf(setState)\n if (index > -1) {\n listeners.splice(index, 1)\n }\n }\n }, [state])\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n }\n}\n\nexport { useToast, toast }\n","size_bytes":3895},"client/src/hooks/useApi.ts":{"content":"import { useQuery, useMutation, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';\nimport { outletsApi, articlesApi, searchApi, mutations, feedApi } from '@/lib/api';\n\n// Outlets hooks\nexport function useOutlets(category?: string) {\n return useQuery({\n queryKey: ['/outlets', category],\n queryFn: () => outletsApi.getAll(category),\n });\n}\n\nexport function useOutlet(id: string) {\n return useQuery({\n queryKey: ['outlet', id],\n queryFn: () => outletsApi.getById(id),\n enabled: !!id && id.trim().length > 0,\n });\n}\n\n// Articles hooks\nexport function useArticles() {\n return useQuery({\n queryKey: ['/articles'],\n queryFn: () => articlesApi.getAll(),\n });\n}\n\nexport function useArticlesByOutlet(outletId: string) {\n return useQuery({\n queryKey: ['/articles', outletId],\n queryFn: () => articlesApi.getByOutlet(outletId),\n enabled: !!outletId,\n });\n}\n\nexport function useFeaturedArticles(limit = 10) {\n return useQuery({\n queryKey: ['/articles', 'featured', limit],\n queryFn: () => articlesApi.getFeatured(limit),\n });\n}\n\nexport function useArticle(id: string) {\n return useQuery({\n queryKey: ['/articles', id],\n queryFn: () => articlesApi.getById(id),\n enabled: !!id,\n });\n}\n\n// Search hooks\nexport function useSearch(query: string, type: 'all' | 'articles' | 'outlets' = 'all') {\n return useQuery({\n queryKey: ['/search', query, type],\n queryFn: () => searchApi.search(query, type),\n enabled: !!query.trim(),\n });\n}\n\n// Backward compatibility\nexport function useSearchArticles(query: string) {\n return useQuery({\n queryKey: ['/search', query, 'articles'],\n queryFn: () => searchApi.articles(query),\n enabled: !!query.trim(),\n });\n}\n\n// Mutation hooks\nexport function useCreateOutlet() {\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: mutations.createOutlet,\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['/outlets'] });\n },\n });\n}\n\nexport function useCreateArticle() {\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: mutations.createArticle,\n onSuccess: (data, variables) => {\n queryClient.invalidateQueries({ queryKey: ['/articles'] });\n queryClient.invalidateQueries({ queryKey: ['/articles', variables.outletId] });\n },\n });\n}\n\n// YouTube-style feed hooks\nexport function useFeed(filter: 'all' | 'people' | 'topics' | 'companies' = 'all') {\n return useInfiniteQuery({\n queryKey: ['/feed', filter],\n queryFn: ({ pageParam }) => {\n return feedApi.getFeed({\n cursor: pageParam,\n limit: 10,\n filter: filter\n });\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage: any) => lastPage?.nextCursor,\n });\n}\n\nexport function useIncrementView(filter?: 'all' | 'people' | 'topics' | 'companies') {\n const queryClient = useQueryClient();\n \n return useMutation({\n mutationFn: feedApi.incrementView,\n onSuccess: (_, articleId) => {\n console.log(`[DEBUG] View incremented for article ${articleId}, invalidating cache with filter:`, filter);\n // Invalidate the specific filter's feed cache for better precision\n if (filter) {\n queryClient.invalidateQueries({ queryKey: ['/feed', filter] });\n } else {\n // Fallback to invalidating all feed caches if filter not provided\n queryClient.invalidateQueries({ queryKey: ['/feed'] });\n }\n // Also invalidate the specific article cache\n queryClient.invalidateQueries({ queryKey: ['/articles'] });\n },\n });\n}","size_bytes":3589},"client/src/lib/api.ts":{"content":"import { queryClient } from './queryClient';\n\nconst API_BASE = '/api';\n\n// Generic API request helper\nasync function apiRequest(endpoint: string, options: RequestInit = {}): Promise {\n const response = await fetch(`${API_BASE}${endpoint}`, {\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n ...options,\n });\n\n if (!response.ok) {\n throw new Error(`API Error: ${response.statusText}`);\n }\n\n return response.json();\n}\n\n// Outlets API\nexport const outletsApi = {\n getAll: (category?: string) => \n apiRequest(`/outlets${category ? `?category=${category}` : ''}`),\n \n getById: (id: string) => \n apiRequest(`/outlets/${id}`),\n \n create: (data: any) => \n apiRequest('/outlets', {\n method: 'POST',\n body: JSON.stringify(data),\n }),\n};\n\n// Articles API\nexport const articlesApi = {\n getAll: () => \n apiRequest('/articles'),\n \n getByOutlet: (outletId: string) => \n apiRequest(`/articles?outlet=${outletId}`),\n \n getFeatured: (limit = 10) => \n apiRequest(`/articles?featured=true&limit=${limit}`),\n \n getById: (id: string) => \n apiRequest(`/articles/${id}`),\n \n create: (data: any) => \n apiRequest('/articles', {\n method: 'POST',\n body: JSON.stringify(data),\n }),\n};\n\n// Search API\nexport const searchApi = {\n search: (query: string, type: 'all' | 'articles' | 'outlets' = 'all') => \n apiRequest(`/search?q=${encodeURIComponent(query)}&type=${type}`),\n \n // Backward compatibility\n articles: (query: string) => \n apiRequest(`/search?q=${encodeURIComponent(query)}&type=articles`).then((result: any) => result.articles || []),\n};\n\n// AI API\nexport const aiApi = {\n generateThumbnail: (description: string, aspectRatio = '16:9') =>\n apiRequest('/generate-thumbnail', {\n method: 'POST',\n body: JSON.stringify({ description, aspectRatio }),\n }),\n \n enhanceArticle: (title: string, summary: string, content: string) =>\n apiRequest('/enhance-article', {\n method: 'POST',\n body: JSON.stringify({ title, summary, content }),\n }),\n\n generateSummary: (content: string, title?: string) =>\n apiRequest('/generate-summary', {\n method: 'POST',\n body: JSON.stringify({ content, title }),\n }),\n};\n\n// Stats API\nexport const statsApi = {\n get: () => apiRequest('/stats'),\n};\n\n// Feed API for YouTube-style interface\nexport const feedApi = {\n getFeed: (params: { \n cursor?: string; \n limit?: number; \n filter?: 'all' | 'people' | 'topics' | 'companies' \n }) => {\n const searchParams = new URLSearchParams();\n if (params.cursor) searchParams.set('cursor', params.cursor);\n if (params.limit) searchParams.set('limit', params.limit.toString());\n if (params.filter) searchParams.set('filter', params.filter);\n \n return apiRequest(`/feed?${searchParams.toString()}`);\n },\n \n incrementView: (articleId: string) => \n apiRequest(`/articles/${articleId}/view`, {\n method: 'POST'\n })\n};\n\n// Mutation helpers for React Query\nexport const mutations = {\n createOutlet: (data: any) => {\n return apiRequest('/outlets', {\n method: 'POST',\n body: JSON.stringify(data),\n }).then((result) => {\n queryClient.invalidateQueries({ queryKey: ['/outlets'] });\n return result;\n });\n },\n \n createArticle: (data: any) => {\n return apiRequest('/articles', {\n method: 'POST',\n body: JSON.stringify(data),\n }).then((result) => {\n queryClient.invalidateQueries({ queryKey: ['/articles'] });\n queryClient.invalidateQueries({ queryKey: ['/articles', data.outletId] });\n return result;\n });\n },\n};","size_bytes":3630},"client/src/lib/queryClient.ts":{"content":"import { QueryClient, QueryFunction } from \"@tanstack/react-query\";\n\nasync function throwIfResNotOk(res: Response) {\n if (!res.ok) {\n const text = (await res.text()) || res.statusText;\n throw new Error(`${res.status}: ${text}`);\n }\n}\n\nexport async function apiRequest(\n method: string,\n url: string,\n data?: unknown | undefined,\n): Promise {\n const res = await fetch(url, {\n method,\n headers: data ? { \"Content-Type\": \"application/json\" } : {},\n body: data ? JSON.stringify(data) : undefined,\n credentials: \"include\",\n });\n\n await throwIfResNotOk(res);\n return res;\n}\n\ntype UnauthorizedBehavior = \"returnNull\" | \"throw\";\nexport const getQueryFn: (options: {\n on401: UnauthorizedBehavior;\n}) => QueryFunction =\n ({ on401: unauthorizedBehavior }) =>\n async ({ queryKey }) => {\n const res = await fetch(queryKey.join(\"/\") as string, {\n credentials: \"include\",\n });\n\n if (unauthorizedBehavior === \"returnNull\" && res.status === 401) {\n return null;\n }\n\n await throwIfResNotOk(res);\n return await res.json();\n };\n\nexport const queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n queryFn: getQueryFn({ on401: \"throw\" }),\n refetchInterval: false,\n refetchOnWindowFocus: false,\n staleTime: Infinity,\n retry: false,\n },\n mutations: {\n retry: false,\n },\n },\n});\n","size_bytes":1383},"client/src/lib/utils.ts":{"content":"import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Format time distance - always returns \"X min ago\" format\n */\nexport function formatTimeAgo(date: Date | string): string {\n const now = new Date()\n const past = new Date(date)\n const diffInSeconds = Math.floor((now.getTime() - past.getTime()) / 1000)\n const diffInMinutes = Math.floor(diffInSeconds / 60)\n \n // Always return in \"X min ago\" format\n return `${diffInMinutes} min ago`\n}\n","size_bytes":564},"client/src/pages/ArticlePage.tsx":{"content":"import { useState, useEffect } from \"react\";\nimport { useRoute, useLocation } from \"wouter\";\nimport { useQuery, useMutation } from \"@tanstack/react-query\";\nimport { Plus, Minus, RotateCcw } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { Card } from \"@/components/ui/card\";\nimport { apiRequest, queryClient } from \"@/lib/queryClient\";\nimport ArticleDetail from \"@/components/ArticleDetail\";\nimport SearchOverlay from \"@/components/SearchOverlay\";\nimport BottomTabBar from \"@/components/BottomTabBar\";\nimport CommentsDrawer from \"@/components/CommentsDrawer\";\nimport OutletProfile from \"@/components/OutletProfile\";\nimport PredictionMarketCard from \"@/components/PredictionMarketCard\";\nimport { useSearch } from \"@/hooks/useApi\";\nimport { useToast } from \"@/hooks/use-toast\";\nimport type { Article, MediaOutlet, PredictionMarket } from \"@shared/schema\";\n\n\nexport default function ArticlePage() {\n const [match, params] = useRoute(\"/article/:id\");\n const [, setLocation] = useLocation();\n const [selectedLanguage, setSelectedLanguage] = useState(\"en\");\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [showComments, setShowComments] = useState(false);\n const [textSize, setTextSize] = useState(5);\n const [showTextSizeControls, setShowTextSizeControls] = useState(false);\n const [showAllMarkets, setShowAllMarkets] = useState(false);\n const [userIdentifier] = useState(() => {\n const stored = localStorage.getItem('userIdentifier');\n if (stored) return stored;\n const newId = `user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n localStorage.setItem('userIdentifier', newId);\n return newId;\n });\n const { toast } = useToast();\n\n const articleId = params?.id || '';\n \n // Search API call\n const { data: searchResults = { articles: [], outlets: [] } } = useSearch(searchQuery);\n \n // Fetch article from API\n const { data: article, isLoading: articleLoading, isError: articleError } = useQuery
({\n queryKey: ['/api/articles', articleId],\n enabled: !!articleId\n });\n\n // Fetch outlet information for the article\n const { data: outlet, isLoading: outletLoading } = useQuery({\n queryKey: ['/api/outlets', article?.outletId],\n enabled: !!article?.outletId\n });\n\n // Fetch comment count\n const { data: commentCountData } = useQuery<{ count: number }>({\n queryKey: ['/api/articles', articleId, 'comment-count'],\n enabled: !!articleId\n });\n\n // Fetch bookmark status\n const { data: bookmarkData } = useQuery<{ isBookmarked: boolean }>({\n queryKey: ['/api/bookmarks', articleId, userIdentifier],\n enabled: !!articleId && !!userIdentifier\n });\n\n // Fetch prediction markets\n const { data: predictionMarkets = [] } = useQuery({\n queryKey: ['/api/prediction-markets/article', articleId, showAllMarkets ? 100 : 3],\n queryFn: async () => {\n const limit = showAllMarkets ? 100 : 3;\n const response = await fetch(`/api/prediction-markets/article/${articleId}?limit=${limit}`);\n return response.json();\n },\n enabled: !!articleId\n });\n\n // Toggle bookmark mutation - must be declared before any conditional returns\n const toggleBookmark = useMutation({\n mutationFn: async () => {\n const response = await apiRequest('POST', '/api/bookmarks/toggle', {\n articleId,\n userIdentifier,\n });\n return response.json();\n },\n onSuccess: () => {\n queryClient.invalidateQueries({ queryKey: ['/api/bookmarks', articleId, userIdentifier] });\n },\n });\n\n const commentCount = commentCountData?.count || 0;\n const isBookmarked = bookmarkData?.isBookmarked || false;\n\n const isLoading = articleLoading || outletLoading;\n const isError = articleError;\n\n if (isLoading) {\n return (\n
\n
\n
\n

Loading article...

\n
\n
\n );\n }\n\n if (isError || !article) {\n return (\n
\n
\n

Article not found

\n

The requested article does not exist.

\n
\n
\n );\n }\n\n // Previous/next navigation will be implemented when feed ordering is available\n const handlePreviousArticle = () => {};\n const handleNextArticle = () => {};\n\n const handleArticleClick = (articleId: string) => {\n setLocation(`/article/${articleId}`);\n };\n\n const handleOutletClick = (outletId: string) => {\n setLocation(`/outlet/${outletId}`);\n };\n\n const handleTitleClick = () => {\n // Navigate to home with the article's outlet category selected\n const category = outlet?.category || 'people';\n setLocation(`/?category=${category}`);\n };\n\n const handleBackClick = () => {\n // Navigate back to the outlet page\n if (outlet?.id) {\n setLocation(`/outlet/${outlet.id}`);\n } else {\n window.history.back();\n }\n };\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n };\n\n const handleCommentClick = () => {\n setShowComments(!showComments);\n };\n\n const handleShareClick = () => {\n if (navigator.share) {\n navigator.share({\n title: article?.title,\n text: article?.summary,\n url: window.location.href,\n });\n } else {\n navigator.clipboard.writeText(window.location.href);\n toast({\n title: \"Link copied\",\n description: \"Article link copied to clipboard\",\n });\n }\n };\n\n const handleBookmarkClick = () => {\n toggleBookmark.mutate();\n toast({\n title: isBookmarked ? \"Removed from bookmarks\" : \"Added to bookmarks\",\n description: isBookmarked ? \"Article removed from your bookmarks\" : \"Article saved to your bookmarks\",\n });\n };\n\n const handleTextSizeChange = (size: number) => {\n setTextSize(size);\n };\n\n return (\n
\n {/* Main content with slide transition */}\n
\n {/* Outlet Profile - sticky at top */}\n
\n {outlet && (\n setIsSearchOpen(true)}\n selectedLanguage={selectedLanguage}\n onLanguageChange={setSelectedLanguage}\n onLoginClick={() => console.log('Login clicked')}\n />\n )}\n
\n\n
\n \n\n {/* Prediction Markets Section */}\n {predictionMarkets.length > 0 && (\n
\n

Related Prediction Markets

\n
\n {predictionMarkets.map(market => (\n console.log('Market clicked:', market.id)}\n />\n ))}\n
\n {!showAllMarkets && predictionMarkets.length >= 3 && (\n setShowAllMarkets(true)}\n data-testid=\"button-load-more-markets\"\n >\n Load More\n \n )}\n
\n )}\n
\n
\n\n {/* Text Size Controls - shown when text size button clicked */}\n {showTextSizeControls && (\n
\n \n
\n {/* Plus button */}\n handleTextSizeChange(Math.min(9, textSize + 1))}\n disabled={textSize === 9}\n data-testid=\"button-text-size-increase\"\n >\n \n \n \n {/* Minus button */}\n handleTextSizeChange(Math.max(0, textSize - 1))}\n disabled={textSize === 0}\n data-testid=\"button-text-size-decrease\"\n >\n \n \n \n {/* Reset button */}\n handleTextSizeChange(5)}\n data-testid=\"button-text-size-reset\"\n >\n \n \n
\n
\n
\n )}\n\n {/* Bottom Navigation Bar with integrated action icons */}\n setShowTextSizeControls(!showTextSizeControls)}\n />\n \n {/* Search Overlay positioned to slide in from right */}\n setIsSearchOpen(false)}\n onArticleClick={(id) => setLocation(`/article/${id}`)}\n searchResults={searchResults as any}\n onSearch={handleSearch}\n />\n\n {/* Comments Drawer */}\n setShowComments(false)}\n />\n
\n );\n}","size_bytes":11396},"client/src/pages/HomePage.tsx":{"content":"import { useState, useEffect } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useLocation } from \"wouter\";\nimport MobileHeader from \"@/components/MobileHeader\";\nimport FeedList from \"@/components/FeedList\";\nimport BottomTabBar from \"@/components/BottomTabBar\";\nimport SearchOverlay from \"@/components/SearchOverlay\";\nimport OutletCard from \"@/components/OutletCard\";\nimport { useSearch } from \"@/hooks/useApi\";\nimport type { MediaOutlet } from \"@shared/schema\";\n\n// Extended type for outlets with article count from API\ntype MediaOutletWithCount = MediaOutlet & {\n articleCount?: number;\n};\n\n// Real data now loaded from API\n\nexport default function HomePage() {\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [, setLocation] = useLocation();\n \n // Get category from URL params or default to 'people'\n const getInitialCategory = (): 'people' | 'topics' | 'companies' => {\n const params = new URLSearchParams(window.location.search);\n const category = params.get('category') as 'people' | 'topics' | 'companies';\n return ['people', 'topics', 'companies'].includes(category) ? category : 'people';\n };\n \n const [activeFilter, setActiveFilter] = useState<'people' | 'topics' | 'companies'>(getInitialCategory());\n \n // Update URL when category changes\n useEffect(() => {\n const params = new URLSearchParams(window.location.search);\n params.set('category', activeFilter);\n const newUrl = `${window.location.pathname}?${params.toString()}`;\n window.history.replaceState({}, '', newUrl);\n }, [activeFilter]);\n \n // Handle browser back/forward buttons\n useEffect(() => {\n const handlePopState = () => {\n setActiveFilter(getInitialCategory());\n };\n \n window.addEventListener('popstate', handlePopState);\n return () => window.removeEventListener('popstate', handlePopState);\n }, []);\n\n // Search API call\n const { data: searchResults = { articles: [], outlets: [] } } = useSearch(searchQuery);\n\n // Fetch all outlets\n const { data: allOutlets = [], isLoading: outletsLoading } = useQuery({\n queryKey: ['/api/outlets'],\n });\n\n // Filter outlets based on activeFilter\n const filteredOutlets = allOutlets.filter(outlet => {\n return outlet.category === activeFilter;\n });\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n };\n\n return (\n
\n {/* YouTube-style Header */}\n setIsSearchOpen(true)}\n />\n\n {/* Media Outlets Section */}\n
\n {outletsLoading ? (\n
\n
\n

Loading media outlets...

\n
\n ) : (\n
\n {filteredOutlets.map((outlet) => (\n setLocation(`/outlet/${id}`)}\n />\n ))}\n
\n )}\n
\n\n\n {/* Bottom Tab Bar */}\n {\n // Push new state to history for proper back/forward navigation\n const params = new URLSearchParams();\n params.set('category', tab);\n const newUrl = `${window.location.pathname}?${params.toString()}`;\n window.history.pushState({}, '', newUrl);\n setActiveFilter(tab);\n }}\n />\n\n {/* Search Overlay */}\n setIsSearchOpen(false)}\n onArticleClick={(id) => console.log('Navigate to article:', id)}\n searchResults={searchResults as any}\n onSearch={handleSearch}\n />\n
\n );\n}","size_bytes":4395},"client/src/pages/OutletPage.tsx":{"content":"import { useState, useEffect, useRef, useCallback } from \"react\";\nimport { useRoute, useLocation } from \"wouter\";\nimport { Loader2, Grid3X3, List } from \"lucide-react\";\nimport { Button } from \"@/components/ui/button\";\nimport OutletProfile from \"@/components/OutletProfile\";\nimport BottomTabBar from \"@/components/BottomTabBar\";\nimport ArticleCard from \"@/components/ArticleCard\";\nimport SearchOverlay from \"@/components/SearchOverlay\";\nimport { useOutlet, useArticlesByOutlet, useSearch } from \"@/hooks/useApi\";\nimport { queryClient } from \"@/lib/queryClient\";\n\n// Real data loaded from API\n\nexport default function OutletPage() {\n const [match, params] = useRoute(\"/outlet/:id\");\n const [, setLocation] = useLocation();\n const [selectedLanguage, setSelectedLanguage] = useState(\"en\");\n const [isSearchOpen, setIsSearchOpen] = useState(false);\n const [searchQuery, setSearchQuery] = useState(\"\");\n const [viewMode, setViewMode] = useState<'card' | 'list'>('card');\n \n // Pull-to-refresh state\n const [isPulling, setIsPulling] = useState(false);\n const [isRefreshing, setIsRefreshing] = useState(false);\n const [pullDistance, setPullDistance] = useState(0);\n const touchStartY = useRef(0);\n const touchCurrentY = useRef(0);\n const containerRef = useRef(null);\n\n // Fix route parameter extraction - wouter returns params as second element\n const outletId = params?.id || '';\n \n // API calls for real data\n const { data: outlet, isLoading: outletLoading, error: outletError } = useOutlet(outletId);\n const { data: articles = [], isLoading: articlesLoading } = useArticlesByOutlet(outletId);\n const { data: searchResults = { articles: [], outlets: [] } } = useSearch(searchQuery);\n \n // Pull-to-refresh handlers - MUST be before any conditional returns\n const handleRefresh = useCallback(async () => {\n setIsRefreshing(true);\n try {\n // Invalidate and refetch outlet and articles data\n await queryClient.invalidateQueries({ queryKey: ['outlet', outletId] });\n await queryClient.invalidateQueries({ queryKey: ['articles', outletId] });\n // Wait a bit for the refresh to complete\n setTimeout(() => {\n setIsRefreshing(false);\n setIsPulling(false);\n setPullDistance(0);\n }, 1000);\n } catch (error) {\n setIsRefreshing(false);\n setIsPulling(false);\n setPullDistance(0);\n }\n }, [outletId]);\n\n const handleTouchStart = useCallback((e: TouchEvent) => {\n if (containerRef.current && containerRef.current.scrollTop === 0) {\n touchStartY.current = e.touches[0].clientY;\n setIsPulling(true);\n }\n }, []);\n\n const handleTouchMove = useCallback((e: TouchEvent) => {\n if (!isPulling || isRefreshing) return;\n \n touchCurrentY.current = e.touches[0].clientY;\n const distance = touchCurrentY.current - touchStartY.current;\n \n if (distance > 0) {\n e.preventDefault();\n const pullDist = Math.min(distance * 0.5, 80); // Max pull distance of 80px\n setPullDistance(pullDist);\n }\n }, [isPulling, isRefreshing]);\n\n const handleTouchEnd = useCallback(() => {\n if (pullDistance > 60 && !isRefreshing) {\n handleRefresh();\n } else {\n setIsPulling(false);\n setPullDistance(0);\n }\n }, [pullDistance, isRefreshing, handleRefresh]);\n\n // Add touch event listeners\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n container.addEventListener('touchstart', handleTouchStart, { passive: false });\n container.addEventListener('touchmove', handleTouchMove, { passive: false });\n container.addEventListener('touchend', handleTouchEnd, { passive: false });\n\n return () => {\n container.removeEventListener('touchstart', handleTouchStart);\n container.removeEventListener('touchmove', handleTouchMove);\n container.removeEventListener('touchend', handleTouchEnd);\n };\n }, [handleTouchStart, handleTouchMove, handleTouchEnd]);\n\n // Type-safe outlet data\n const outletData = outlet as any;\n const articlesData = articles as any[];\n\n\n // Show loading state\n if (outletLoading) {\n return (\n
\n
\n

Loading

\n
\n
\n );\n }\n\n // Show not found state\n if (!outlet) {\n return (\n
\n
\n

Outlet not found

\n

The requested outlet does not exist.

\n
\n
\n );\n }\n\n const handleSearch = (query: string) => {\n setSearchQuery(query);\n };\n\n const handleTitleClick = () => {\n // Navigate to home with the outlet's category selected\n const category = outletData?.category || 'people';\n setLocation(`/?category=${category}`);\n };\n\n const handleBackClick = () => {\n // Navigate back to home with the outlet's category selected\n const category = outletData?.category || 'people';\n setLocation(`/?category=${category}`);\n };\n\n return (\n
\n {/* Main content with slide transition */}\n
\n
\n {/* Pull-to-refresh indicator */}\n {(isPulling || isRefreshing) && (\n
\n
\n \n \n {isRefreshing ? '새로고침 중...' : pullDistance > 60 ? '놓으면 새로고침' : '아래로 당겨서 새로고침'}\n \n
\n
\n )}\n\n {/* Fixed Profile Header - now at top */}\n
\n setIsSearchOpen(true)}\n selectedLanguage={selectedLanguage}\n onLanguageChange={setSelectedLanguage}\n onLoginClick={() => console.log('Login clicked')}\n />\n
\n\n
\n {/* Articles feed */}\n
\n \n {/* View mode toggle */}\n
\n

Latest Articles

\n
\n setViewMode('card')}\n data-testid=\"button-card-view\"\n >\n \n \n setViewMode('list')}\n data-testid=\"button-list-view\"\n >\n \n \n
\n
\n \n {articlesLoading ? (\n
\n

Loading articles...

\n
\n ) : (\n
\n {(() => {\n // For Palantir outlet, mix ads with articles like YouTube\n if (outletId === 'palantir') {\n const regularArticles = articlesData.filter((article: any) => article.isScraped !== 2);\n const ads = articlesData.filter((article: any) => article.isScraped === 2);\n const articlesWithAds = [];\n \n let adIndex = 0;\n \n // Insert articles and ads: add an ad after every 3 articles\n for (let i = 0; i < regularArticles.length; i++) {\n articlesWithAds.push({\n ...regularArticles[i],\n isAd: false\n });\n \n // Insert ad after every 3 articles (and we have ads available)\n if ((i + 1) % 3 === 0 && ads.length > 0) {\n articlesWithAds.push({\n ...ads[adIndex % ads.length],\n isAd: true\n });\n adIndex++;\n }\n }\n \n return articlesWithAds.map((item: any, index: number) => (\n {\n if (item.isAd) {\n // For ads, open external URL instead of navigating to article\n const newWindow = window.open('https://investing.com', '_blank', 'noopener,noreferrer');\n if (newWindow) newWindow.opener = null;\n } else {\n setLocation(`/article/${id}`);\n }\n }}\n className=\"w-full\"\n isAd={item.isAd}\n tags={item.tags || []}\n index={index}\n variant={viewMode}\n />\n ));\n } else {\n // For other outlets, show articles normally\n return articlesData.map((article: any, index: number) => (\n setLocation(`/article/${id}`)}\n className=\"w-full\"\n tags={article.tags || []}\n index={index}\n variant={viewMode}\n />\n ));\n }\n })()}\n
\n )}\n \n {articlesData.length === 0 && !articlesLoading && (\n
\n

No articles available yet.

\n
\n )}\n
\n
\n
\n
\n\n {/* Bottom Navigation Bar - Always fixed at bottom */}\n \n \n {/* Search Overlay positioned to slide in from right */}\n setIsSearchOpen(false)}\n onArticleClick={(id) => setLocation(`/article/${id}`)}\n searchResults={searchResults as any}\n onSearch={handleSearch}\n />\n
\n );\n}","size_bytes":12623},"client/src/pages/not-found.tsx":{"content":"import { Card, CardContent } from \"@/components/ui/card\";\nimport { AlertCircle } from \"lucide-react\";\n\nexport default function NotFound() {\n return (\n
\n \n \n
\n \n

404 Page Not Found

\n
\n\n

\n Did you forget to add the page to the router?\n

\n
\n
\n
\n );\n}\n","size_bytes":711},"client/src/components/examples/ArticleCard.tsx":{"content":"import ArticleCard from '../ArticleCard';\n\nexport default function ArticleCardExample() {\n return (\n
\n console.log('Article clicked:', id)}\n />\n
\n );\n}","size_bytes":671},"client/src/components/examples/ArticleDetail.tsx":{"content":"import ArticleDetail from '../ArticleDetail';\n\nexport default function ArticleDetailExample() {\n return (\n
\n console.log('Previous article')}\n onNextArticle={() => console.log('Next article')}\n hasPrevious={true}\n hasNext={true}\n />\n
\n );\n}","size_bytes":2200},"client/src/components/examples/CategoryTabs.tsx":{"content":"import CategoryTabs from '../CategoryTabs';\n\nexport default function CategoryTabsExample() {\n const categories = [\n { id: 'all', name: 'All', count: 15 },\n { id: 'people', name: 'People', count: 6 },\n { id: 'topics', name: 'Topics', count: 4 },\n { id: 'companies', name: 'Companies', count: 5 },\n ];\n\n return (\n console.log('Category changed to:', id)}\n />\n );\n}","size_bytes":487},"client/src/components/examples/MobileHeader.tsx":{"content":"import MobileHeader from '../MobileHeader';\n\nexport default function MobileHeaderExample() {\n return (\n console.log('Search clicked')}\n selectedLanguage=\"en\"\n onLanguageChange={(lang) => console.log('Language changed to:', lang)}\n onProfileClick={() => console.log('Profile clicked')}\n />\n );\n}","size_bytes":358},"client/src/components/examples/OutletCard.tsx":{"content":"import OutletCard from '../OutletCard';\n\nexport default function OutletCardExample() {\n return (\n
\n console.log('Outlet clicked:', id)}\n />\n
\n );\n}","size_bytes":498},"client/src/components/examples/OutletProfile.tsx":{"content":"import OutletProfile from '../OutletProfile';\n\nexport default function OutletProfileExample() {\n return (\n
\n \n \n
\n

Sticky Header Version:

\n \n
\n
\n );\n}","size_bytes":1208},"client/src/components/examples/SearchOverlay.tsx":{"content":"import { useState } from 'react';\nimport SearchOverlay from '../SearchOverlay';\nimport { Button } from '@/components/ui/button';\n\nexport default function SearchOverlayExample() {\n const [isOpen, setIsOpen] = useState(false);\n \n const mockResults = [\n {\n id: '1',\n title: 'Jacob Robert Steeves to Speak at dAI Conference in Seoul',\n summary: 'Co-founder of Bittensor will discuss decentralized AI and the TAO token economy.',\n category: 'People',\n outletName: 'Bittensor Focus',\n publishedAt: new Date('2024-09-22T09:30:00'),\n },\n {\n id: '2',\n title: 'Alpha Sigma Capital Publishes Report on Bittensor',\n summary: 'In-depth analysis of the neural internet model and market implications.',\n category: 'Topics',\n outletName: 'Crypto Insights',\n publishedAt: new Date('2024-09-22T11:15:00'),\n },\n ];\n\n return (\n
\n \n setIsOpen(false)}\n onArticleClick={(id) => console.log('Article clicked:', id)}\n searchResults={mockResults}\n onSearch={(query) => console.log('Search query:', query)}\n />\n
\n );\n}","size_bytes":1260},"client/src/components/examples/SwipeableCarousel.tsx":{"content":"import SwipeableCarousel from '../SwipeableCarousel';\nimport ArticleCard from '../ArticleCard';\n\nexport default function SwipeableCarouselExample() {\n const items = [\n {\n id: '1',\n content: (\n console.log('Article clicked:', id)}\n />\n ),\n },\n {\n id: '2',\n content: (\n console.log('Article clicked:', id)}\n />\n ),\n },\n {\n id: '3',\n content: (\n console.log('Article clicked:', id)}\n />\n ),\n },\n ];\n\n return (\n
\n \n
\n );\n}","size_bytes":1748},"client/src/components/ui/accordion.tsx":{"content":"import * as React from \"react\"\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\"\nimport { ChevronDown } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Accordion = AccordionPrimitive.Root\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAccordionItem.displayName = \"AccordionItem\"\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n svg]:rotate-180\",\n className\n )}\n {...props}\n >\n {children}\n \n \n \n))\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n
{children}
\n \n))\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n","size_bytes":1977},"client/src/components/ui/alert-dialog.tsx":{"content":"import * as React from \"react\"\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\nconst AlertDialog = AlertDialogPrimitive.Root\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n \n))\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nAlertDialogHeader.displayName = \"AlertDialogHeader\"\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nAlertDialogFooter.displayName = \"AlertDialogFooter\"\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n}\n","size_bytes":4420},"client/src/components/ui/alert.tsx":{"content":"import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes & VariantProps\n>(({ className, variant, ...props }, ref) => (\n \n))\nAlert.displayName = \"Alert\"\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes\n>(({ className, ...props }, ref) => (\n \n))\nAlertTitle.displayName = \"AlertTitle\"\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes\n>(({ className, ...props }, ref) => (\n \n))\nAlertDescription.displayName = \"AlertDescription\"\n\nexport { Alert, AlertTitle, AlertDescription }\n","size_bytes":1584},"client/src/components/ui/aspect-ratio.tsx":{"content":"import * as AspectRatioPrimitive from \"@radix-ui/react-aspect-ratio\"\n\nconst AspectRatio = AspectRatioPrimitive.Root\n\nexport { AspectRatio }\n","size_bytes":140},"client/src/components/ui/avatar.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Avatar = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAvatar.displayName = AvatarPrimitive.Root.displayName\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAvatarImage.displayName = AvatarPrimitive.Image.displayName\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName\n\nexport { Avatar, AvatarImage, AvatarFallback }\n","size_bytes":1605},"client/src/components/ui/badge.tsx":{"content":"import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n // Whitespace-nowrap: Badges should never wrap.\n \"whitespace-nowrap inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\" +\n \" hover-elevate \" ,\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground shadow-xs\",\n secondary: \"border-transparent bg-secondary text-secondary-foreground\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground shadow-xs\",\n\n outline: \" border [border-color:var(--badge-outline)] shadow-xs\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n)\n\nexport interface BadgeProps\n extends React.HTMLAttributes,\n VariantProps {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n
\n );\n}\n\nexport { Badge, badgeVariants }\n","size_bytes":1202},"client/src/components/ui/breadcrumb.tsx":{"content":"import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { ChevronRight, MoreHorizontal } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Breadcrumb = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<\"nav\"> & {\n separator?: React.ReactNode\n }\n>(({ ...props }, ref) =>
\n \n )\n})\nChartContainer.displayName = \"Chart\"\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nconst ChartTooltipContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }\n>(\n (\n {\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n },\n ref\n ) => {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n
\n {labelFormatter(value, payload)}\n
\n )\n }\n\n if (!value) {\n return null\n }\n\n return
{value}
\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n \n {!nestLabel ? tooltipLabel : null}\n
\n {payload.map((item, index) => {\n const key = `${nameKey || item.name || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor = color || item.payload.fill || item.color\n\n return (\n svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n \n ) : (\n !hideIndicator && (\n \n )\n )}\n \n
\n {nestLabel ? tooltipLabel : null}\n \n {itemConfig?.label || item.name}\n \n
\n {item.value && (\n \n {item.value.toLocaleString()}\n \n )}\n
\n \n )}\n
\n )\n })}\n
\n
\n )\n }\n)\nChartTooltipContent.displayName = \"ChartTooltip\"\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nconst ChartLegendContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<\"div\"> &\n Pick & {\n hideIcon?: boolean\n nameKey?: string\n }\n>(\n (\n { className, hideIcon = false, payload, verticalAlign = \"bottom\", nameKey },\n ref\n ) => {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n \n {payload.map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n \n ) : (\n \n )}\n {itemConfig?.label}\n \n )\n })}\n \n )\n }\n)\nChartLegendContent.displayName = \"ChartLegend\"\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n","size_bytes":10481},"client/src/components/ui/checkbox.tsx":{"content":"import * as React from \"react\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\nimport { Check } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Checkbox = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n \n \n))\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n","size_bytes":1056},"client/src/components/ui/collapsible.tsx":{"content":"\"use client\"\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\"\n\nconst Collapsible = CollapsiblePrimitive.Root\n\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger\n\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n","size_bytes":329},"client/src/components/ui/command.tsx":{"content":"import * as React from \"react\"\nimport { type DialogProps } from \"@radix-ui/react-dialog\"\nimport { Command as CommandPrimitive } from \"cmdk\"\nimport { Search } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Dialog, DialogContent } from \"@/components/ui/dialog\"\n\nconst Command = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nCommand.displayName = CommandPrimitive.displayName\n\nconst CommandDialog = ({ children, ...props }: DialogProps) => {\n return (\n \n \n \n {children}\n \n \n \n )\n}\n\nconst CommandInput = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n
\n \n \n
\n))\n\nCommandInput.displayName = CommandPrimitive.Input.displayName\n\nconst CommandList = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\n\nCommandList.displayName = CommandPrimitive.List.displayName\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>((props, ref) => (\n \n))\n\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\n\nCommandGroup.displayName = CommandPrimitive.Group.displayName\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName\n\nconst CommandItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\n\nCommandItem.displayName = CommandPrimitive.Item.displayName\n\nconst CommandShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes) => {\n return (\n \n )\n}\nCommandShortcut.displayName = \"CommandShortcut\"\n\nexport {\n Command,\n CommandDialog,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n}\n","size_bytes":4885},"client/src/components/ui/context-menu.tsx":{"content":"import * as React from \"react\"\nimport * as ContextMenuPrimitive from \"@radix-ui/react-context-menu\"\nimport { Check, ChevronRight, Circle } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst ContextMenu = ContextMenuPrimitive.Root\n\nconst ContextMenuTrigger = ContextMenuPrimitive.Trigger\n\nconst ContextMenuGroup = ContextMenuPrimitive.Group\n\nconst ContextMenuPortal = ContextMenuPrimitive.Portal\n\nconst ContextMenuSub = ContextMenuPrimitive.Sub\n\nconst ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup\n\nconst ContextMenuSubTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n \n {children}\n \n \n))\nContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName\n\nconst ContextMenuSubContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName\n\nconst ContextMenuContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n))\nContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName\n\nconst ContextMenuItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName\n\nconst ContextMenuCheckboxItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, checked, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nContextMenuCheckboxItem.displayName =\n ContextMenuPrimitive.CheckboxItem.displayName\n\nconst ContextMenuRadioItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName\n\nconst ContextMenuLabel = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName\n\nconst ContextMenuSeparator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName\n\nconst ContextMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes) => {\n return (\n \n )\n}\nContextMenuShortcut.displayName = \"ContextMenuShortcut\"\n\nexport {\n ContextMenu,\n ContextMenuTrigger,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuCheckboxItem,\n ContextMenuRadioItem,\n ContextMenuLabel,\n ContextMenuSeparator,\n ContextMenuShortcut,\n ContextMenuGroup,\n ContextMenuPortal,\n ContextMenuSub,\n ContextMenuSubContent,\n ContextMenuSubTrigger,\n ContextMenuRadioGroup,\n}\n","size_bytes":7428},"client/src/components/ui/dialog.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\"\nimport { X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Dialog = DialogPrimitive.Root\n\nconst DialogTrigger = DialogPrimitive.Trigger\n\nconst DialogPortal = DialogPrimitive.Portal\n\nconst DialogClose = DialogPrimitive.Close\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName\n\nconst DialogContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n {children}\n \n \n Close\n \n \n \n))\nDialogContent.displayName = DialogPrimitive.Content.displayName\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nDialogHeader.displayName = \"DialogHeader\"\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nDialogFooter.displayName = \"DialogFooter\"\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDialogTitle.displayName = DialogPrimitive.Title.displayName\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDialogDescription.displayName = DialogPrimitive.Description.displayName\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n}\n","size_bytes":3848},"client/src/components/ui/drawer.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport { Drawer as DrawerPrimitive } from \"vaul\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Drawer = ({\n shouldScaleBackground = true,\n ...props\n}: React.ComponentProps) => (\n \n)\nDrawer.displayName = \"Drawer\"\n\nconst DrawerTrigger = DrawerPrimitive.Trigger\n\nconst DrawerPortal = DrawerPrimitive.Portal\n\nconst DrawerClose = DrawerPrimitive.Close\n\nconst DrawerOverlay = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName\n\nconst DrawerContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n
\n {children}\n \n \n))\nDrawerContent.displayName = \"DrawerContent\"\n\nconst DrawerHeader = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nDrawerHeader.displayName = \"DrawerHeader\"\n\nconst DrawerFooter = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nDrawerFooter.displayName = \"DrawerFooter\"\n\nconst DrawerTitle = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDrawerTitle.displayName = DrawerPrimitive.Title.displayName\n\nconst DrawerDescription = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDrawerDescription.displayName = DrawerPrimitive.Description.displayName\n\nexport {\n Drawer,\n DrawerPortal,\n DrawerOverlay,\n DrawerTrigger,\n DrawerClose,\n DrawerContent,\n DrawerHeader,\n DrawerFooter,\n DrawerTitle,\n DrawerDescription,\n}\n","size_bytes":3021},"client/src/components/ui/dropdown-menu.tsx":{"content":"import * as React from \"react\"\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\"\nimport { Check, ChevronRight, Circle } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst DropdownMenu = DropdownMenuPrimitive.Root\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n \n {children}\n \n \n))\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, sideOffset = 4, ...props }, ref) => (\n \n \n \n))\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, checked, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes) => {\n return (\n \n )\n}\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\"\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n}\n","size_bytes":7609},"client/src/components/ui/form.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport {\n Controller,\n FormProvider,\n useFormContext,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Label } from \"@/components/ui/label\"\n\nconst Form = FormProvider\n\ntype FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath = FieldPath\n> = {\n name: TName\n}\n\nconst FormFieldContext = React.createContext(\n {} as FormFieldContextValue\n)\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath = FieldPath\n>({\n ...props\n}: ControllerProps) => {\n return (\n \n \n \n )\n}\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext)\n const itemContext = React.useContext(FormItemContext)\n const { getFieldState, formState } = useFormContext()\n\n const fieldState = getFieldState(fieldContext.name, formState)\n\n if (!fieldContext) {\n throw new Error(\"useFormField should be used within \")\n }\n\n const { id } = itemContext\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n }\n}\n\ntype FormItemContextValue = {\n id: string\n}\n\nconst FormItemContext = React.createContext(\n {} as FormItemContextValue\n)\n\nconst FormItem = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes\n>(({ className, ...props }, ref) => {\n const id = React.useId()\n\n return (\n \n
\n \n )\n})\nFormItem.displayName = \"FormItem\"\n\nconst FormLabel = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField()\n\n return (\n \n )\n})\nFormLabel.displayName = \"FormLabel\"\n\nconst FormControl = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField()\n\n return (\n \n )\n})\nFormControl.displayName = \"FormControl\"\n\nconst FormDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes\n>(({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField()\n\n return (\n \n )\n})\nFormDescription.displayName = \"FormDescription\"\n\nconst FormMessage = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes\n>(({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField()\n const body = error ? String(error?.message ?? \"\") : children\n\n if (!body) {\n return null\n }\n\n return (\n \n {body}\n

\n )\n})\nFormMessage.displayName = \"FormMessage\"\n\nexport {\n useFormField,\n Form,\n FormItem,\n FormLabel,\n FormControl,\n FormDescription,\n FormMessage,\n FormField,\n}\n","size_bytes":4120},"client/src/components/ui/hover-card.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst HoverCard = HoverCardPrimitive.Root\n\nconst HoverCardTrigger = HoverCardPrimitive.Trigger\n\nconst HoverCardContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n \n))\nHoverCardContent.displayName = HoverCardPrimitive.Content.displayName\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\n","size_bytes":1251},"client/src/components/ui/input-otp.tsx":{"content":"import * as React from \"react\"\nimport { OTPInput, OTPInputContext } from \"input-otp\"\nimport { Dot } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst InputOTP = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, containerClassName, ...props }, ref) => (\n \n))\nInputOTP.displayName = \"InputOTP\"\n\nconst InputOTPGroup = React.forwardRef<\n React.ElementRef<\"div\">,\n React.ComponentPropsWithoutRef<\"div\">\n>(({ className, ...props }, ref) => (\n
\n))\nInputOTPGroup.displayName = \"InputOTPGroup\"\n\nconst InputOTPSlot = React.forwardRef<\n React.ElementRef<\"div\">,\n React.ComponentPropsWithoutRef<\"div\"> & { index: number }\n>(({ index, className, ...props }, ref) => {\n const inputOTPContext = React.useContext(OTPInputContext)\n const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]\n\n return (\n \n {char}\n {hasFakeCaret && (\n
\n
\n
\n )}\n
\n )\n})\nInputOTPSlot.displayName = \"InputOTPSlot\"\n\nconst InputOTPSeparator = React.forwardRef<\n React.ElementRef<\"div\">,\n React.ComponentPropsWithoutRef<\"div\">\n>(({ ...props }, ref) => (\n
\n \n
\n))\nInputOTPSeparator.displayName = \"InputOTPSeparator\"\n\nexport { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }\n","size_bytes":2154},"client/src/components/ui/input.tsx":{"content":"import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Input = React.forwardRef>(\n ({ className, type, ...props }, ref) => {\n // h-9 to match icon buttons and default buttons.\n return (\n \n )\n }\n)\nInput.displayName = \"Input\"\n\nexport { Input }\n","size_bytes":844},"client/src/components/ui/label.tsx":{"content":"import * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n)\n\nconst Label = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef &\n VariantProps\n>(({ className, ...props }, ref) => (\n \n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n","size_bytes":710},"client/src/components/ui/menubar.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\"\nimport { Check, ChevronRight, Circle } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction MenubarMenu({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarGroup({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarPortal({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarRadioGroup({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nfunction MenubarSub({\n ...props\n}: React.ComponentProps) {\n return \n}\n\nconst Menubar = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubar.displayName = MenubarPrimitive.Root.displayName\n\nconst MenubarTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n \n {children}\n \n \n))\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName\n\nconst MenubarSubContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName\n\nconst MenubarContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(\n (\n { className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props },\n ref\n ) => (\n \n \n \n )\n)\nMenubarContent.displayName = MenubarPrimitive.Content.displayName\n\nconst MenubarItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nMenubarItem.displayName = MenubarPrimitive.Item.displayName\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, checked, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName\n\nconst MenubarRadioItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n \n \n \n {children}\n \n))\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName\n\nconst MenubarLabel = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n \n))\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName\n\nconst MenubarSeparator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName\n\nconst MenubarShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes) => {\n return (\n \n )\n}\nMenubarShortcut.displayname = \"MenubarShortcut\"\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarItem,\n MenubarSeparator,\n MenubarLabel,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarPortal,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarGroup,\n MenubarSub,\n MenubarShortcut,\n}\n","size_bytes":8605},"client/src/components/ui/navigation-menu.tsx":{"content":"import * as React from \"react\"\nimport * as NavigationMenuPrimitive from \"@radix-ui/react-navigation-menu\"\nimport { cva } from \"class-variance-authority\"\nimport { ChevronDown } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst NavigationMenu = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n {children}\n \n \n))\nNavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName\n\nconst NavigationMenuList = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nNavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName\n\nconst NavigationMenuItem = NavigationMenuPrimitive.Item\n\nconst navigationMenuTriggerStyle = cva(\n \"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-accent-foreground data-[state=open]:bg-accent/50 data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent\"\n)\n\nconst NavigationMenuTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n {children}{\" \"}\n \n \n))\nNavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName\n\nconst NavigationMenuContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nNavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName\n\nconst NavigationMenuLink = NavigationMenuPrimitive.Link\n\nconst NavigationMenuViewport = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n
\n \n
\n))\nNavigationMenuViewport.displayName =\n NavigationMenuPrimitive.Viewport.displayName\n\nconst NavigationMenuIndicator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n
\n \n))\nNavigationMenuIndicator.displayName =\n NavigationMenuPrimitive.Indicator.displayName\n\nexport {\n navigationMenuTriggerStyle,\n NavigationMenu,\n NavigationMenuList,\n NavigationMenuItem,\n NavigationMenuContent,\n NavigationMenuTrigger,\n NavigationMenuLink,\n NavigationMenuIndicator,\n NavigationMenuViewport,\n}\n","size_bytes":5128},"client/src/components/ui/pagination.tsx":{"content":"import * as React from \"react\"\nimport { ChevronLeft, ChevronRight, MoreHorizontal } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { ButtonProps, buttonVariants } from \"@/components/ui/button\"\n\nconst Pagination = ({ className, ...props }: React.ComponentProps<\"nav\">) => (\n \n)\nPagination.displayName = \"Pagination\"\n\nconst PaginationContent = React.forwardRef<\n HTMLUListElement,\n React.ComponentProps<\"ul\">\n>(({ className, ...props }, ref) => (\n \n))\nPaginationContent.displayName = \"PaginationContent\"\n\nconst PaginationItem = React.forwardRef<\n HTMLLIElement,\n React.ComponentProps<\"li\">\n>(({ className, ...props }, ref) => (\n
  • \n))\nPaginationItem.displayName = \"PaginationItem\"\n\ntype PaginationLinkProps = {\n isActive?: boolean\n} & Pick &\n React.ComponentProps<\"a\">\n\nconst PaginationLink = ({\n className,\n isActive,\n size = \"icon\",\n ...props\n}: PaginationLinkProps) => (\n \n)\nPaginationLink.displayName = \"PaginationLink\"\n\nconst PaginationPrevious = ({\n className,\n ...props\n}: React.ComponentProps) => (\n \n \n Previous\n \n)\nPaginationPrevious.displayName = \"PaginationPrevious\"\n\nconst PaginationNext = ({\n className,\n ...props\n}: React.ComponentProps) => (\n \n Next\n \n \n)\nPaginationNext.displayName = \"PaginationNext\"\n\nconst PaginationEllipsis = ({\n className,\n ...props\n}: React.ComponentProps<\"span\">) => (\n \n \n More pages\n \n)\nPaginationEllipsis.displayName = \"PaginationEllipsis\"\n\nexport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n}\n","size_bytes":2751},"client/src/components/ui/popover.tsx":{"content":"import * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\n\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n \n \n \n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n","size_bytes":1280},"client/src/components/ui/progress.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Progress = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, value, ...props }, ref) => (\n \n \n \n))\nProgress.displayName = ProgressPrimitive.Root.displayName\n\nexport { Progress }\n","size_bytes":791},"client/src/components/ui/radio-group.tsx":{"content":"import * as React from \"react\"\nimport * as RadioGroupPrimitive from \"@radix-ui/react-radio-group\"\nimport { Circle } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst RadioGroup = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => {\n return (\n \n )\n})\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName\n\nconst RadioGroupItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => {\n return (\n \n \n \n \n \n )\n})\nRadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName\n\nexport { RadioGroup, RadioGroupItem }\n","size_bytes":1467},"client/src/components/ui/resizable.tsx":{"content":"\"use client\"\n\nimport { GripVertical } from \"lucide-react\"\nimport * as ResizablePrimitive from \"react-resizable-panels\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst ResizablePanelGroup = ({\n className,\n ...props\n}: React.ComponentProps) => (\n \n)\n\nconst ResizablePanel = ResizablePrimitive.Panel\n\nconst ResizableHandle = ({\n withHandle,\n className,\n ...props\n}: React.ComponentProps & {\n withHandle?: boolean\n}) => (\n div]:rotate-90\",\n className\n )}\n {...props}\n >\n {withHandle && (\n
    \n \n
    \n )}\n \n)\n\nexport { ResizablePanelGroup, ResizablePanel, ResizableHandle }\n","size_bytes":1723},"client/src/components/ui/scroll-area.tsx":{"content":"import * as React from \"react\"\nimport * as ScrollAreaPrimitive from \"@radix-ui/react-scroll-area\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst ScrollArea = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n {children}\n \n \n \n \n))\nScrollArea.displayName = ScrollAreaPrimitive.Root.displayName\n\nconst ScrollBar = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, orientation = \"vertical\", ...props }, ref) => (\n \n \n \n))\nScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName\n\nexport { ScrollArea, ScrollBar }\n","size_bytes":1642},"client/src/components/ui/select.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as SelectPrimitive from \"@radix-ui/react-select\"\nimport { Check, ChevronDown, ChevronUp } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Select = SelectPrimitive.Root\n\nconst SelectGroup = SelectPrimitive.Group\n\nconst SelectValue = SelectPrimitive.Value\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n span]:line-clamp-1\",\n className\n )}\n {...props}\n >\n {children}\n \n \n \n \n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n))\nSelectScrollDownButton.displayName =\n SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, position = \"popper\", ...props }, ref) => (\n \n \n \n \n {children}\n \n \n \n \n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, children, ...props }, ref) => (\n \n \n \n \n \n \n\n {children}\n \n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n}\n","size_bytes":5741},"client/src/components/ui/separator.tsx":{"content":"import * as React from \"react\"\nimport * as SeparatorPrimitive from \"@radix-ui/react-separator\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Separator = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(\n (\n { className, orientation = \"horizontal\", decorative = true, ...props },\n ref\n ) => (\n \n )\n)\nSeparator.displayName = SeparatorPrimitive.Root.displayName\n\nexport { Separator }\n","size_bytes":756},"client/src/components/ui/sheet.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport * as SheetPrimitive from \"@radix-ui/react-dialog\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Sheet = SheetPrimitive.Root\n\nconst SheetTrigger = SheetPrimitive.Trigger\n\nconst SheetClose = SheetPrimitive.Close\n\nconst SheetPortal = SheetPrimitive.Portal\n\nconst SheetOverlay = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nSheetOverlay.displayName = SheetPrimitive.Overlay.displayName\n\nconst sheetVariants = cva(\n \"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500\",\n {\n variants: {\n side: {\n top: \"inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top\",\n bottom:\n \"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom\",\n left: \"inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm\",\n right:\n \"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm\",\n },\n },\n defaultVariants: {\n side: \"right\",\n },\n }\n)\n\ninterface SheetContentProps\n extends React.ComponentPropsWithoutRef,\n VariantProps {}\n\nconst SheetContent = React.forwardRef<\n React.ElementRef,\n SheetContentProps\n>(({ side = \"right\", className, children, ...props }, ref) => (\n \n \n \n {children}\n \n \n Close\n \n \n \n))\nSheetContent.displayName = SheetPrimitive.Content.displayName\n\nconst SheetHeader = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nSheetHeader.displayName = \"SheetHeader\"\n\nconst SheetFooter = ({\n className,\n ...props\n}: React.HTMLAttributes) => (\n \n)\nSheetFooter.displayName = \"SheetFooter\"\n\nconst SheetTitle = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nSheetTitle.displayName = SheetPrimitive.Title.displayName\n\nconst SheetDescription = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n))\nSheetDescription.displayName = SheetPrimitive.Description.displayName\n\nexport {\n Sheet,\n SheetPortal,\n SheetOverlay,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","size_bytes":4281},"client/src/components/ui/sidebar.tsx":{"content":"\"use client\"\n\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, VariantProps } from \"class-variance-authority\"\nimport { PanelLeftIcon } from \"lucide-react\"\n\nimport { useIsMobile } from \"@/hooks/use-mobile\"\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { Input } from \"@/components/ui/input\"\nimport { Separator } from \"@/components/ui/separator\"\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from \"@/components/ui/sheet\"\nimport { Skeleton } from \"@/components/ui/skeleton\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\"\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = \"16rem\"\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\n\ntype SidebarContextProps = {\n state: \"expanded\" | \"collapsed\"\n open: boolean\n setOpen: (open: boolean) => void\n openMobile: boolean\n setOpenMobile: (open: boolean) => void\n isMobile: boolean\n toggleSidebar: () => void\n}\n\nconst SidebarContext = React.createContext(null)\n\nfunction useSidebar() {\n const context = React.useContext(SidebarContext)\n if (!context) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\")\n }\n\n return context\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n defaultOpen?: boolean\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}) {\n const isMobile = useIsMobile()\n const [openMobile, setOpenMobile] = React.useState(false)\n\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n const [_open, _setOpen] = React.useState(defaultOpen)\n const open = openProp ?? _open\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value\n if (setOpenProp) {\n setOpenProp(openState)\n } else {\n _setOpen(openState)\n }\n\n // This sets the cookie to keep the sidebar state.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\n },\n [setOpenProp, open]\n )\n\n // Helper to toggle the sidebar.\n const toggleSidebar = React.useCallback(() => {\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)\n }, [isMobile, setOpen, setOpenMobile])\n\n // Adds a keyboard shortcut to toggle the sidebar.\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\n event.preventDefault()\n toggleSidebar()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [toggleSidebar])\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? \"expanded\" : \"collapsed\"\n\n const contextValue = React.useMemo(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]\n )\n\n return (\n \n \n \n {children}\n
  • \n \n \n )\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offcanvas\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\"\n variant?: \"sidebar\" | \"floating\" | \"inset\"\n collapsible?: \"offcanvas\" | \"icon\" | \"none\"\n}) {\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\n\n if (collapsible === \"none\") {\n return (\n \n {children}\n
    \n )\n }\n\n if (isMobile) {\n return (\n \n button]:hidden\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as React.CSSProperties\n }\n side={side}\n >\n \n Sidebar\n Displays the mobile sidebar.\n \n
    {children}
    \n \n
    \n )\n }\n\n return (\n
    \n
    \n \n )\n}\n\nfunction SidebarTrigger({\n className,\n onClick,\n ...props\n}: React.ComponentProps) {\n const { toggleSidebar } = useSidebar()\n\n return (\n {\n onClick?.(event)\n toggleSidebar()\n }}\n {...props}\n >\n \n Toggle Sidebar\n \n )\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\n const { toggleSidebar } = useSidebar()\n\n // Note: Tailwind v3.4 doesn't support \"in-\" selectors. So the rail won't work perfectly.\n return (\n