From db4e15e3ec5e07da2e75b9cc4b0a44f1c95263b5 Mon Sep 17 00:00:00 2001 From: sopaco Date: Sun, 28 Sep 2025 21:37:35 +0800 Subject: [PATCH] generate docs by litho (deepwiki-rs) generate docs by litho (deepwiki-rs) --- .../0010b029ee6abdf494fefa6d787c8dda.json | 88 + .../0174f7dcabd104d574f296f0d921d6bf.json | 200 + .../0195076381e69d609268f3678aa827f7.json | 266 + .../0206557cf8509a0ecac7c050730a8607.json | 39 + .../037c011f098a1e80ee87c03e4ac4f69f.json | 201 + .../06cf4fa5f16ef861546ccced9f7b6b25.json | 128 + .../08b41b312bd398cb5f94da5a6a5d36a7.json | 39 + .../09128581bb8c55de6f7da222ea21b400.json | 83 + .../09d2b7bca284cb3e93d422854df5efc1.json | 86 + .../0a18f7ab09a702175ce21710efa77554.json | 121 + .../0a91b530f0180f66fddbf22980c585f4.json | 190 + .../0bb4ab47c07e0a8fc173883264e45f26.json | 115 + .../0bb6effe1ad867e8004bd2ac0ffe1432.json | 40 + .../0c2760672116db4e9f3ed65c8cea377c.json | 77 + .../0d72ea10d9150578f945553974f094de.json | 131 + .../0fbc1633e603348451135fc394ec54a2.json | 72 + .../11369782ecef4ec381ae2141112bce2b.json | 63 + .../11eb06cd23d3dc1bee9ce05ff404b6ef.json | 47 + .../126632c0362c17cbd5258dbef4bd5bcc.json | 68 + .../12aa64503c44747dbccc4b8a9b50c925.json | 105 + .../13d3311c57a4942491dd73a43a41311e.json | 144 + .../13d811cb5f01480847f5763393ca3e29.json | 83 + .../143649b2e7df919a5a61a676170f594b.json | 89 + .../1445c7ab0cb786bdd8cdfbf520276166.json | 159 + .../16d65f6a97cf7bb81899e8e9abf10d32.json | 77 + .../184bb05e0d17bd85030e0cd1ab8da47d.json | 40 + .../1998bbf6a543ea876c074b34b7545191.json | 78 + .../1a1a9b30ee6d8ae7b1da717e5300e481.json | 106 + .../1aff5469f8999556d9085f189b75755b.json | 50 + .../1b754b203996771c5a6dd71534bbdc15.json | 77 + .../1cfacab2cbc2c6bd94c7d78ce762a3eb.json | 251 + .../1d1497c3971d256c8d887048a62f3ed9.json | 66 + .../1f3c0dc04e63c9306d560b83929bfdef.json | 40 + .../1f59c370079b48d193d6a414f8cec863.json | 173 + .../1fcf292b999dccf0c8214ea316144918.json | 158 + .../21f7ea14dab5aaddb082bf74224314e0.json | 50 + .../2384216ebbf7041d48073d079243f7bb.json | 173 + .../25217391845516e5b71dc0101c6b2cae.json | 48 + .../2586645484a5567b61efc57503b2c3a0.json | 85 + .../26381acd2859d55167419934fb8212e0.json | 183 + .../27ca3638a157126364647d701beedbb0.json | 114 + .../28ca872aad808bbe93155e72c9cad232.json | 81 + .../28ff941c3c855b21c493373ddec83237.json | 82 + .../2964aa5f4475545302528c3e59b9be6d.json | 70 + .../2c8e64968ba6cdc2c3960d8d9081704a.json | 39 + .../2dd6a833ecceec8cb69bc89759a5debe.json | 92 + .../2ed047563eba803562f7491c91607abd.json | 42 + .../302afdf662f68b6d1cbe3b6f2ac0c320.json | 155 + .../317264bc9a41525642223799077c4818.json | 76 + .../33036e527c7041f1d59d97031c90ab46.json | 93 + .../342836c19b10875183c4eb597d4130ad.json | 70 + .../34a006e9861ea50feae34bd3850e924a.json | 81 + .../3601d5b1a0cbbc7ae3a39665a71cc938.json | 110 + .../384468e60cfc1eb91df8f0f4dff09582.json | 61 + .../3a52713ea84e03bbcbc65df9bbebbe05.json | 110 + .../3a6c3b61af5a5ca06048c051e1cb4fdc.json | 150 + .../3ce2a51137321e383baab4d8660cb641.json | 80 + .../3d09d8e5ba7eeae9c7c8a362fdd5673b.json | 50 + .../3dc084d733458d35d323fcc4de0e37fb.json | 116 + .../3f03f24fcb16f0dcbb365762049970f1.json | 363 + .../3f28221975c41db1eee84e4d518e5805.json | 265 + .../407d1b0c806c69dd0e4f23770b0fd741.json | 72 + .../409faa45e7903f096fdb6535f11b4a99.json | 92 + .../4230e4241fbad156d9cd4ba191a62b35.json | 49 + .../4244b60930d605826ddec5305e747392.json | 127 + .../42a132f0aa9f8db040bde57dd56293d5.json | 122 + .../42c6c3b8b38361d0b870e0fd40c71928.json | 128 + .../431062a9c86b129c09193fcede2669c2.json | 202 + .../43e1e3e6bba003342ce2aee7ad187bcd.json | 131 + .../4495bdbcc08212704207f665b788462a.json | 67 + .../457b7b302d7f71e51e11ab1a7640eb42.json | 58 + .../45cb436521235e4d034a71e22730e6cf.json | 50 + .../45eec785a9d081d4337b1a060cee24d6.json | 75 + .../4690c42a7d2da0891ef9c1416e1c7273.json | 105 + .../48514e90f10df015b57da543b49c0bbc.json | 99 + .../4990d2a248b5115727059f32e1a3bd34.json | 93 + .../4ca53e004fa88b3e64b0a167212fe7c5.json | 43 + .../4dcaa642b6730282a912b5099ee87e53.json | 235 + .../4f7185e3eabcb3c804d621f9ddeb4e6d.json | 126 + .../501c146ce5aba3f2a64a6fd27f67b120.json | 154 + .../5064170bf87b00f6a19aafbdb3522d45.json | 87 + .../509778d785842a165f6ec9f0e18014a0.json | 40 + .../51362896b1facc80650e24ea8c5c785d.json | 41 + .../514d4c0b04d3d780ce01311309910cd8.json | 49 + .../53bacdb24378ff0ad9c4663c1b4e0fa7.json | 48 + .../5469f38188f245cce5d35a46f815b166.json | 67 + .../54dae1e05c3a4d3ee0f0e0df7f5317a8.json | 88 + .../54e89df6ef71b3e6a4c03591745171e6.json | 60 + .../5602eecf348eaeca4f0eb4632f85cbcb.json | 496 + .../566758005c7599d9c1887e14c77d54b4.json | 234 + .../57ab254f6508149592b0ffef9299d668.json | 47 + .../5812b5594d8525d3532de9b18e171f96.json | 84 + .../58b773ecbd9fd26592f36347631a3c29.json | 66 + .../5c768c8d6c8e6dd66ab215dce47b3f34.json | 48 + .../5d3e653fa78c2a1cdd0adff16b3ca232.json | 88 + .../5de2c8e6ae487ed907ad51fae5bbda30.json | 49 + .../5e9a3ba874f09a3229ccac54845fb3c8.json | 105 + .../5f9c5382a31c90a4968f7b418edc9099.json | 76 + .../62619e7ccab878642efc666b41a43eb5.json | 39 + .../63464ab4d38a6e724c67ffeea505b685.json | 123 + .../63b76c51282dec5d5db2219968bd5c99.json | 50 + .../65a4ded8f7b861f8d55aecf58fe0005e.json | 329 + .../6654b7f0e0b6315d59bea218097bda8b.json | 40 + .../66e11055ecfddc815b84ef74734c929e.json | 103 + .../67b0e101babd39897cdf5a26e51de157.json | 118 + .../684e37e171a28e045821f6dfba331a14.json | 61 + .../68d760b0d05eb65fa4348484009855df.json | 59 + .../696df1c6fca3fed85872b7040c31b6e9.json | 83 + .../6983fc30af9bc60b1b9af1ecd0e341f6.json | 180 + .../69e10635102689d195801f1a76d9360a.json | 144 + .../6b397ec9a37a982794b1c3f095d54c0e.json | 53 + .../6ccf5fd00ecfadf659131e813593fba4.json | 252 + .../70c09ce4a2a65332561a35b3ab6409ab.json | 86 + .../73344f222c4160af99c64c8e6f9ab7bd.json | 55 + .../733b0de1b59a3de709f1ecbeebe6d161.json | 88 + .../73d050d67c343cf40f2a74e819f39945.json | 59 + .../746257dfdfa6c6c10739c54c30e23a9f.json | 91 + .../746d48b27f27baf6c69b7a6718eb1a73.json | 40 + .../74bab31315a8960d4ce77b43dd344178.json | 50 + .../7769ebcdc6a484b55221c6cca454b36e.json | 58 + .../78520a548d6cdab7a2844f81cae51e22.json | 89 + .../786b69d3c396d1a070f35a9e9a2963fb.json | 38 + .../790984d1bbd9e6790c6f52e9614496fd.json | 123 + .../79722b9ff757abc80130ff5312ac93da.json | 39 + .../79fbfbb6c3d63c5b791ce454b00d698d.json | 95 + .../7a7bbd0b11c0e19b574ec3469947e912.json | 133 + .../7a8eeb4ad5e00605874269d4428161e8.json | 61 + .../7b5e8c15cf4078c8e4902404f0930d2f.json | 75 + .../7c3967eaf9f17960fef351271795f6f2.json | 120 + .../7c57c3051847bcdeafe165709195313e.json | 146 + .../7df3a7c345f93a2a645ccb03f339e3b2.json | 161 + .../7e0e8fef0131b7a0c87c87dfd1fe24a1.json | 104 + .../7e8a973c8b2a4d26fdecf2634da67d25.json | 72 + .../7ea084b580daec28f2d54c2d4d6b8221.json | 61 + .../7ef25265a87dc8901007c0def6dd9376.json | 42 + .../80b695228e7ab95081cf5571a6dc2f9a.json | 159 + .../80f61996e2d06022b495b4ba4b64b062.json | 106 + .../83682f524cb0e93138a59ce664e9aa41.json | 296 + .../83d05e12b628c2d7cd1d86f3007e94cb.json | 76 + .../849d3a6b45640b65396afd58695bf847.json | 84 + .../84cd79d365ba42093e6ee9a55a8ba055.json | 289 + .../860f2aef0ec434e6bf925a94c7a7aa79.json | 49 + .../8774bcabedc89de528bdab1b0eb158c2.json | 109 + .../87aade9efd624b66cc966003e2391c82.json | 159 + .../87d989544413a8099358bde45864e14f.json | 40 + .../88b1de4cfa45a27fbd0f96d11fb12a14.json | 129 + .../88c86ac5915868064de89650a69f65b2.json | 152 + .../89ff389b285cb8f201720a6bbde0927a.json | 93 + .../8a80f984693064e97840353555933f94.json | 146 + .../8b418c3361926337283c2a123284c5f2.json | 182 + .../8b50e08f39972e471eeff731e83dc8f8.json | 51 + .../8c3a3790eb2a9d2a2fe2f790fc5c2b79.json | 159 + .../8e292d9c80991a9f4ec647fd3faacef2.json | 178 + .../8f2b7f9a396fa7d8f831124619001714.json | 59 + .../8ff5bf46b5d12046d8fdc8053bc2c451.json | 133 + .../900b73675a2a8d1afd2c5c9d53c46131.json | 40 + .../909b5cb43cabaa97af93cea50a9d8474.json | 89 + .../909d78037190872fb1bae3181c9be40d.json | 49 + .../9174e34c1b67e246a67144e35bb94e48.json | 120 + .../926f094d2428a4cbfd5933b4669aca5f.json | 228 + .../9276c0d8316c8c6f81690e015657645f.json | 184 + .../929c919b226f8b99be92fee0aa9a04f2.json | 73 + .../940af1e923133707481c6b68a66b7748.json | 51 + .../952149d754cc18b71a69052679087887.json | 40 + .../9656ab0f2459c9bb839eb71bda5afab3.json | 97 + .../96d870b1a6b442d8bb70d367b08083e0.json | 107 + .../9a0c0aea81cc72cc13d6b8d1b3f1cce5.json | 70 + .../9a8a579a07ccbdfaca7eeda797409138.json | 187 + .../9afcc0a2aad7ba144d9071852e12dac1.json | 74 + .../9b2b0d80cfc15c7bc59ad686a9e90723.json | 73 + .../9cab669aef6cb0d35df819fd0dfd920b.json | 51 + .../9f00aa53bb19aeddcfc6da8590973776.json | 108 + .../a23fc67512b17b1feac5985b9692a7f2.json | 182 + .../a400b5d729bb04c7cd24a67f7eb77cee.json | 121 + .../a5c496dda132677abe0eb636ac9cfe0d.json | 39 + .../a637c5b39416f4ebdd06177531cab86a.json | 313 + .../a6608f266c742be633a355cdfd2d3db7.json | 102 + .../a6cb6ba582e164d7a7fc2c1f99150bb5.json | 223 + .../a72745de0a68a2a2e8f7ed4854312ce7.json | 88 + .../a733d5bbea0966fe77e752a458aed424.json | 68 + .../a9cb666db0a84608e1b88d30ff7c6cd1.json | 126 + .../aa5a4f69973c3b3787ca003a4abf79e9.json | 123 + .../aa668edc04d179f5ee42c2304e991e0a.json | 58 + .../ab1b0f4b4197fe537faf67a75318cfba.json | 204 + .../abbddff0d4ee559593fb7202b8d69b56.json | 127 + .../abf1f2badac95395e0086d153644ecd5.json | 101 + .../ad5591568fbf848ccc67c2f330d7e3a1.json | 61 + .../adcc64021e419e0c86e06f2bc3768e17.json | 129 + .../af4afc224c894109c3acc51738a7fc31.json | 101 + .../afd44f4486d4c637660b1e531ab6bd89.json | 99 + .../b21b6fe6400e3eb7598b2cc64511e74e.json | 61 + .../b24ca7810d9662bec32c2c4e492bc0f1.json | 98 + .../b25782644749a3853e2e6b2566861bc4.json | 83 + .../b43f713a3ab866458b74ecb4ade7d085.json | 57 + .../b4dff124eecfc611d49db5d9729c3e10.json | 207 + .../b528373e7983b7f77b17152b0f474e39.json | 112 + .../b5604c3dc5b0c3b1c76fbf43f82f2662.json | 79 + .../b67c8489b2cd5da813598600e4966390.json | 226 + .../b70bd4d30a4a95f45ec6b91b748bfc1b.json | 109 + .../b8fe66c348c62f74192dd7a2d9e09066.json | 61 + .../b9bed7e187467464983c670bd01a7e39.json | 40 + .../ba4ec27c19baa7853eb4668d13fca560.json | 90 + .../bbbed2e929d9f9920c8808aac9a1bf5a.json | 57 + .../bdf4db3ae9767cfd45989fba4fb9f48c.json | 91 + .../be639f2c3fb0acbb72d4bae5312e9ea3.json | 189 + .../bf3bdacf1d45e059c908d7eb632419c7.json | 251 + .../bf7caf80e892271f21f3392b5e723804.json | 269 + .../c01c639f0b5d2335780ca0bf9afa5a8f.json | 190 + .../c0bf3f844db0e6208c3db258d3dd4ad8.json | 126 + .../c312653a8b6a3384796c5604548dc15e.json | 124 + .../c37f1b5ec9dae2ca73697002dfc56a37.json | 151 + .../c44c3751c4e7f5a384d11932ea147240.json | 50 + .../c4f21b3653affea2e24af9666cd06e43.json | 96 + .../c51195d4607339d5b49e118ff6004474.json | 118 + .../c58c1199b0ac1a118b33fbee882f34e8.json | 191 + .../c60a9b128f104e5a03201e8e57e928b8.json | 76 + .../c6e2e7311d296bf3ab8e0f8679f39e74.json | 161 + .../c90166d7b174ef9ba698081eac51e92f.json | 55 + .../c945e65bc2a07dbce8bce5ab0d808a21.json | 188 + .../cb907ee0f1aeb477c494af7dcd643a7a.json | 36 + .../cc353396746ffeee557b1e15e395cdcf.json | 39 + .../cc9a86a891aafdf33ec771553270a43f.json | 89 + .../cca07707e11e5cc5c434ca48a0dd83e9.json | 173 + .../cd39ba3772e0585b6b1349549060b61b.json | 60 + .../cd42fa388f1ab964e886320df30e3fa7.json | 176 + .../cdf2f03db5ef55d8a85e74a24485a76d.json | 145 + .../ceebe79b5444b6ad84fddc50e7af4c00.json | 116 + .../cf5c8c7340c35a40db8c879ac1f24695.json | 250 + .../d3587c6595fba24b01396252e690b278.json | 158 + .../d6132493918884adf65900c81985801d.json | 180 + .../d643935497bac76af9b36320b1325eba.json | 80 + .../d934c7110198737cb6db6d97841ee982.json | 74 + .../d93af0f5eff898e99fdc34ac5700bb28.json | 49 + .../da0ddc21f17ec5c8ec642b79137a5fb0.json | 87 + .../db707f8f79f7dbe558f55ae6b44122cf.json | 75 + .../df2928a7262264d67e322a18eca6e5b0.json | 48 + .../df32560b0e620b76f2259be2b70b310c.json | 132 + .../e0891eb9d02d52ed1ad99afb60adc4e0.json | 99 + .../e10b377d096175bbd3fe3908637a979d.json | 118 + .../e2436fe098e7dc07b40960531fb0be5d.json | 158 + .../e2624ceec999bc0558ad736e61475553.json | 77 + .../e4a42ef3a4528ff76e5b29e6fe2f57d3.json | 38 + .../e586cef0f5902fe32364a4a45617361d.json | 52 + .../e748ac4f91e2148bd4912f201b538863.json | 112 + .../e7cf88813582429de3aa801c8ff9f699.json | 108 + .../e7f285a5bb282d303bedf23ebc850cf5.json | 69 + .../e8595e72c8feb61776378d498ce4d287.json | 38 + .../e86640141e810421f144c0a6911ba74d.json | 161 + .../e94fa7de235161815ab4279639df6a33.json | 167 + .../eba31b09180ad9babb41912ebe7c52de.json | 77 + .../ecd06cf71483c78301f89c9f58242253.json | 152 + .../ee27b33c42144764d2d90581004791bf.json | 90 + .../ef3d38c3da8134420ef27e7b01559a4e.json | 103 + .../f1c2b75a29e47cae9bca4dde201ea6f4.json | 85 + .../f20e85176e96fbc66a38669eed2f8023.json | 113 + .../f3bccab8840913564a2b9ac5f196e846.json | 108 + .../f47463c7ae23c2d554caae4cf5663c35.json | 105 + .../f48390bc5679776b9834f47f13ff85f9.json | 38 + .../f6d899c0803ef1ddcfe74878756a3492.json | 328 + .../f72a93fbe97082e68bc29a0346bce434.json | 67 + .../f84775b81c7535e2266878815ef17842.json | 38 + .../fa50fd7e1714af56ef04d55902cc97b2.json | 51 + .../fa738e2eab71707900520d6be67b42e3.json | 121 + .../fa7fea178035c6ef43a756cd3c73b949.json | 100 + .../fc2b6b03438671e65dd4c18db50c2fd7.json | 69 + .../fd389f16b8f148c2bcb087f672dfb2c3.json | 362 + .../097defe81d5298e1842d3fa7c2196dab.json | 15 + .../0d3de532a250fcc7b15c32e9594b1cf7.json | 15 + .../0e1c0d14f3d82a9a019a861dc0b3c27a.json | 15 + .../0fd6b783fc38cc85f045cead6c0b1895.json | 15 + .../123aea93baa3f2422fd0263711da45d6.json | 15 + .../14db9ebb6b6d5b78dcf4abe4f8b2d537.json | 15 + .../16d73c4d0ebf315247bfdf668082a859.json | 15 + .../1775842716fe5c8e3c17b18c97c0e67e.json | 15 + .../18c58c159b16a49a9bca374812886197.json | 15 + .../1b4710821771eafb5053a0e2344c824a.json | 15 + .../2325899079672d681cc027a09435dbde.json | 15 + .../273dbb27b9cba520d7fb67e400bbdf14.json | 15 + .../29d001d6ae21fd5e4077ef6b404f0ab5.json | 15 + .../2b146e8c900a427832d0f40b2fe82d4a.json | 15 + .../2b3a1a43f1a8ee478955d04ec6356bab.json | 15 + .../318c6a8e2773b044da69465616cceed8.json | 15 + .../35179b3e23902ccd7f8d54200802ee54.json | 15 + .../3a6bec24c23c07d8c04bbd99c42b99df.json | 15 + .../3d9fd2b019fc832a84e546524d91dfff.json | 15 + .../49240ec2be1c3ffee157e6a72f441c5c.json | 15 + .../49ec0252c0f95e6952dcf2cba0e1a4d0.json | 15 + .../4bda361559de7be9c9b7ab8807319ccb.json | 15 + .../4c4d178b545c7872b02ce5f4f064c001.json | 15 + .../4ff01c896ec936f373a1fcd0ba1aeece.json | 15 + .../5402b0393b2da56718bcb87175fd6b97.json | 15 + .../5705e81e6a13d23bdf131d5208700925.json | 15 + .../5895e48f0a7812b87c864c6ebc37eb25.json | 15 + .../58be7221e9b2f703305e937726df5ba5.json | 15 + .../5a477c1cc59409b5c794f317aa69b2fe.json | 15 + .../5a8658c4d3d8b64a36641a8ff25719e2.json | 15 + .../5e099f29fa916518c41c52c5baae8821.json | 15 + .../5f7e3b5c901a987186729247cac909e4.json | 15 + .../632dd5134101a9ed5bb92ec9f1031e44.json | 15 + .../64d5fa70b3b666913c583675e596ecb1.json | 15 + .../66e16f2552351b6d3866d42b3e20934d.json | 15 + .../6d47234a8b70bbb1f4119477aaf511a2.json | 15 + .../7605cd98b380f133edcc17fc3b294e7a.json | 15 + .../78cac1c6ec5031395ca95490235a3444.json | 15 + .../98902b51cbe78a05b212a687edb32e22.json | 15 + .../9a211bd03c2447463cfa968edc582890.json | 15 + .../9a37a53461e999713d57dd6ef8766e44.json | 15 + .../9ba614ee49edd569bdf7c6dfbceeefe1.json | 15 + .../9e0bf564d0b1fc181ced505838d99b31.json | 15 + .../a10e75ecf5bfadbf456e8ec506e81331.json | 15 + .../a1ff22ac5975af17b39ade5399053f31.json | 15 + .../a32ef042760431c435329ff28c4bcd28.json | 15 + .../a3c2ccb43834dd7723e9c73445ce2083.json | 15 + .../a7c1dba5939d94410984b9591372618f.json | 15 + .../a983f3e4ffc8701b751af22384f85f8a.json | 15 + .../abe106b9401c1f583351133273952e6c.json | 15 + .../af61ea36d053150cda1923eb32e8accf.json | 15 + .../b2fd859f2a8bec1ef5b463e1f7a9b48b.json | 15 + .../b3364aedd016a4fff2a617096444d766.json | 15 + .../b3d59ce958b066a149ec27eee1fda487.json | 15 + .../c3b026c384fb05ff33443c38e9a98ea3.json | 15 + .../c3b49164d58333890fe66d84766e71fa.json | 15 + .../c3e0a4bb91564316a491223c00cb8584.json | 15 + .../cbe52c9246be9f721ff1750f557e7a45.json | 15 + .../d091d7c7c7324cf800b5d4eecf908d2b.json | 15 + .../d3317fa8ea14c31e7e3e3b5156a01dc6.json | 15 + .../d71d85c9ab38bfc245e28e6360ab937a.json | 15 + .../d914663c2996e3aab2bb46cbbe2ec563.json | 15 + .../d9e7cb6fd9854789cb10cec0906fdc92.json | 15 + .../df3b261b0e3dc6a3edeacb261030b5fd.json | 15 + .../e4347ad25a998685f7704566b0f5575b.json | 15 + .../e4cdfef0c9056558802d1ee87b85163c.json | 15 + .../e8053d69434776f5128217a6a96f3bc7.json | 15 + .../ef9beb60ca0c7e71b0c874fe000dfa8f.json | 15 + .../f19e6f3ff8a57e87758c2762c2584aeb.json | 15 + .../f3cdaa7099cf2f26f4176196cad175eb.json | 15 + .../f5e2f65d5437fc2b003325d963984f47.json | 15 + .../f814d2cefa80e6fd9e53e11e7ff79670.json | 15 + .../fbd6308127aea68e1a7c15f2ef01ed7a.json | 15 + .../0b584104c12da43080b2423eac392021.json | 165 + .../9f3352e1846cace30f6f23d4c5ec30fa.json | 134 + .../81ce170d34aadf59b5341dea337be584.json | 2682 +++ .../0b91e53dcc6abfb4676dd722cf7fd463.json" | 34 + .../96a241c8fb50490541b377f3d4da0e04.json" | 34 + .../c6c26d9cbe960ea4d90bf7c49a5467f0.json" | 34 + .../05e6bfd706e2703d2ed5aa1ec947ad82.json" | 26 + .../0def7ce5bb74891b3843f02402fcf908.json" | 26 + .../23bbe2a147778a11c13ed9da4020a2ec.json" | 24 + .../030b4b030d6c3d49b56031a8216be15f.json" | 23 + .../7c432dd8749edd8ce83c5ec9f84db7f8.json" | 24 + .../b0366f6699fb5bb1906582413a3ede08.json" | 25 + .../cb9efdf8e6795c7f0bbfe403c6d6437b.json" | 26 + .../6e96afdc15ae6c72c2ce76e824e6b44c.json" | 23 + .../9bda3a2868ba8c9632a6c519b38871e8.json" | 26 + .../f929784062a9f9600134fe6772bd6ee8.json" | 26 + .../aff4d36feb00eb3ad43b48f8091c1ee3.json" | 23 + .../21d4878ee02b3c82a86a034c67fe3094.json" | 102 + .../86a3f8c5e4af6a75b2ca3186877a1ed7.json" | 95 + .../65390a58cc330d06fba7bd2cdb86164c.json" | 452 + .../e58e3850ee9a8cb05d89ea5b4e6fe22a.json" | 616 + ...71\347\233\256\346\246\202\350\277\260.md" | 296 + ...66\346\236\204\346\246\202\350\247\210.md" | 3 + ...45\344\275\234\346\265\201\347\250\213.md" | 434 + ...33\351\233\206\346\210\220\345\237\237.md" | 384 + ...16\345\244\204\347\220\206\345\237\237.md" | 325 + ...01\344\271\205\345\214\226\345\237\237.md" | 321 + ...01\347\256\241\347\220\206\345\237\237.md" | 320 + ...67\347\225\214\351\235\242\345\237\237.md" | 581 + ...16\351\205\215\347\275\256\345\237\237.md" | 345 + litho.docs/__Litho_Summary_Brief__.md | 63 + litho.docs/__Litho_Summary_Detail__.md | 13915 ++++++++++++++++ 371 files changed, 51944 insertions(+) create mode 100644 .litho/cache/ai_code_insight/0010b029ee6abdf494fefa6d787c8dda.json create mode 100644 .litho/cache/ai_code_insight/0174f7dcabd104d574f296f0d921d6bf.json create mode 100644 .litho/cache/ai_code_insight/0195076381e69d609268f3678aa827f7.json create mode 100644 .litho/cache/ai_code_insight/0206557cf8509a0ecac7c050730a8607.json create mode 100644 .litho/cache/ai_code_insight/037c011f098a1e80ee87c03e4ac4f69f.json create mode 100644 .litho/cache/ai_code_insight/06cf4fa5f16ef861546ccced9f7b6b25.json create mode 100644 .litho/cache/ai_code_insight/08b41b312bd398cb5f94da5a6a5d36a7.json create mode 100644 .litho/cache/ai_code_insight/09128581bb8c55de6f7da222ea21b400.json create mode 100644 .litho/cache/ai_code_insight/09d2b7bca284cb3e93d422854df5efc1.json create mode 100644 .litho/cache/ai_code_insight/0a18f7ab09a702175ce21710efa77554.json create mode 100644 .litho/cache/ai_code_insight/0a91b530f0180f66fddbf22980c585f4.json create mode 100644 .litho/cache/ai_code_insight/0bb4ab47c07e0a8fc173883264e45f26.json create mode 100644 .litho/cache/ai_code_insight/0bb6effe1ad867e8004bd2ac0ffe1432.json create mode 100644 .litho/cache/ai_code_insight/0c2760672116db4e9f3ed65c8cea377c.json create mode 100644 .litho/cache/ai_code_insight/0d72ea10d9150578f945553974f094de.json create mode 100644 .litho/cache/ai_code_insight/0fbc1633e603348451135fc394ec54a2.json create mode 100644 .litho/cache/ai_code_insight/11369782ecef4ec381ae2141112bce2b.json create mode 100644 .litho/cache/ai_code_insight/11eb06cd23d3dc1bee9ce05ff404b6ef.json create mode 100644 .litho/cache/ai_code_insight/126632c0362c17cbd5258dbef4bd5bcc.json create mode 100644 .litho/cache/ai_code_insight/12aa64503c44747dbccc4b8a9b50c925.json create mode 100644 .litho/cache/ai_code_insight/13d3311c57a4942491dd73a43a41311e.json create mode 100644 .litho/cache/ai_code_insight/13d811cb5f01480847f5763393ca3e29.json create mode 100644 .litho/cache/ai_code_insight/143649b2e7df919a5a61a676170f594b.json create mode 100644 .litho/cache/ai_code_insight/1445c7ab0cb786bdd8cdfbf520276166.json create mode 100644 .litho/cache/ai_code_insight/16d65f6a97cf7bb81899e8e9abf10d32.json create mode 100644 .litho/cache/ai_code_insight/184bb05e0d17bd85030e0cd1ab8da47d.json create mode 100644 .litho/cache/ai_code_insight/1998bbf6a543ea876c074b34b7545191.json create mode 100644 .litho/cache/ai_code_insight/1a1a9b30ee6d8ae7b1da717e5300e481.json create mode 100644 .litho/cache/ai_code_insight/1aff5469f8999556d9085f189b75755b.json create mode 100644 .litho/cache/ai_code_insight/1b754b203996771c5a6dd71534bbdc15.json create mode 100644 .litho/cache/ai_code_insight/1cfacab2cbc2c6bd94c7d78ce762a3eb.json create mode 100644 .litho/cache/ai_code_insight/1d1497c3971d256c8d887048a62f3ed9.json create mode 100644 .litho/cache/ai_code_insight/1f3c0dc04e63c9306d560b83929bfdef.json create mode 100644 .litho/cache/ai_code_insight/1f59c370079b48d193d6a414f8cec863.json create mode 100644 .litho/cache/ai_code_insight/1fcf292b999dccf0c8214ea316144918.json create mode 100644 .litho/cache/ai_code_insight/21f7ea14dab5aaddb082bf74224314e0.json create mode 100644 .litho/cache/ai_code_insight/2384216ebbf7041d48073d079243f7bb.json create mode 100644 .litho/cache/ai_code_insight/25217391845516e5b71dc0101c6b2cae.json create mode 100644 .litho/cache/ai_code_insight/2586645484a5567b61efc57503b2c3a0.json create mode 100644 .litho/cache/ai_code_insight/26381acd2859d55167419934fb8212e0.json create mode 100644 .litho/cache/ai_code_insight/27ca3638a157126364647d701beedbb0.json create mode 100644 .litho/cache/ai_code_insight/28ca872aad808bbe93155e72c9cad232.json create mode 100644 .litho/cache/ai_code_insight/28ff941c3c855b21c493373ddec83237.json create mode 100644 .litho/cache/ai_code_insight/2964aa5f4475545302528c3e59b9be6d.json create mode 100644 .litho/cache/ai_code_insight/2c8e64968ba6cdc2c3960d8d9081704a.json create mode 100644 .litho/cache/ai_code_insight/2dd6a833ecceec8cb69bc89759a5debe.json create mode 100644 .litho/cache/ai_code_insight/2ed047563eba803562f7491c91607abd.json create mode 100644 .litho/cache/ai_code_insight/302afdf662f68b6d1cbe3b6f2ac0c320.json create mode 100644 .litho/cache/ai_code_insight/317264bc9a41525642223799077c4818.json create mode 100644 .litho/cache/ai_code_insight/33036e527c7041f1d59d97031c90ab46.json create mode 100644 .litho/cache/ai_code_insight/342836c19b10875183c4eb597d4130ad.json create mode 100644 .litho/cache/ai_code_insight/34a006e9861ea50feae34bd3850e924a.json create mode 100644 .litho/cache/ai_code_insight/3601d5b1a0cbbc7ae3a39665a71cc938.json create mode 100644 .litho/cache/ai_code_insight/384468e60cfc1eb91df8f0f4dff09582.json create mode 100644 .litho/cache/ai_code_insight/3a52713ea84e03bbcbc65df9bbebbe05.json create mode 100644 .litho/cache/ai_code_insight/3a6c3b61af5a5ca06048c051e1cb4fdc.json create mode 100644 .litho/cache/ai_code_insight/3ce2a51137321e383baab4d8660cb641.json create mode 100644 .litho/cache/ai_code_insight/3d09d8e5ba7eeae9c7c8a362fdd5673b.json create mode 100644 .litho/cache/ai_code_insight/3dc084d733458d35d323fcc4de0e37fb.json create mode 100644 .litho/cache/ai_code_insight/3f03f24fcb16f0dcbb365762049970f1.json create mode 100644 .litho/cache/ai_code_insight/3f28221975c41db1eee84e4d518e5805.json create mode 100644 .litho/cache/ai_code_insight/407d1b0c806c69dd0e4f23770b0fd741.json create mode 100644 .litho/cache/ai_code_insight/409faa45e7903f096fdb6535f11b4a99.json create mode 100644 .litho/cache/ai_code_insight/4230e4241fbad156d9cd4ba191a62b35.json create mode 100644 .litho/cache/ai_code_insight/4244b60930d605826ddec5305e747392.json create mode 100644 .litho/cache/ai_code_insight/42a132f0aa9f8db040bde57dd56293d5.json create mode 100644 .litho/cache/ai_code_insight/42c6c3b8b38361d0b870e0fd40c71928.json create mode 100644 .litho/cache/ai_code_insight/431062a9c86b129c09193fcede2669c2.json create mode 100644 .litho/cache/ai_code_insight/43e1e3e6bba003342ce2aee7ad187bcd.json create mode 100644 .litho/cache/ai_code_insight/4495bdbcc08212704207f665b788462a.json create mode 100644 .litho/cache/ai_code_insight/457b7b302d7f71e51e11ab1a7640eb42.json create mode 100644 .litho/cache/ai_code_insight/45cb436521235e4d034a71e22730e6cf.json create mode 100644 .litho/cache/ai_code_insight/45eec785a9d081d4337b1a060cee24d6.json create mode 100644 .litho/cache/ai_code_insight/4690c42a7d2da0891ef9c1416e1c7273.json create mode 100644 .litho/cache/ai_code_insight/48514e90f10df015b57da543b49c0bbc.json create mode 100644 .litho/cache/ai_code_insight/4990d2a248b5115727059f32e1a3bd34.json create mode 100644 .litho/cache/ai_code_insight/4ca53e004fa88b3e64b0a167212fe7c5.json create mode 100644 .litho/cache/ai_code_insight/4dcaa642b6730282a912b5099ee87e53.json create mode 100644 .litho/cache/ai_code_insight/4f7185e3eabcb3c804d621f9ddeb4e6d.json create mode 100644 .litho/cache/ai_code_insight/501c146ce5aba3f2a64a6fd27f67b120.json create mode 100644 .litho/cache/ai_code_insight/5064170bf87b00f6a19aafbdb3522d45.json create mode 100644 .litho/cache/ai_code_insight/509778d785842a165f6ec9f0e18014a0.json create mode 100644 .litho/cache/ai_code_insight/51362896b1facc80650e24ea8c5c785d.json create mode 100644 .litho/cache/ai_code_insight/514d4c0b04d3d780ce01311309910cd8.json create mode 100644 .litho/cache/ai_code_insight/53bacdb24378ff0ad9c4663c1b4e0fa7.json create mode 100644 .litho/cache/ai_code_insight/5469f38188f245cce5d35a46f815b166.json create mode 100644 .litho/cache/ai_code_insight/54dae1e05c3a4d3ee0f0e0df7f5317a8.json create mode 100644 .litho/cache/ai_code_insight/54e89df6ef71b3e6a4c03591745171e6.json create mode 100644 .litho/cache/ai_code_insight/5602eecf348eaeca4f0eb4632f85cbcb.json create mode 100644 .litho/cache/ai_code_insight/566758005c7599d9c1887e14c77d54b4.json create mode 100644 .litho/cache/ai_code_insight/57ab254f6508149592b0ffef9299d668.json create mode 100644 .litho/cache/ai_code_insight/5812b5594d8525d3532de9b18e171f96.json create mode 100644 .litho/cache/ai_code_insight/58b773ecbd9fd26592f36347631a3c29.json create mode 100644 .litho/cache/ai_code_insight/5c768c8d6c8e6dd66ab215dce47b3f34.json create mode 100644 .litho/cache/ai_code_insight/5d3e653fa78c2a1cdd0adff16b3ca232.json create mode 100644 .litho/cache/ai_code_insight/5de2c8e6ae487ed907ad51fae5bbda30.json create mode 100644 .litho/cache/ai_code_insight/5e9a3ba874f09a3229ccac54845fb3c8.json create mode 100644 .litho/cache/ai_code_insight/5f9c5382a31c90a4968f7b418edc9099.json create mode 100644 .litho/cache/ai_code_insight/62619e7ccab878642efc666b41a43eb5.json create mode 100644 .litho/cache/ai_code_insight/63464ab4d38a6e724c67ffeea505b685.json create mode 100644 .litho/cache/ai_code_insight/63b76c51282dec5d5db2219968bd5c99.json create mode 100644 .litho/cache/ai_code_insight/65a4ded8f7b861f8d55aecf58fe0005e.json create mode 100644 .litho/cache/ai_code_insight/6654b7f0e0b6315d59bea218097bda8b.json create mode 100644 .litho/cache/ai_code_insight/66e11055ecfddc815b84ef74734c929e.json create mode 100644 .litho/cache/ai_code_insight/67b0e101babd39897cdf5a26e51de157.json create mode 100644 .litho/cache/ai_code_insight/684e37e171a28e045821f6dfba331a14.json create mode 100644 .litho/cache/ai_code_insight/68d760b0d05eb65fa4348484009855df.json create mode 100644 .litho/cache/ai_code_insight/696df1c6fca3fed85872b7040c31b6e9.json create mode 100644 .litho/cache/ai_code_insight/6983fc30af9bc60b1b9af1ecd0e341f6.json create mode 100644 .litho/cache/ai_code_insight/69e10635102689d195801f1a76d9360a.json create mode 100644 .litho/cache/ai_code_insight/6b397ec9a37a982794b1c3f095d54c0e.json create mode 100644 .litho/cache/ai_code_insight/6ccf5fd00ecfadf659131e813593fba4.json create mode 100644 .litho/cache/ai_code_insight/70c09ce4a2a65332561a35b3ab6409ab.json create mode 100644 .litho/cache/ai_code_insight/73344f222c4160af99c64c8e6f9ab7bd.json create mode 100644 .litho/cache/ai_code_insight/733b0de1b59a3de709f1ecbeebe6d161.json create mode 100644 .litho/cache/ai_code_insight/73d050d67c343cf40f2a74e819f39945.json create mode 100644 .litho/cache/ai_code_insight/746257dfdfa6c6c10739c54c30e23a9f.json create mode 100644 .litho/cache/ai_code_insight/746d48b27f27baf6c69b7a6718eb1a73.json create mode 100644 .litho/cache/ai_code_insight/74bab31315a8960d4ce77b43dd344178.json create mode 100644 .litho/cache/ai_code_insight/7769ebcdc6a484b55221c6cca454b36e.json create mode 100644 .litho/cache/ai_code_insight/78520a548d6cdab7a2844f81cae51e22.json create mode 100644 .litho/cache/ai_code_insight/786b69d3c396d1a070f35a9e9a2963fb.json create mode 100644 .litho/cache/ai_code_insight/790984d1bbd9e6790c6f52e9614496fd.json create mode 100644 .litho/cache/ai_code_insight/79722b9ff757abc80130ff5312ac93da.json create mode 100644 .litho/cache/ai_code_insight/79fbfbb6c3d63c5b791ce454b00d698d.json create mode 100644 .litho/cache/ai_code_insight/7a7bbd0b11c0e19b574ec3469947e912.json create mode 100644 .litho/cache/ai_code_insight/7a8eeb4ad5e00605874269d4428161e8.json create mode 100644 .litho/cache/ai_code_insight/7b5e8c15cf4078c8e4902404f0930d2f.json create mode 100644 .litho/cache/ai_code_insight/7c3967eaf9f17960fef351271795f6f2.json create mode 100644 .litho/cache/ai_code_insight/7c57c3051847bcdeafe165709195313e.json create mode 100644 .litho/cache/ai_code_insight/7df3a7c345f93a2a645ccb03f339e3b2.json create mode 100644 .litho/cache/ai_code_insight/7e0e8fef0131b7a0c87c87dfd1fe24a1.json create mode 100644 .litho/cache/ai_code_insight/7e8a973c8b2a4d26fdecf2634da67d25.json create mode 100644 .litho/cache/ai_code_insight/7ea084b580daec28f2d54c2d4d6b8221.json create mode 100644 .litho/cache/ai_code_insight/7ef25265a87dc8901007c0def6dd9376.json create mode 100644 .litho/cache/ai_code_insight/80b695228e7ab95081cf5571a6dc2f9a.json create mode 100644 .litho/cache/ai_code_insight/80f61996e2d06022b495b4ba4b64b062.json create mode 100644 .litho/cache/ai_code_insight/83682f524cb0e93138a59ce664e9aa41.json create mode 100644 .litho/cache/ai_code_insight/83d05e12b628c2d7cd1d86f3007e94cb.json create mode 100644 .litho/cache/ai_code_insight/849d3a6b45640b65396afd58695bf847.json create mode 100644 .litho/cache/ai_code_insight/84cd79d365ba42093e6ee9a55a8ba055.json create mode 100644 .litho/cache/ai_code_insight/860f2aef0ec434e6bf925a94c7a7aa79.json create mode 100644 .litho/cache/ai_code_insight/8774bcabedc89de528bdab1b0eb158c2.json create mode 100644 .litho/cache/ai_code_insight/87aade9efd624b66cc966003e2391c82.json create mode 100644 .litho/cache/ai_code_insight/87d989544413a8099358bde45864e14f.json create mode 100644 .litho/cache/ai_code_insight/88b1de4cfa45a27fbd0f96d11fb12a14.json create mode 100644 .litho/cache/ai_code_insight/88c86ac5915868064de89650a69f65b2.json create mode 100644 .litho/cache/ai_code_insight/89ff389b285cb8f201720a6bbde0927a.json create mode 100644 .litho/cache/ai_code_insight/8a80f984693064e97840353555933f94.json create mode 100644 .litho/cache/ai_code_insight/8b418c3361926337283c2a123284c5f2.json create mode 100644 .litho/cache/ai_code_insight/8b50e08f39972e471eeff731e83dc8f8.json create mode 100644 .litho/cache/ai_code_insight/8c3a3790eb2a9d2a2fe2f790fc5c2b79.json create mode 100644 .litho/cache/ai_code_insight/8e292d9c80991a9f4ec647fd3faacef2.json create mode 100644 .litho/cache/ai_code_insight/8f2b7f9a396fa7d8f831124619001714.json create mode 100644 .litho/cache/ai_code_insight/8ff5bf46b5d12046d8fdc8053bc2c451.json create mode 100644 .litho/cache/ai_code_insight/900b73675a2a8d1afd2c5c9d53c46131.json create mode 100644 .litho/cache/ai_code_insight/909b5cb43cabaa97af93cea50a9d8474.json create mode 100644 .litho/cache/ai_code_insight/909d78037190872fb1bae3181c9be40d.json create mode 100644 .litho/cache/ai_code_insight/9174e34c1b67e246a67144e35bb94e48.json create mode 100644 .litho/cache/ai_code_insight/926f094d2428a4cbfd5933b4669aca5f.json create mode 100644 .litho/cache/ai_code_insight/9276c0d8316c8c6f81690e015657645f.json create mode 100644 .litho/cache/ai_code_insight/929c919b226f8b99be92fee0aa9a04f2.json create mode 100644 .litho/cache/ai_code_insight/940af1e923133707481c6b68a66b7748.json create mode 100644 .litho/cache/ai_code_insight/952149d754cc18b71a69052679087887.json create mode 100644 .litho/cache/ai_code_insight/9656ab0f2459c9bb839eb71bda5afab3.json create mode 100644 .litho/cache/ai_code_insight/96d870b1a6b442d8bb70d367b08083e0.json create mode 100644 .litho/cache/ai_code_insight/9a0c0aea81cc72cc13d6b8d1b3f1cce5.json create mode 100644 .litho/cache/ai_code_insight/9a8a579a07ccbdfaca7eeda797409138.json create mode 100644 .litho/cache/ai_code_insight/9afcc0a2aad7ba144d9071852e12dac1.json create mode 100644 .litho/cache/ai_code_insight/9b2b0d80cfc15c7bc59ad686a9e90723.json create mode 100644 .litho/cache/ai_code_insight/9cab669aef6cb0d35df819fd0dfd920b.json create mode 100644 .litho/cache/ai_code_insight/9f00aa53bb19aeddcfc6da8590973776.json create mode 100644 .litho/cache/ai_code_insight/a23fc67512b17b1feac5985b9692a7f2.json create mode 100644 .litho/cache/ai_code_insight/a400b5d729bb04c7cd24a67f7eb77cee.json create mode 100644 .litho/cache/ai_code_insight/a5c496dda132677abe0eb636ac9cfe0d.json create mode 100644 .litho/cache/ai_code_insight/a637c5b39416f4ebdd06177531cab86a.json create mode 100644 .litho/cache/ai_code_insight/a6608f266c742be633a355cdfd2d3db7.json create mode 100644 .litho/cache/ai_code_insight/a6cb6ba582e164d7a7fc2c1f99150bb5.json create mode 100644 .litho/cache/ai_code_insight/a72745de0a68a2a2e8f7ed4854312ce7.json create mode 100644 .litho/cache/ai_code_insight/a733d5bbea0966fe77e752a458aed424.json create mode 100644 .litho/cache/ai_code_insight/a9cb666db0a84608e1b88d30ff7c6cd1.json create mode 100644 .litho/cache/ai_code_insight/aa5a4f69973c3b3787ca003a4abf79e9.json create mode 100644 .litho/cache/ai_code_insight/aa668edc04d179f5ee42c2304e991e0a.json create mode 100644 .litho/cache/ai_code_insight/ab1b0f4b4197fe537faf67a75318cfba.json create mode 100644 .litho/cache/ai_code_insight/abbddff0d4ee559593fb7202b8d69b56.json create mode 100644 .litho/cache/ai_code_insight/abf1f2badac95395e0086d153644ecd5.json create mode 100644 .litho/cache/ai_code_insight/ad5591568fbf848ccc67c2f330d7e3a1.json create mode 100644 .litho/cache/ai_code_insight/adcc64021e419e0c86e06f2bc3768e17.json create mode 100644 .litho/cache/ai_code_insight/af4afc224c894109c3acc51738a7fc31.json create mode 100644 .litho/cache/ai_code_insight/afd44f4486d4c637660b1e531ab6bd89.json create mode 100644 .litho/cache/ai_code_insight/b21b6fe6400e3eb7598b2cc64511e74e.json create mode 100644 .litho/cache/ai_code_insight/b24ca7810d9662bec32c2c4e492bc0f1.json create mode 100644 .litho/cache/ai_code_insight/b25782644749a3853e2e6b2566861bc4.json create mode 100644 .litho/cache/ai_code_insight/b43f713a3ab866458b74ecb4ade7d085.json create mode 100644 .litho/cache/ai_code_insight/b4dff124eecfc611d49db5d9729c3e10.json create mode 100644 .litho/cache/ai_code_insight/b528373e7983b7f77b17152b0f474e39.json create mode 100644 .litho/cache/ai_code_insight/b5604c3dc5b0c3b1c76fbf43f82f2662.json create mode 100644 .litho/cache/ai_code_insight/b67c8489b2cd5da813598600e4966390.json create mode 100644 .litho/cache/ai_code_insight/b70bd4d30a4a95f45ec6b91b748bfc1b.json create mode 100644 .litho/cache/ai_code_insight/b8fe66c348c62f74192dd7a2d9e09066.json create mode 100644 .litho/cache/ai_code_insight/b9bed7e187467464983c670bd01a7e39.json create mode 100644 .litho/cache/ai_code_insight/ba4ec27c19baa7853eb4668d13fca560.json create mode 100644 .litho/cache/ai_code_insight/bbbed2e929d9f9920c8808aac9a1bf5a.json create mode 100644 .litho/cache/ai_code_insight/bdf4db3ae9767cfd45989fba4fb9f48c.json create mode 100644 .litho/cache/ai_code_insight/be639f2c3fb0acbb72d4bae5312e9ea3.json create mode 100644 .litho/cache/ai_code_insight/bf3bdacf1d45e059c908d7eb632419c7.json create mode 100644 .litho/cache/ai_code_insight/bf7caf80e892271f21f3392b5e723804.json create mode 100644 .litho/cache/ai_code_insight/c01c639f0b5d2335780ca0bf9afa5a8f.json create mode 100644 .litho/cache/ai_code_insight/c0bf3f844db0e6208c3db258d3dd4ad8.json create mode 100644 .litho/cache/ai_code_insight/c312653a8b6a3384796c5604548dc15e.json create mode 100644 .litho/cache/ai_code_insight/c37f1b5ec9dae2ca73697002dfc56a37.json create mode 100644 .litho/cache/ai_code_insight/c44c3751c4e7f5a384d11932ea147240.json create mode 100644 .litho/cache/ai_code_insight/c4f21b3653affea2e24af9666cd06e43.json create mode 100644 .litho/cache/ai_code_insight/c51195d4607339d5b49e118ff6004474.json create mode 100644 .litho/cache/ai_code_insight/c58c1199b0ac1a118b33fbee882f34e8.json create mode 100644 .litho/cache/ai_code_insight/c60a9b128f104e5a03201e8e57e928b8.json create mode 100644 .litho/cache/ai_code_insight/c6e2e7311d296bf3ab8e0f8679f39e74.json create mode 100644 .litho/cache/ai_code_insight/c90166d7b174ef9ba698081eac51e92f.json create mode 100644 .litho/cache/ai_code_insight/c945e65bc2a07dbce8bce5ab0d808a21.json create mode 100644 .litho/cache/ai_code_insight/cb907ee0f1aeb477c494af7dcd643a7a.json create mode 100644 .litho/cache/ai_code_insight/cc353396746ffeee557b1e15e395cdcf.json create mode 100644 .litho/cache/ai_code_insight/cc9a86a891aafdf33ec771553270a43f.json create mode 100644 .litho/cache/ai_code_insight/cca07707e11e5cc5c434ca48a0dd83e9.json create mode 100644 .litho/cache/ai_code_insight/cd39ba3772e0585b6b1349549060b61b.json create mode 100644 .litho/cache/ai_code_insight/cd42fa388f1ab964e886320df30e3fa7.json create mode 100644 .litho/cache/ai_code_insight/cdf2f03db5ef55d8a85e74a24485a76d.json create mode 100644 .litho/cache/ai_code_insight/ceebe79b5444b6ad84fddc50e7af4c00.json create mode 100644 .litho/cache/ai_code_insight/cf5c8c7340c35a40db8c879ac1f24695.json create mode 100644 .litho/cache/ai_code_insight/d3587c6595fba24b01396252e690b278.json create mode 100644 .litho/cache/ai_code_insight/d6132493918884adf65900c81985801d.json create mode 100644 .litho/cache/ai_code_insight/d643935497bac76af9b36320b1325eba.json create mode 100644 .litho/cache/ai_code_insight/d934c7110198737cb6db6d97841ee982.json create mode 100644 .litho/cache/ai_code_insight/d93af0f5eff898e99fdc34ac5700bb28.json create mode 100644 .litho/cache/ai_code_insight/da0ddc21f17ec5c8ec642b79137a5fb0.json create mode 100644 .litho/cache/ai_code_insight/db707f8f79f7dbe558f55ae6b44122cf.json create mode 100644 .litho/cache/ai_code_insight/df2928a7262264d67e322a18eca6e5b0.json create mode 100644 .litho/cache/ai_code_insight/df32560b0e620b76f2259be2b70b310c.json create mode 100644 .litho/cache/ai_code_insight/e0891eb9d02d52ed1ad99afb60adc4e0.json create mode 100644 .litho/cache/ai_code_insight/e10b377d096175bbd3fe3908637a979d.json create mode 100644 .litho/cache/ai_code_insight/e2436fe098e7dc07b40960531fb0be5d.json create mode 100644 .litho/cache/ai_code_insight/e2624ceec999bc0558ad736e61475553.json create mode 100644 .litho/cache/ai_code_insight/e4a42ef3a4528ff76e5b29e6fe2f57d3.json create mode 100644 .litho/cache/ai_code_insight/e586cef0f5902fe32364a4a45617361d.json create mode 100644 .litho/cache/ai_code_insight/e748ac4f91e2148bd4912f201b538863.json create mode 100644 .litho/cache/ai_code_insight/e7cf88813582429de3aa801c8ff9f699.json create mode 100644 .litho/cache/ai_code_insight/e7f285a5bb282d303bedf23ebc850cf5.json create mode 100644 .litho/cache/ai_code_insight/e8595e72c8feb61776378d498ce4d287.json create mode 100644 .litho/cache/ai_code_insight/e86640141e810421f144c0a6911ba74d.json create mode 100644 .litho/cache/ai_code_insight/e94fa7de235161815ab4279639df6a33.json create mode 100644 .litho/cache/ai_code_insight/eba31b09180ad9babb41912ebe7c52de.json create mode 100644 .litho/cache/ai_code_insight/ecd06cf71483c78301f89c9f58242253.json create mode 100644 .litho/cache/ai_code_insight/ee27b33c42144764d2d90581004791bf.json create mode 100644 .litho/cache/ai_code_insight/ef3d38c3da8134420ef27e7b01559a4e.json create mode 100644 .litho/cache/ai_code_insight/f1c2b75a29e47cae9bca4dde201ea6f4.json create mode 100644 .litho/cache/ai_code_insight/f20e85176e96fbc66a38669eed2f8023.json create mode 100644 .litho/cache/ai_code_insight/f3bccab8840913564a2b9ac5f196e846.json create mode 100644 .litho/cache/ai_code_insight/f47463c7ae23c2d554caae4cf5663c35.json create mode 100644 .litho/cache/ai_code_insight/f48390bc5679776b9834f47f13ff85f9.json create mode 100644 .litho/cache/ai_code_insight/f6d899c0803ef1ddcfe74878756a3492.json create mode 100644 .litho/cache/ai_code_insight/f72a93fbe97082e68bc29a0346bce434.json create mode 100644 .litho/cache/ai_code_insight/f84775b81c7535e2266878815ef17842.json create mode 100644 .litho/cache/ai_code_insight/fa50fd7e1714af56ef04d55902cc97b2.json create mode 100644 .litho/cache/ai_code_insight/fa738e2eab71707900520d6be67b42e3.json create mode 100644 .litho/cache/ai_code_insight/fa7fea178035c6ef43a756cd3c73b949.json create mode 100644 .litho/cache/ai_code_insight/fc2b6b03438671e65dd4c18db50c2fd7.json create mode 100644 .litho/cache/ai_code_insight/fd389f16b8f148c2bcb087f672dfb2c3.json create mode 100644 .litho/cache/ai_code_purpose/097defe81d5298e1842d3fa7c2196dab.json create mode 100644 .litho/cache/ai_code_purpose/0d3de532a250fcc7b15c32e9594b1cf7.json create mode 100644 .litho/cache/ai_code_purpose/0e1c0d14f3d82a9a019a861dc0b3c27a.json create mode 100644 .litho/cache/ai_code_purpose/0fd6b783fc38cc85f045cead6c0b1895.json create mode 100644 .litho/cache/ai_code_purpose/123aea93baa3f2422fd0263711da45d6.json create mode 100644 .litho/cache/ai_code_purpose/14db9ebb6b6d5b78dcf4abe4f8b2d537.json create mode 100644 .litho/cache/ai_code_purpose/16d73c4d0ebf315247bfdf668082a859.json create mode 100644 .litho/cache/ai_code_purpose/1775842716fe5c8e3c17b18c97c0e67e.json create mode 100644 .litho/cache/ai_code_purpose/18c58c159b16a49a9bca374812886197.json create mode 100644 .litho/cache/ai_code_purpose/1b4710821771eafb5053a0e2344c824a.json create mode 100644 .litho/cache/ai_code_purpose/2325899079672d681cc027a09435dbde.json create mode 100644 .litho/cache/ai_code_purpose/273dbb27b9cba520d7fb67e400bbdf14.json create mode 100644 .litho/cache/ai_code_purpose/29d001d6ae21fd5e4077ef6b404f0ab5.json create mode 100644 .litho/cache/ai_code_purpose/2b146e8c900a427832d0f40b2fe82d4a.json create mode 100644 .litho/cache/ai_code_purpose/2b3a1a43f1a8ee478955d04ec6356bab.json create mode 100644 .litho/cache/ai_code_purpose/318c6a8e2773b044da69465616cceed8.json create mode 100644 .litho/cache/ai_code_purpose/35179b3e23902ccd7f8d54200802ee54.json create mode 100644 .litho/cache/ai_code_purpose/3a6bec24c23c07d8c04bbd99c42b99df.json create mode 100644 .litho/cache/ai_code_purpose/3d9fd2b019fc832a84e546524d91dfff.json create mode 100644 .litho/cache/ai_code_purpose/49240ec2be1c3ffee157e6a72f441c5c.json create mode 100644 .litho/cache/ai_code_purpose/49ec0252c0f95e6952dcf2cba0e1a4d0.json create mode 100644 .litho/cache/ai_code_purpose/4bda361559de7be9c9b7ab8807319ccb.json create mode 100644 .litho/cache/ai_code_purpose/4c4d178b545c7872b02ce5f4f064c001.json create mode 100644 .litho/cache/ai_code_purpose/4ff01c896ec936f373a1fcd0ba1aeece.json create mode 100644 .litho/cache/ai_code_purpose/5402b0393b2da56718bcb87175fd6b97.json create mode 100644 .litho/cache/ai_code_purpose/5705e81e6a13d23bdf131d5208700925.json create mode 100644 .litho/cache/ai_code_purpose/5895e48f0a7812b87c864c6ebc37eb25.json create mode 100644 .litho/cache/ai_code_purpose/58be7221e9b2f703305e937726df5ba5.json create mode 100644 .litho/cache/ai_code_purpose/5a477c1cc59409b5c794f317aa69b2fe.json create mode 100644 .litho/cache/ai_code_purpose/5a8658c4d3d8b64a36641a8ff25719e2.json create mode 100644 .litho/cache/ai_code_purpose/5e099f29fa916518c41c52c5baae8821.json create mode 100644 .litho/cache/ai_code_purpose/5f7e3b5c901a987186729247cac909e4.json create mode 100644 .litho/cache/ai_code_purpose/632dd5134101a9ed5bb92ec9f1031e44.json create mode 100644 .litho/cache/ai_code_purpose/64d5fa70b3b666913c583675e596ecb1.json create mode 100644 .litho/cache/ai_code_purpose/66e16f2552351b6d3866d42b3e20934d.json create mode 100644 .litho/cache/ai_code_purpose/6d47234a8b70bbb1f4119477aaf511a2.json create mode 100644 .litho/cache/ai_code_purpose/7605cd98b380f133edcc17fc3b294e7a.json create mode 100644 .litho/cache/ai_code_purpose/78cac1c6ec5031395ca95490235a3444.json create mode 100644 .litho/cache/ai_code_purpose/98902b51cbe78a05b212a687edb32e22.json create mode 100644 .litho/cache/ai_code_purpose/9a211bd03c2447463cfa968edc582890.json create mode 100644 .litho/cache/ai_code_purpose/9a37a53461e999713d57dd6ef8766e44.json create mode 100644 .litho/cache/ai_code_purpose/9ba614ee49edd569bdf7c6dfbceeefe1.json create mode 100644 .litho/cache/ai_code_purpose/9e0bf564d0b1fc181ced505838d99b31.json create mode 100644 .litho/cache/ai_code_purpose/a10e75ecf5bfadbf456e8ec506e81331.json create mode 100644 .litho/cache/ai_code_purpose/a1ff22ac5975af17b39ade5399053f31.json create mode 100644 .litho/cache/ai_code_purpose/a32ef042760431c435329ff28c4bcd28.json create mode 100644 .litho/cache/ai_code_purpose/a3c2ccb43834dd7723e9c73445ce2083.json create mode 100644 .litho/cache/ai_code_purpose/a7c1dba5939d94410984b9591372618f.json create mode 100644 .litho/cache/ai_code_purpose/a983f3e4ffc8701b751af22384f85f8a.json create mode 100644 .litho/cache/ai_code_purpose/abe106b9401c1f583351133273952e6c.json create mode 100644 .litho/cache/ai_code_purpose/af61ea36d053150cda1923eb32e8accf.json create mode 100644 .litho/cache/ai_code_purpose/b2fd859f2a8bec1ef5b463e1f7a9b48b.json create mode 100644 .litho/cache/ai_code_purpose/b3364aedd016a4fff2a617096444d766.json create mode 100644 .litho/cache/ai_code_purpose/b3d59ce958b066a149ec27eee1fda487.json create mode 100644 .litho/cache/ai_code_purpose/c3b026c384fb05ff33443c38e9a98ea3.json create mode 100644 .litho/cache/ai_code_purpose/c3b49164d58333890fe66d84766e71fa.json create mode 100644 .litho/cache/ai_code_purpose/c3e0a4bb91564316a491223c00cb8584.json create mode 100644 .litho/cache/ai_code_purpose/cbe52c9246be9f721ff1750f557e7a45.json create mode 100644 .litho/cache/ai_code_purpose/d091d7c7c7324cf800b5d4eecf908d2b.json create mode 100644 .litho/cache/ai_code_purpose/d3317fa8ea14c31e7e3e3b5156a01dc6.json create mode 100644 .litho/cache/ai_code_purpose/d71d85c9ab38bfc245e28e6360ab937a.json create mode 100644 .litho/cache/ai_code_purpose/d914663c2996e3aab2bb46cbbe2ec563.json create mode 100644 .litho/cache/ai_code_purpose/d9e7cb6fd9854789cb10cec0906fdc92.json create mode 100644 .litho/cache/ai_code_purpose/df3b261b0e3dc6a3edeacb261030b5fd.json create mode 100644 .litho/cache/ai_code_purpose/e4347ad25a998685f7704566b0f5575b.json create mode 100644 .litho/cache/ai_code_purpose/e4cdfef0c9056558802d1ee87b85163c.json create mode 100644 .litho/cache/ai_code_purpose/e8053d69434776f5128217a6a96f3bc7.json create mode 100644 .litho/cache/ai_code_purpose/ef9beb60ca0c7e71b0c874fe000dfa8f.json create mode 100644 .litho/cache/ai_code_purpose/f19e6f3ff8a57e87758c2762c2584aeb.json create mode 100644 .litho/cache/ai_code_purpose/f3cdaa7099cf2f26f4176196cad175eb.json create mode 100644 .litho/cache/ai_code_purpose/f5e2f65d5437fc2b003325d963984f47.json create mode 100644 .litho/cache/ai_code_purpose/f814d2cefa80e6fd9e53e11e7ff79670.json create mode 100644 .litho/cache/ai_code_purpose/fbd6308127aea68e1a7c15f2ef01ed7a.json create mode 100644 .litho/cache/ai_relationships_insights/0b584104c12da43080b2423eac392021.json create mode 100644 .litho/cache/ai_relationships_insights/9f3352e1846cace30f6f23d4c5ec30fa.json create mode 100644 .litho/cache/structure/81ce170d34aadf59b5341dea337be584.json create mode 100644 ".litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/0b91e53dcc6abfb4676dd722cf7fd463.json" create mode 100644 ".litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/96a241c8fb50490541b377f3d4da0e04.json" create mode 100644 ".litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/c6c26d9cbe960ea4d90bf7c49a5467f0.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/AI\350\203\275\345\212\233\351\233\206\346\210\220\345\237\237/05e6bfd706e2703d2ed5aa1ec947ad82.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\345\244\204\347\220\206\345\237\237/0def7ce5bb74891b3843f02402fcf908.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\350\216\267\345\217\226\344\270\216\345\244\204\347\220\206\345\237\237/23bbe2a147778a11c13ed9da4020a2ec.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\345\255\230\345\202\250\345\237\237/030b4b030d6c3d49b56031a8216be15f.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\237\237/7c432dd8749edd8ce83c5ec9f84db7f8.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/b0366f6699fb5bb1906582413a3ede08.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/cb9efdf8e6795c7f0bbfe403c6d6437b.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/6e96afdc15ae6c72c2ce76e824e6b44c.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/9bda3a2868ba8c9632a6c519b38871e8.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237/f929784062a9f9600134fe6772bd6ee8.json" create mode 100644 ".litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\351\233\206\346\210\220\345\237\237/aff4d36feb00eb3ad43b48f8091c1ee3.json" create mode 100644 ".litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/21d4878ee02b3c82a86a034c67fe3094.json" create mode 100644 ".litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/86a3f8c5e4af6a75b2ca3186877a1ed7.json" create mode 100644 ".litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/65390a58cc330d06fba7bd2cdb86164c.json" create mode 100644 ".litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/e58e3850ee9a8cb05d89ea5b4e6fe22a.json" create mode 100644 "litho.docs/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" create mode 100644 "litho.docs/2\343\200\201\346\236\266\346\236\204\346\246\202\350\247\210.md" create mode 100644 "litho.docs/3\343\200\201\345\267\245\344\275\234\346\265\201\347\250\213.md" create mode 100644 "litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/AI\350\203\275\345\212\233\351\233\206\346\210\220\345\237\237.md" create mode 100644 "litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\345\206\205\345\256\271\350\216\267\345\217\226\344\270\216\345\244\204\347\220\206\345\237\237.md" create mode 100644 "litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\237\237.md" create mode 100644 "litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237.md" create mode 100644 "litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237.md" create mode 100644 "litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237.md" create mode 100644 litho.docs/__Litho_Summary_Brief__.md create mode 100644 litho.docs/__Litho_Summary_Detail__.md diff --git a/.litho/cache/ai_code_insight/0010b029ee6abdf494fefa6d787c8dda.json b/.litho/cache/ai_code_insight/0010b029ee6abdf494fefa6d787c8dda.json new file mode 100644 index 0000000..e5ff38a --- /dev/null +++ b/.litho/cache/ai_code_insight/0010b029ee6abdf494fefa6d787c8dda.json @@ -0,0 +1,88 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/scrap/src/types.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义抓取器接口 IFetcher,用于异步获取文章列表。依赖于 Tauri 框架和外部类型系统。", + "functions": [], + "interfaces": [ + "IFetcher" + ] + }, + "detailed_description": "该组件定义了一个名为 IFetcher 的 trait,用于抽象不同数据源的抓取逻辑。其核心方法 fetch 接收应用句柄、LLM 分析段落和 Feed 目标描述,返回一个异步 Future,输出为 Article 对象的 Result 列表。此设计支持在 Tauri 桌面应用上下文中进行灵活扩展,允许不同的实现根据配置从多种来源抓取内容。", + "responsibilities": [ + "定义抓取操作的统一接口契约", + "支持异步非阻塞的数据获取模式", + "集成 Tauri 应用上下文以访问资源", + "解耦具体抓取逻辑与调用方", + "传递 LLM 处理指令与目标源描述" + ], + "interfaces": [ + { + "name": "IFetcher", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri 应用句柄,用于访问应用状态或资源" + }, + { + "name": "llm_section", + "param_type": "&LLMSection", + "is_optional": false, + "description": "指定 LLM 处理的内容区域配置" + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": "目标 feed 来源的描述信息" + } + ], + "return_type": "impl std::future::Future>> + Send", + "description": "抓取器行为的抽象接口,支持运行时动态分发。" + } + ], + "dependencies": [ + { + "name": "tauri", + "path": "tauri::{AppHandle, Runtime}", + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "types", + "path": "types::{Article, FeedTargetDescription, LLMSection}", + "is_external": false, + "line_number": 2, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 11, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.67, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024623, + "prompt_hash": "0010b029ee6abdf494fefa6d787c8dda", + "token_usage": { + "input_tokens": 498, + "output_tokens": 703, + "total_tokens": 1201 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0174f7dcabd104d574f296f0d921d6bf.json b/.litho/cache/ai_code_insight/0174f7dcabd104d574f296f0d921d6bf.json new file mode 100644 index 0000000..17ef0b6 --- /dev/null +++ b/.litho/cache/ai_code_insight/0174f7dcabd104d574f296f0d921d6bf.json @@ -0,0 +1,200 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/main/+page.svelte", + "source_summary": "", + "code_purpose": "page", + "importance_score": 1.0, + "description": "主页面路由组件,负责整合feeds、文章列表、阅读器和AI精灵面板等核心UI模块。", + "functions": [], + "interfaces": [ + "onFeedPressed", + "onSelectToday", + "onSelectWeekend", + "onSelectFavorite", + "onSelectUnread", + "onArticlePressed" + ] + }, + "detailed_description": "该组件是SvelteKit应用中的主页面路由组件(+page.svelte),位于 /main 路由下。它作为整个主界面的布局容器,负责协调多个功能模块:左侧为信息源列表(FeedsList),中间为文章列表(ArticlesList)与搜索栏(SearchBar),右侧为主内容区的文章阅读器(ArticleReader)或空白提示(ReaderBlankIndicator)。底部包含全局Footer和AI精灵面板(AISpritePanel)。通过导入 createStore 初始化主状态 store,并将其拆分为 feedsStore、articlesStore、readerStore 等子模块供各子组件使用。同时集成了两个 Toaster 实例用于全局通知和AI相关通知。组件使用 disableContextMenu 指令防止右键菜单触发,提升用户体验。", + "responsibilities": [ + "作为主路由页面的布局容器,组织并渲染核心UI组件", + "初始化并管理全局状态 store 及其子模块", + "协调不同功能模块之间的数据流和事件通信", + "处理用户交互事件(如选择feed、文章点击等)", + "集成全局通知系统(Toaster)和AI精灵面板" + ], + "interfaces": [ + { + "name": "onFeedPressed", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": "被点击的信息源ID" + } + ], + "return_type": "void", + "description": "当用户点击某个信息源时触发,用于更新当前选中的feed" + }, + { + "name": "onSelectToday", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "选择今日推荐内容" + }, + { + "name": "onSelectWeekend", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "选择周末精选内容" + }, + { + "name": "onSelectFavorite", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "选择收藏的文章" + }, + { + "name": "onSelectUnread", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "选择未读文章" + }, + { + "name": "onArticlePressed", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "article", + "param_type": "Article", + "is_optional": false, + "description": "被点击的文章对象" + } + ], + "return_type": "void", + "description": "当用户点击文章列表中的某篇文章时触发" + } + ], + "dependencies": [ + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/FeedsList.svelte", + "path": "./widgets/FeedsList.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/ArticlesList.svelte", + "path": "./widgets/ArticlesList.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/SearchBar.svelte", + "path": "./widgets/SearchBar.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/ArticleReader.svelte", + "path": "./widgets/ArticleReader.svelte", + "is_external": false, + "line_number": 6, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/Footer.svelte", + "path": "./widgets/Footer.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/ReaderBlankIndicator.svelte", + "path": "./widgets/ReaderBlankIndicator.svelte", + "is_external": false, + "line_number": 8, + "dependency_type": "import", + "version": null + }, + { + "name": "./stores/index.svelte", + "path": "./stores/index.svelte", + "is_external": false, + "line_number": 9, + "dependency_type": "import", + "version": null + }, + { + "name": "./widgets/AISpritePanel.svelte", + "path": "./widgets/AISpritePanel.svelte", + "is_external": false, + "line_number": 10, + "dependency_type": "import", + "version": null + }, + { + "name": "./stores/toast", + "path": "./stores/toast", + "is_external": false, + "line_number": 11, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 75, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 11.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024159, + "prompt_hash": "0174f7dcabd104d574f296f0d921d6bf", + "token_usage": { + "input_tokens": 1102, + "output_tokens": 1395, + "total_tokens": 2497 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0195076381e69d609268f3678aa827f7.json b/.litho/cache/ai_code_insight/0195076381e69d609268f3678aa827f7.json new file mode 100644 index 0000000..ff58c5a --- /dev/null +++ b/.litho/cache/ai_code_insight/0195076381e69d609268f3678aa827f7.json @@ -0,0 +1,266 @@ +{ + "data": { + "code_dossier": { + "name": "llm_ollama.rs", + "file_path": "crates/llm/src/providers/llm_ollama.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "Ollama LLM服务的完成接口实现,负责与Ollama后端进行通信以生成文本补全。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了针对Ollama大语言模型的文本补全功能。通过封装请求参数并使用reqwest客户端发送POST请求到指定API端点,获取生成的响应内容。主要逻辑集中在构建符合Ollama API规范的请求体,并解析返回结果。系统提示词、模型配置和AI目标选项均在初始化时注入,保证了服务实例的可复用性和配置灵活性。", + "responsibilities": [ + "实现Ollama大模型的文本补全接口调用", + "封装请求参数以适配Ollama API格式", + "管理HTTP客户端与远程API的通信", + "处理序列化与反序列化的数据转换", + "提供基于配置的可扩展服务实例创建机制" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了文本补全服务的标准行为契约" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&OllamaLLMProvider", + "is_optional": false, + "description": "Ollama提供者配置" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词" + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "AI目标选项" + } + ], + "return_type": "anyhow::Result", + "description": "根据配置创建新的OllamaCompletionService实例" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入的内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行文本补全操作并返回生成结果" + }, + { + "name": "RequestParameter", + "interface_type": "struct", + "visibility": "private", + "parameters": [ + { + "name": "model", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "system", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "prompt", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": null + }, + { + "name": "images", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "format", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "keep_alive", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "stream", + "param_type": "bool", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "用于序列化为Ollama API所需请求体的数据结构" + }, + { + "name": "CompletionReply", + "interface_type": "struct", + "visibility": "private", + "parameters": [ + { + "name": "response", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "用于反序列化Ollama API响应的数据结构" + }, + { + "name": "OllamaCompletionService", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "endpoint", + "param_type": "LLMEndPoint", + "is_optional": false, + "description": null + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": null + }, + { + "name": "client", + "param_type": "Client", + "is_optional": false, + "description": null + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "Ollama文本补全服务的主要实现结构" + }, + { + "name": "impl CompletionService for OllamaCompletionService", + "interface_type": "impl", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "为OllamaCompletionService实现CompletionService trait" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::llm_endpoint::LLMEndPoint", + "path": "types/llm_endpoint.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "type", + "version": null + }, + { + "name": "types::OllamaLLMProvider", + "path": "types/mod.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "module", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 8, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 8, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 65, + "number_of_functions": 2, + "number_of_classes": 3, + "depth_of_inheritance": 0, + "coupling_factor": 0.38, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801116, + "prompt_hash": "0195076381e69d609268f3678aa827f7", + "token_usage": { + "input_tokens": 939, + "output_tokens": 1500, + "total_tokens": 2439 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0206557cf8509a0ecac7c050730a8607.json b/.litho/cache/ai_code_insight/0206557cf8509a0ecac7c050730a8607.json new file mode 100644 index 0000000..855f2c7 --- /dev/null +++ b/.litho/cache/ai_code_insight/0206557cf8509a0ecac7c050730a8607.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "FeedPackageEditPanel.svelte", + "file_path": "app/src/routes/main/widgets/FeedPackageEditPanel.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件为空文件,无任何代码实现。预期应为一个用于编辑信息流包(Feed Package)的前端UI面板,但当前未定义任何逻辑、结构或交互。", + "responsibilities": [ + "占位组件:目前仅作为路径存在,无实际职责", + "待实现功能:预计承担信息流包的配置与编辑界面展示", + "用户交互处理:未来可能包含表单输入、数据绑定和提交操作" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.0 + } + }, + "timestamp": 1759024547, + "prompt_hash": "0206557cf8509a0ecac7c050730a8607", + "token_usage": { + "input_tokens": 419, + "output_tokens": 307, + "total_tokens": 726 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/037c011f098a1e80ee87c03e4ac4f69f.json b/.litho/cache/ai_code_insight/037c011f098a1e80ee87c03e4ac4f69f.json new file mode 100644 index 0000000..a6cef15 --- /dev/null +++ b/.litho/cache/ai_code_insight/037c011f098a1e80ee87c03e4ac4f69f.json @@ -0,0 +1,201 @@ +{ + "data": { + "code_dossier": { + "name": "Cargo.toml", + "file_path": "app/src-tauri/Cargo.toml", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Tauri应用的Rust构建配置文件,定义项目元信息、依赖管理和编译配置。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该Cargo.toml文件是Tauri桌面应用的核心构建配置,负责管理整个后端Rust模块的依赖关系、编译选项和项目元数据。它定义了本地库的输出类型(动态/静态库),声明了多个Tauri官方插件以支持系统级功能如托盘图标、剪贴板操作、命令行执行等,并通过workspace机制统一管理共享依赖版本,确保依赖一致性。同时,配置了不同构建模式下的优化策略,提升发布版本性能。", + "responsibilities": [ + "管理项目的元数据和版本信息", + "协调本地crates之间的依赖关系", + "集成Tauri生态插件以扩展桌面应用能力", + "统一workspace共享依赖的版本与特性", + "配置编译优化参数以提升运行时性能" + ], + "interfaces": [], + "dependencies": [ + { + "name": "tauri-build", + "path": null, + "is_external": true, + "line_number": 11, + "dependency_type": "build-dependencies", + "version": "2.3.0" + }, + { + "name": "sentry", + "path": null, + "is_external": true, + "line_number": 15, + "dependency_type": "dependencies", + "version": "0.41.0" + }, + { + "name": "fslock", + "path": null, + "is_external": true, + "line_number": 16, + "dependency_type": "dependencies", + "version": "0.2.1" + }, + { + "name": "tauri-plugin-shell", + "path": null, + "is_external": true, + "line_number": 17, + "dependency_type": "dependencies", + "version": "2.3.0" + }, + { + "name": "tauri-plugin-clipboard-manager", + "path": null, + "is_external": true, + "line_number": 18, + "dependency_type": "dependencies", + "version": "2.3.0" + }, + { + "name": "tauri-plugin-os", + "path": null, + "is_external": true, + "line_number": 19, + "dependency_type": "dependencies", + "version": "2.3.0" + }, + { + "name": "tauri-plugin-dialog", + "path": null, + "is_external": true, + "line_number": 20, + "dependency_type": "dependencies", + "version": "2.3.1" + }, + { + "name": "tauri-plugin-autostart", + "path": null, + "is_external": true, + "line_number": 23, + "dependency_type": "target.dependencies", + "version": "2.5.0" + }, + { + "name": "tauri-plugin-single-instance", + "path": null, + "is_external": true, + "line_number": 24, + "dependency_type": "target.dependencies", + "version": "2.3.1" + }, + { + "name": "feed_api_rs", + "path": "../../crates/feed_api_rs", + "is_external": false, + "line_number": 27, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "types", + "path": "../../crates/types", + "is_external": false, + "line_number": 28, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "recorder", + "path": "../../crates/recorder", + "is_external": false, + "line_number": 29, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "ollama", + "path": "../../crates/ollama", + "is_external": false, + "line_number": 30, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "tauri-plugin-feed-api", + "path": "../../crates/tauri-plugin-feed-api", + "is_external": false, + "line_number": 31, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 34, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 35, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "serde_json", + "path": null, + "is_external": true, + "line_number": 36, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": 37, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 38, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "spdlog-rs", + "path": null, + "is_external": true, + "line_number": 39, + "dependency_type": "dependencies", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 53, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.75, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805961, + "prompt_hash": "037c011f098a1e80ee87c03e4ac4f69f", + "token_usage": { + "input_tokens": 775, + "output_tokens": 1118, + "total_tokens": 1893 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/06cf4fa5f16ef861546ccced9f7b6b25.json b/.litho/cache/ai_code_insight/06cf4fa5f16ef861546ccced9f7b6b25.json new file mode 100644 index 0000000..6c87a2c --- /dev/null +++ b/.litho/cache/ai_code_insight/06cf4fa5f16ef861546ccced9f7b6b25.json @@ -0,0 +1,128 @@ +{ + "data": { + "code_dossier": { + "name": "assistant.rs", + "file_path": "crates/intelligent/src/article_processor/assistant.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "智能助手组件,用于处理文章内容并基于用户提问和会话历史生成回复。", + "functions": [ + "new", + "chat" + ], + "interfaces": [ + "Assistant" + ] + }, + "detailed_description": "该组件是一个智能Agent,负责处理文章内容并与用户进行对话。它通过调用底层LLM服务来生成回复。组件初始化时配置了系统提示和用户指令后缀,并在聊天过程中将文章内容、用户会话历史和当前问题组合成完整的上下文发送给LLM模型。其主要功能是作为文章处理器的对话接口层,实现基于文档内容的问答能力。", + "responsibilities": [ + "管理与LLM模型的交互会话", + "构建包含文章内容、历史记录和用户问题的完整上下文", + "封装底层LLM调用细节,提供简洁的聊天接口", + "维护系统提示和用户指令模板" + ], + "interfaces": [ + { + "name": "Assistant", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "智能助手主结构体,封装LLM代理实例和用户指令" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "LLM配置区域" + } + ], + "return_type": "Assistant", + "description": "创建新的Assistant实例,初始化LLM代理和选项" + }, + { + "name": "chat", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "article", + "param_type": "String", + "is_optional": false, + "description": "要处理的文章正文" + }, + { + "name": "user_prompt", + "param_type": "&str", + "is_optional": false, + "description": "用户的当前提问" + }, + { + "name": "history", + "param_type": "Vec", + "is_optional": false, + "description": "之前的会话历史记录" + } + ], + "return_type": "anyhow::Result", + "description": "执行聊天操作,结合文章内容、历史记录和用户提问生成回复" + } + ], + "dependencies": [ + { + "name": "llm::llm_agent::CompletionAgent", + "path": "llm::llm_agent::CompletionAgent", + "is_external": true, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types::AITargetOption", + "is_external": true, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::ConversationMessage", + "path": "types::ConversationMessage", + "is_external": true, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types::LLMSection", + "is_external": true, + "line_number": 3, + "dependency_type": "struct", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 43, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805334, + "prompt_hash": "06cf4fa5f16ef861546ccced9f7b6b25", + "token_usage": { + "input_tokens": 796, + "output_tokens": 930, + "total_tokens": 1726 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/08b41b312bd398cb5f94da5a6a5d36a7.json b/.litho/cache/ai_code_insight/08b41b312bd398cb5f94da5a6a5d36a7.json new file mode 100644 index 0000000..0071f77 --- /dev/null +++ b/.litho/cache/ai_code_insight/08b41b312bd398cb5f94da5a6a5d36a7.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "FeedEditPanel.svelte", + "file_path": "app/src/routes/main/widgets/FeedEditPanel.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件的源代码为空,未实现任何功能。理论上作为Feed编辑面板,应提供内容输入、格式化、提交等交互能力,但当前版本为空白组件。", + "responsibilities": [ + "占位符:待实现Feed内容编辑功能", + "占位符:待实现用户输入处理逻辑", + "占位符:待集成表单验证机制" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.0 + } + }, + "timestamp": 1759024543, + "prompt_hash": "08b41b312bd398cb5f94da5a6a5d36a7", + "token_usage": { + "input_tokens": 415, + "output_tokens": 265, + "total_tokens": 680 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/09128581bb8c55de6f7da222ea21b400.json b/.litho/cache/ai_code_insight/09128581bb8c55de6f7da222ea21b400.json new file mode 100644 index 0000000..784297e --- /dev/null +++ b/.litho/cache/ai_code_insight/09128581bb8c55de6f7da222ea21b400.json @@ -0,0 +1,83 @@ +{ + "data": { + "code_dossier": { + "name": "simulator.rs", + "file_path": "crates/scrap/src/simulator.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": null, + "functions": [ + "scrap_text_by_url" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了基于Tauri框架的网页内容抓取功能。通过创建一个隐藏的Webview窗口加载指定URL,在页面加载完成后执行JavaScript代码提取document.documentElement.innerHTML,并通过事件机制将结果回传。使用全局互斥锁确保同一时间只能有一个抓取任务执行,防止资源冲突。支持异步操作和超时控制,若在10秒内未获取到数据则返回超时错误。", + "responsibilities": [ + "管理Webview窗口的创建与销毁以实现网页内容抓取", + "通过JavaScript注入和事件监听机制提取页面HTML内容", + "使用互斥锁保证同一时间仅允许一个抓取任务运行", + "处理异步超时逻辑,避免请求无限期挂起", + "封装Tauri Webview操作的错误处理与资源清理" + ], + "interfaces": [], + "dependencies": [ + { + "name": "once_cell", + "path": "once_cell::sync::Lazy", + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog::error", + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": "tauri::{async_runtime, AppHandle, Listener, Manager, Runtime, Url, WebviewUrl, WebviewWindowBuilder}", + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "tokio", + "path": "tokio::{sync::{oneshot, Mutex}, time::{sleep, Duration}}", + "is_external": true, + "line_number": 5, + "dependency_type": "use", + "version": null + }, + { + "name": "anyhow", + "path": "anyhow::Result", + "is_external": true, + "line_number": null, + "dependency_type": "return", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 81, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805559, + "prompt_hash": "09128581bb8c55de6f7da222ea21b400", + "token_usage": { + "input_tokens": 1181, + "output_tokens": 639, + "total_tokens": 1820 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/09d2b7bca284cb3e93d422854df5efc1.json b/.litho/cache/ai_code_insight/09d2b7bca284cb3e93d422854df5efc1.json new file mode 100644 index 0000000..5e5d7c5 --- /dev/null +++ b/.litho/cache/ai_code_insight/09d2b7bca284cb3e93d422854df5efc1.json @@ -0,0 +1,86 @@ +{ + "data": { + "code_dossier": { + "name": "utils.rs", + "file_path": "crates/scrap/src/search/utils.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供用于文本和HTML内容清理的辅助函数,主要用于提取和标准化网页搜索结果中的信息。", + "functions": [ + "trim_head_read_days_ago", + "trim_html_with_script_and_style", + "trim_to" + ], + "interfaces": [ + "trim_head_read_days_ago", + "trim_html_with_script_and_style" + ] + }, + "detailed_description": "该组件包含三个函数,其中两个为公共接口。`trim_head_read_days_ago` 用于清理表示阅读时间的字符串,移除多种语言中表示相对时间的后缀(如“天之前”、“days ago”等),返回纯数字天数。`trim_html_with_script_and_style` 接收原始HTML文本,解析并过滤掉script、style、meta等非主体内容标签,保留body内主要可视元素,生成简化后的HTML结构。`trim_to` 是私有辅助函数,执行具体的子串截取逻辑,基于指定前缀进行删除。", + "responsibilities": [ + "清理和标准化时间相关的文本数据", + "从HTML中提取有意义的内容并去除干扰标签", + "提供可复用的字符串处理基础能力" + ], + "interfaces": [ + { + "name": "trim_head_read_days_ago", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "head_read", + "param_type": "String", + "is_optional": false, + "description": "包含相对时间描述的输入字符串" + } + ], + "return_type": "String", + "description": "移除多种语言的时间后缀,返回干净的天数文本" + }, + { + "name": "trim_html_with_script_and_style", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "html_text", + "param_type": "&str", + "is_optional": false, + "description": "原始HTML文档内容" + } + ], + "return_type": "String", + "description": "解析HTML并移除脚本、样式等非主体标签,返回精简后的HTML" + } + ], + "dependencies": [ + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 39, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024369, + "prompt_hash": "09d2b7bca284cb3e93d422854df5efc1", + "token_usage": { + "input_tokens": 846, + "output_tokens": 730, + "total_tokens": 1576 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0a18f7ab09a702175ce21710efa77554.json b/.litho/cache/ai_code_insight/0a18f7ab09a702175ce21710efa77554.json new file mode 100644 index 0000000..efdc8ec --- /dev/null +++ b/.litho/cache/ai_code_insight/0a18f7ab09a702175ce21710efa77554.json @@ -0,0 +1,121 @@ +{ + "data": { + "code_dossier": { + "name": "llm_glm.rs", + "file_path": "crates/llm/src/providers/llm_glm.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现GLM大语言模型的调用服务,基于OpenAI兼容接口协议封装。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了对智谱AI GLM系列大语言模型的适配支持。通过复用OpenAI类接口的基础服务实现(OpenAILikeCompletionService),将GLMProvider配置转换为标准OpenAI格式进行请求转发。其核心逻辑在于构造一个兼容OpenAI API风格的客户端,利用已有的通用完成度服务来与GLM后端通信。这种设计避免了重复实现网络请求、错误处理等基础设施代码,提升了代码复用性和维护性。", + "responsibilities": [ + "将GLM LLM提供者配置转换为OpenAI兼容格式", + "封装GLM模型的文本生成请求能力", + "通过组合模式复用OpenAI类服务的通用实现", + "管理与GLM API的连接客户端生命周期", + "提供异步完成度接口供上层调用" + ], + "interfaces": [ + { + "name": "new", + "interface_type": "constructor", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&GLMLLMProvider", + "is_optional": false, + "description": "GLM提供商配置信息" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "目标选项(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "创建新的GLMCompletionService实例" + }, + { + "name": "completion", + "interface_type": "method", + "visibility": "impl-CompletionService", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行文本补全请求并返回结果" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types::{GLMLLMProvider, OpenAILLMProvider}", + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::connector", + "path": "crate::connector", + "is_external": false, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "OpenAILikeCompletionService", + "path": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "is_external": false, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "CompletionService", + "path": "crate::providers::types::{AITargetOption, CompletionService}", + "is_external": false, + "line_number": 5, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 33, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 4.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758801130, + "prompt_hash": "0a18f7ab09a702175ce21710efa77554", + "token_usage": { + "input_tokens": 761, + "output_tokens": 878, + "total_tokens": 1639 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0a91b530f0180f66fddbf22980c585f4.json b/.litho/cache/ai_code_insight/0a91b530f0180f66fddbf22980c585f4.json new file mode 100644 index 0000000..2f2b4e8 --- /dev/null +++ b/.litho/cache/ai_code_insight/0a91b530f0180f66fddbf22980c585f4.json @@ -0,0 +1,190 @@ +{ + "data": { + "code_dossier": { + "name": "tray.rs", + "file_path": "app/src-tauri/src/tray.rs", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "系统托盘图标管理组件,用于创建和控制桌面应用的托盘菜单及窗口行为", + "functions": [ + "create_tray", + "open_main_window", + "bring_to_front" + ], + "interfaces": [] + }, + "detailed_description": "该组件负责在桌面应用程序中创建系统托盘图标,并绑定右键菜单功能。支持通过托盘菜单项显示/隐藏主窗口、打开网络信息窗口、关于窗口以及退出程序。同时支持双击托盘图标打开主窗口。针对macOS和其他操作系统对菜单点击行为做了差异化处理。所有窗口配置(如标题、尺寸、URL)均从常量模块导入,确保配置集中化。", + "responsibilities": [ + "创建并初始化系统托盘图标及其上下文菜单", + "响应托盘菜单事件以控制应用程序窗口的显示状态", + "实现跨平台托盘行为适配(特别是macOS左键点击菜单的支持)", + "管理多个独立窗口的打开与聚焦逻辑", + "提供通用的窗口前置显示辅助函数" + ], + "interfaces": [], + "dependencies": [ + { + "name": "tauri::menu::Menu", + "path": "tauri::menu::Menu", + "is_external": true, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::menu::MenuItem", + "path": "tauri::menu::MenuItem", + "is_external": true, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::tray::TrayIconBuilder", + "path": "tauri::tray::TrayIconBuilder", + "is_external": true, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::Manager", + "path": "tauri::Manager", + "is_external": true, + "line_number": 4, + "dependency_type": "trait", + "version": null + }, + { + "name": "tauri::Runtime", + "path": "tauri::Runtime", + "is_external": true, + "line_number": 4, + "dependency_type": "trait", + "version": null + }, + { + "name": "tauri::Url", + "path": "tauri::Url", + "is_external": true, + "line_number": 5, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::WebviewUrl", + "path": "tauri::WebviewUrl", + "is_external": true, + "line_number": 5, + "dependency_type": "enum", + "version": null + }, + { + "name": "tauri::WebviewWindow", + "path": "tauri::WebviewWindow", + "is_external": true, + "line_number": 6, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::WebviewWindowBuilder", + "path": "tauri::WebviewWindowBuilder", + "is_external": true, + "line_number": 6, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::constrant::WINDOW_ABOUT_LABEL", + "path": "crate::constrant", + "is_external": false, + "line_number": 9, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_ABOUT_TITLE", + "path": "crate::constrant", + "is_external": false, + "line_number": 10, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_ABOUT_URL", + "path": "crate::constrant", + "is_external": false, + "line_number": 11, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_EXTERNAL_ENDPOINT_INFORMATION_LABEL", + "path": "crate::constrant", + "is_external": false, + "line_number": 12, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_EXTERNAL_ENDPOINT_INFORMATION_TITLE", + "path": "crate::constrant", + "is_external": false, + "line_number": 13, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_EXTERNAL_ENDPOINT_INFORMATION_URL", + "path": "crate::constrant", + "is_external": false, + "line_number": 14, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_MAIN_LABEL", + "path": "crate::constrant", + "is_external": false, + "line_number": 15, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_MAIN_TITLE", + "path": "crate::constrant", + "is_external": false, + "line_number": 16, + "dependency_type": "const", + "version": null + }, + { + "name": "crate::constrant::WINDOW_MAIN_URL", + "path": "crate::constrant", + "is_external": false, + "line_number": 17, + "dependency_type": "const", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 8.0, + "lines_of_code": 119, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.65, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024435, + "prompt_hash": "0a91b530f0180f66fddbf22980c585f4", + "token_usage": { + "input_tokens": 1532, + "output_tokens": 1182, + "total_tokens": 2714 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0bb4ab47c07e0a8fc173883264e45f26.json b/.litho/cache/ai_code_insight/0bb4ab47c07e0a8fc173883264e45f26.json new file mode 100644 index 0000000..2c45787 --- /dev/null +++ b/.litho/cache/ai_code_insight/0bb4ab47c07e0a8fc173883264e45f26.json @@ -0,0 +1,115 @@ +{ + "data": { + "code_dossier": { + "name": "EmbedWebView.svelte", + "file_path": "app/src/lib/widgets/EmbedWebView.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "嵌入式Web视图组件,用于加载外部网页内容并提供加载状态反馈", + "functions": [ + "onLoadEventHandler", + "onVisiblityChanged" + ], + "interfaces": [ + "EmbedWebViewProps" + ] + }, + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于在应用中嵌入外部网页。通过iframe实现内容加载,并结合自定义的可见性观察器和加载状态管理,优化用户体验。组件支持传入src属性指定目标URL,并暴露onLoadStart和onLoadEnd回调函数以通知页面加载生命周期。使用Skeleton框架的Progress组件显示加载进度动画,在内容完全加载前隐藏iframe以避免闪烁。组件采用$state和$effect.pre进行响应式状态管理,确保在属性变化时正确重置加载状态。", + "responsibilities": [ + "管理嵌入式网页的加载生命周期", + "提供可视化的加载状态指示", + "优化资源加载策略(仅当组件可见时才请求内容)", + "封装iframe的安全沙箱配置", + "向父组件传递加载状态事件" + ], + "interfaces": [ + { + "name": "EmbedWebViewProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "src", + "param_type": "string", + "is_optional": false, + "description": "要嵌入的网页URL" + }, + { + "name": "onLoadStart", + "param_type": "(src: string) => void", + "is_optional": true, + "description": "加载开始时的回调函数" + }, + { + "name": "onLoadEnd", + "param_type": "(src: string) => void", + "is_optional": true, + "description": "加载完成时的回调函数" + } + ], + "return_type": null, + "description": "嵌入式WebView组件的输入属性类型定义" + }, + { + "name": "onLoadEventHandler", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "void", + "description": "处理iframe加载完成事件的内部处理器" + } + ], + "dependencies": [ + { + "name": "observeVisiblity", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 1, + "dependency_type": "function", + "version": null + }, + { + "name": "LoadingStatus", + "path": "$lib/types/loading", + "is_external": false, + "line_number": 2, + "dependency_type": "enum", + "version": null + }, + { + "name": "EmbedWebViewProps", + "path": "./types", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "Progress", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 4, + "dependency_type": "component", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 79, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024478, + "prompt_hash": "0bb4ab47c07e0a8fc173883264e45f26", + "token_usage": { + "input_tokens": 907, + "output_tokens": 876, + "total_tokens": 1783 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0bb6effe1ad867e8004bd2ac0ffe1432.json b/.litho/cache/ai_code_insight/0bb6effe1ad867e8004bd2ac0ffe1432.json new file mode 100644 index 0000000..bab56d3 --- /dev/null +++ b/.litho/cache/ai_code_insight/0bb6effe1ad867e8004bd2ac0ffe1432.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/intelligent/src/lib.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件作为智能模块的根库文件,主要职责是组织和导出内部模块。当前仅公开导出了`article_processor`模块,表明其功能聚焦于文章处理相关的业务逻辑。该文件本身不包含具体实现,而是作为模块系统的基础入口,用于封装和暴露子模块。", + "responsibilities": [ + "作为智能处理模块的顶层组织单元", + "声明并导出内部功能模块(如文章处理器)", + "提供模块边界和命名空间管理", + "支持外部组件对内部子模块的访问控制" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024598, + "prompt_hash": "0bb6effe1ad867e8004bd2ac0ffe1432", + "token_usage": { + "input_tokens": 425, + "output_tokens": 358, + "total_tokens": 783 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0c2760672116db4e9f3ed65c8cea377c.json b/.litho/cache/ai_code_insight/0c2760672116db4e9f3ed65c8cea377c.json new file mode 100644 index 0000000..52c980f --- /dev/null +++ b/.litho/cache/ai_code_insight/0c2760672116db4e9f3ed65c8cea377c.json @@ -0,0 +1,77 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/hybrid-apis/tauri-regular/index.ts", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "Tauri 插件 API 调用的统一入口,封装 invoke 方法以支持插件通信。", + "functions": [ + "call" + ], + "interfaces": [ + "InvokeArgs", + "Option" + ] + }, + "detailed_description": "该组件作为 Tauri 框架中与原生插件交互的桥接层,通过封装 `@tauri-apps/api/core` 的 `invoke` 方法,提供类型安全的 RPC 调用接口。其主要功能是将前端逻辑与底层 Rust 插件解耦,使用字符串拼接方式构造插件命令(如 `plugin:feed-api|${methodName}`),并传递参数执行异步调用。当前仅暴露一个泛型函数 `call`,支持返回值类型参数化,提升调用端的类型推导能力。", + "responsibilities": [ + "提供统一的 Tauri 插件调用接口", + "封装底层 invoke 方法以简化上层使用", + "确保跨平台 API 调用的类型安全性", + "管理插件命名空间和方法路由" + ], + "interfaces": [ + { + "name": "InvokeArgs", + "interface_type": "type", + "visibility": "export", + "parameters": [], + "return_type": null, + "description": "允许传递对象、数字数组或二进制数据作为调用参数的联合类型。" + }, + { + "name": "Option", + "interface_type": "type", + "visibility": "export", + "parameters": [ + { + "name": "T", + "param_type": "unknown", + "is_optional": false, + "description": "泛型占位符,表示任意可选值类型" + } + ], + "return_type": null, + "description": "表示某值可能存在、为空或未定义的可选类型别名。" + } + ], + "dependencies": [ + { + "name": "@tauri-apps/api/core", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805714, + "prompt_hash": "0c2760672116db4e9f3ed65c8cea377c", + "token_usage": { + "input_tokens": 496, + "output_tokens": 638, + "total_tokens": 1134 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0d72ea10d9150578f945553974f094de.json b/.litho/cache/ai_code_insight/0d72ea10d9150578f945553974f094de.json new file mode 100644 index 0000000..1a76282 --- /dev/null +++ b/.litho/cache/ai_code_insight/0d72ea10d9150578f945553974f094de.json @@ -0,0 +1,131 @@ +{ + "data": { + "code_dossier": { + "name": "launcher.rs", + "file_path": "app/src-tauri/src/daemon/launcher.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "负责守护进程的启动逻辑,包含带错误忽略的启动接口和标准启动流程。", + "functions": [ + "launch_ignore_error", + "launch" + ], + "interfaces": [ + "launch_ignore_error", + "launch" + ] + }, + "detailed_description": "该组件实现了守护进程(daemon)的启动功能。核心逻辑是通过文件锁机制防止重复启动:首先获取指定名称的锁路径,尝试获取文件锁,若已锁定则说明守护进程已在运行,直接返回;否则释放锁并使用当前可执行文件路径结合参数重新启动守护进程。`launch_ignore_error` 提供了对错误静默处理的启动方式,仅在出错时记录日志。", + "responsibilities": [ + "管理守护进程的启动流程", + "通过文件锁防止守护进程重复启动", + "提供静默失败的安全启动接口", + "记录关键启动事件日志", + "调用自身二进制启动新进程实例" + ], + "interfaces": [ + { + "name": "launch", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "host_arg", + "param_type": "&str", + "is_optional": false, + "description": "传递给守护进程的主机参数" + }, + { + "name": "locker_monitor_name", + "param_type": "&str", + "is_optional": false, + "description": "用于生成锁文件路径的监控名称" + } + ], + "return_type": "anyhow::Result<()>", + "description": "安全地启动守护进程,若已被锁定则不重复启动" + }, + { + "name": "launch_ignore_error", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "host_arg", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "locker_monitor_name", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "()", + "description": "启动守护进程并在出错时仅记录日志而不中断调用方" + } + ], + "dependencies": [ + { + "name": "std::env", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "std::process::Command", + "path": null, + "is_external": false, + "line_number": 2, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "fslock::LockFile", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "third_party", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "third_party", + "version": null + }, + { + "name": "crate::daemon::locks::get_lock_path", + "path": "app/src-tauri/src/daemon/locks.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 41, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.55, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024430, + "prompt_hash": "0d72ea10d9150578f945553974f094de", + "token_usage": { + "input_tokens": 803, + "output_tokens": 893, + "total_tokens": 1696 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/0fbc1633e603348451135fc394ec54a2.json b/.litho/cache/ai_code_insight/0fbc1633e603348451135fc394ec54a2.json new file mode 100644 index 0000000..dc18ce8 --- /dev/null +++ b/.litho/cache/ai_code_insight/0fbc1633e603348451135fc394ec54a2.json @@ -0,0 +1,72 @@ +{ + "data": { + "code_dossier": { + "name": "context.ts", + "file_path": "app/src/routes/main/stores/context.ts", + "code_purpose": "model", + "importance_score": 0.8, + "description": "定义了应用上下文的状态结构,用于在不同组件间共享当前文章和信息流ID。", + "functions": [], + "interfaces": [ + "IContext" + ] + }, + "detailed_description": "该组件定义了一个名为 IContext 的接口,用于描述应用程序的上下文状态。它包含两个字段:currentFeedId(表示当前选中的信息流ID,可为 undefined)和 currentArticle(表示当前查看的文章对象,可为 null)。此类型主要用于 Svelte 或类似框架中的 store 模式中,以便在多个组件之间共享状态。通过使用 TypeScript 类型导出,确保类型安全并在编译时进行检查。", + "responsibilities": [ + "定义应用上下文的数据结构", + "提供类型安全的跨组件状态共享机制", + "封装当前信息流和文章的状态标识", + "支持响应式状态管理集成" + ], + "interfaces": [ + { + "name": "IContext", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "currentFeedId", + "param_type": "string | undefined", + "is_optional": true, + "description": "当前选中的信息流ID,可能未设置" + }, + { + "name": "currentArticle", + "param_type": "Article | null", + "is_optional": false, + "description": "当前显示的文章内容,允许为空值表示无文章加载" + } + ], + "return_type": null, + "description": "描述主界面状态下所需共享的应用上下文数据结构" + } + ], + "dependencies": [ + { + "name": "$lib/types/article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 1, + "dependency_type": "type import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 8, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805806, + "prompt_hash": "0fbc1633e603348451135fc394ec54a2", + "token_usage": { + "input_tokens": 444, + "output_tokens": 637, + "total_tokens": 1081 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/11369782ecef4ec381ae2141112bce2b.json b/.litho/cache/ai_code_insight/11369782ecef4ec381ae2141112bce2b.json new file mode 100644 index 0000000..6004d46 --- /dev/null +++ b/.litho/cache/ai_code_insight/11369782ecef4ec381ae2141112bce2b.json @@ -0,0 +1,63 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/scrap/src/lib.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "本模块为爬虫功能的核心聚合模块,通过公共子模块暴露RSS、搜索、模拟器、类型定义等功能,并私有化文章读取器等内部实现细节。", + "functions": [ + "read", + "read_inner", + "acquire_html", + "read_inner_from_response" + ], + "interfaces": [] + }, + "detailed_description": "该组件作为`scrap` crate的根模块,主要职责是组织和导出多个与网页抓取相关的功能模块。它将`rss`、`search`、`simulator`、`types`等模块公开,供外部调用者使用;同时将`article_reader`和`connector`设为私有,作为内部实现依赖。其核心逻辑集中在`article_reader`中:实现智能网页内容提取,支持自动重定向处理、HTML清洗(去除script/style)、基于LLM的内容重定向检测与递归抓取。系统结合了HTTP客户端策略控制、DOM解析(scraper)与AI代理决策能力,形成一个具备自适应能力的网页正文抽取管道。", + "responsibilities": [ + "聚合并导出网页抓取相关功能模块", + "协调内部模块(如article_reader、connector)完成网页内容获取", + "提供高层级API以支持RSS抓取、搜索及页面模拟操作", + "管理子模块之间的依赖关系与数据流", + "封装底层实现细节以提供清晰的外部接口" + ], + "interfaces": [], + "dependencies": [ + { + "name": "article_reader", + "path": "./crates/scrap/src/article_reader.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "connector", + "path": "./crates/scrap/src/connector.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.35, + "cohesion_score": 0.82 + } + }, + "timestamp": 1759024633, + "prompt_hash": "11369782ecef4ec381ae2141112bce2b", + "token_usage": { + "input_tokens": 1781, + "output_tokens": 685, + "total_tokens": 2466 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/11eb06cd23d3dc1bee9ce05ff404b6ef.json b/.litho/cache/ai_code_insight/11eb06cd23d3dc1bee9ce05ff404b6ef.json new file mode 100644 index 0000000..361394a --- /dev/null +++ b/.litho/cache/ai_code_insight/11eb06cd23d3dc1bee9ce05ff404b6ef.json @@ -0,0 +1,47 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/recorder/src/entity/mod.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust模块定义文件(mod.rs),其主要功能是作为实体模块的公共接口入口,用于组织和导出`article_record`子模块。它本身不包含具体实现,而是通过`pub mod article_record;`声明将`article_record`模块公开,供上级模块或外部代码引用。这种结构常见于Rust项目中用于模块化数据模型的组织。", + "responsibilities": [ + "作为实体模块的命名空间管理器", + "导出article_record子模块以供系统其他部分使用", + "维护实体层的模块结构清晰性" + ], + "interfaces": [], + "dependencies": [ + { + "name": "article_record", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805914, + "prompt_hash": "11eb06cd23d3dc1bee9ce05ff404b6ef", + "token_usage": { + "input_tokens": 410, + "output_tokens": 383, + "total_tokens": 793 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/126632c0362c17cbd5258dbef4bd5bcc.json b/.litho/cache/ai_code_insight/126632c0362c17cbd5258dbef4bd5bcc.json new file mode 100644 index 0000000..ee8109a --- /dev/null +++ b/.litho/cache/ai_code_insight/126632c0362c17cbd5258dbef4bd5bcc.json @@ -0,0 +1,68 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/llm/src/providers/types.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义LLM服务所需的核心数据模型与接口契约,包含AI生成参数配置和Completion服务抽象。", + "functions": [], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件定义了两个核心结构:AITargetOption 和 CompletionService。AITargetOption 是一个可序列化的配置结构体,用于封装 LLM 生成过程中的关键参数(如 temperature、top_p、top_k 等),并实现了 Default trait 提供默认值,便于在不同场景下统一行为。CompletionService 是一个异步 trait,抽象了 LLM 的文本生成能力,要求实现者提供一个返回 Future 的 completion 方法,支持异步调用模式,符合现代 Rust 异步编程范式。整体设计简洁,聚焦于类型安全与接口抽象,服务于上层 LLM 调用逻辑。", + "responsibilities": [ + "定义AI生成任务的参数配置模型", + "为LLM Completion能力提供统一的异步接口契约", + "确保配置项的可序列化与反序列化支持", + "提供合理的默认参数设置以降低使用复杂度", + "支持跨平台或服务间的数据交换格式兼容性" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "pub", + "parameters": [ + { + "name": "message", + "param_type": "String", + "is_optional": false, + "description": "用户输入的提示信息,将作为prompt传递给LLM" + } + ], + "return_type": "impl std::future::Future>", + "description": "LLM Generate服务代理,用于调用语言模型的completion能力。" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 28, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024560, + "prompt_hash": "126632c0362c17cbd5258dbef4bd5bcc", + "token_usage": { + "input_tokens": 617, + "output_tokens": 693, + "total_tokens": 1310 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/12aa64503c44747dbccc4b8a9b50c925.json b/.litho/cache/ai_code_insight/12aa64503c44747dbccc4b8a9b50c925.json new file mode 100644 index 0000000..fb6a2e2 --- /dev/null +++ b/.litho/cache/ai_code_insight/12aa64503c44747dbccc4b8a9b50c925.json @@ -0,0 +1,105 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/ollama/src/lib.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "Ollama程序的本地状态检测、远程健康检查及版本查询功能实现", + "functions": [ + "install", + "launch", + "request_running", + "request_version", + "query_platform", + "query_platform_by_remote", + "query_platform_by_process", + "parse_version", + "parse_is_running_from_version", + "create_shell_command" + ], + "interfaces": [ + "ProgramStatus", + "Information", + "APIVersionResponse" + ] + }, + "detailed_description": "该组件负责管理与Ollama AI运行时环境的交互,主要功能包括:1) 检测本地Ollama是否安装并运行;2) 查询本地或远程Ollama服务的版本信息;3) 统一入口`query_platform`根据本地进程状态决定使用本地CLI检测还是远程HTTP探测。支持跨平台(Windows/macOS/Linux)路径配置和shell命令构造。通过`reqwest`发起HTTP请求验证服务可用性,并解析CLI输出获取版本号和运行状态。", + "responsibilities": [ + "检测Ollama在本地系统的安装与运行状态", + "通过HTTP API探测远程Ollama服务的健康状况和版本", + "统一整合本地进程检查与远程API查询的结果", + "跨平台兼容性处理(不同操作系统的执行路径和shell命令)", + "解析Ollama CLI输出以提取版本信息和连接状态" + ], + "interfaces": [ + { + "name": "ProgramStatus", + "interface_type": "enum", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "表示Ollama程序的三种状态:未安装、已安装但未运行、正在运行" + }, + { + "name": "Information", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "封装Ollama实例的版本、状态和额外错误信息" + }, + { + "name": "APIVersionResponse", + "interface_type": "struct", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "用于反序列化远程API返回的版本响应" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "serialization", + "version": null + }, + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "runtime", + "version": null + }, + { + "name": "types", + "path": "types::llm_endpoint::LLMEndPoint", + "is_external": false, + "line_number": 3, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 8.0, + "lines_of_code": 140, + "number_of_functions": 10, + "number_of_classes": 3, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805650, + "prompt_hash": "12aa64503c44747dbccc4b8a9b50c925", + "token_usage": { + "input_tokens": 1462, + "output_tokens": 823, + "total_tokens": 2285 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/13d3311c57a4942491dd73a43a41311e.json b/.litho/cache/ai_code_insight/13d3311c57a4942491dd73a43a41311e.json new file mode 100644 index 0000000..5ed67f4 --- /dev/null +++ b/.litho/cache/ai_code_insight/13d3311c57a4942491dd73a43a41311e.json @@ -0,0 +1,144 @@ +{ + "data": { + "code_dossier": { + "name": "ContextMenuProvider.svelte", + "file_path": "app/src/lib/widgets/ContextMenuProvider.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "提供可复用的右键上下文菜单功能,支持动态菜单项渲染和位置自适应。", + "functions": [ + "showContextMenu", + "onHideMenu", + "getContextMenuDimension", + "wrapMenuPressHandler" + ], + "interfaces": [ + "MenuType" + ] + }, + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于在用户右键点击时显示一个上下文菜单。它通过接收`menus`属性来动态渲染菜单项,并根据浏览器窗口尺寸自动调整菜单位置以避免溢出。组件使用了Svelte的响应式状态管理($state)和片段(Snippet)机制,确保良好的封装性和可复用性。菜单项支持图标、文本和点击回调函数,并可通过`wrapMenuPressHandler`统一处理事件冒泡与关闭逻辑。", + "responsibilities": [ + "管理上下文菜单的显示与隐藏状态", + "计算并适配上下文菜单在视口中的安全位置", + "拦截右键事件并阻止默认行为", + "提供菜单项点击后的自动关闭机制", + "测量并存储上下文菜单的尺寸用于定位" + ], + "interfaces": [ + { + "name": "MenuType", + "interface_type": "type", + "visibility": "private", + "parameters": [ + { + "name": "name", + "param_type": "string", + "is_optional": false, + "description": "菜单项唯一标识,用于key映射或分隔线标记" + }, + { + "name": "onClick", + "param_type": "() => void", + "is_optional": false, + "description": "菜单项点击时触发的回调函数" + }, + { + "name": "displayText", + "param_type": "string", + "is_optional": false, + "description": "菜单项显示的文字内容" + }, + { + "name": "class", + "param_type": "string", + "is_optional": false, + "description": "图标CSS类名,如FontAwesome类" + } + ], + "return_type": null, + "description": "定义上下文菜单中单个菜单项的数据结构" + }, + { + "name": "showContextMenu", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "e", + "param_type": "MouseEvent", + "is_optional": false, + "description": "鼠标右键点击事件对象" + } + ], + "return_type": "boolean", + "description": "显示上下文菜单,阻止默认行为,设置坐标并防止重叠" + }, + { + "name": "onHideMenu", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "当点击页面其他区域时隐藏上下文菜单" + }, + { + "name": "getContextMenuDimension", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "node", + "param_type": "HTMLElement", + "is_optional": false, + "description": "上下文菜单DOM节点" + } + ], + "return_type": null, + "description": "获取并更新上下文菜单的实际宽高用于定位计算" + }, + { + "name": "wrapMenuPressHandler", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "handler", + "param_type": "() => void", + "is_optional": false, + "description": "原始菜单项点击处理器" + } + ], + "return_type": "(e: MouseEvent) => boolean", + "description": "包装菜单点击事件处理器,阻止冒泡并在执行后关闭菜单" + } + ], + "dependencies": [ + { + "name": "svelte", + "path": "svelte", + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 7.0, + "lines_of_code": 160, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.88 + } + }, + "timestamp": 1759024489, + "prompt_hash": "13d3311c57a4942491dd73a43a41311e", + "token_usage": { + "input_tokens": 1344, + "output_tokens": 1135, + "total_tokens": 2479 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/13d811cb5f01480847f5763393ca3e29.json b/.litho/cache/ai_code_insight/13d811cb5f01480847f5763393ca3e29.json new file mode 100644 index 0000000..e11df26 --- /dev/null +++ b/.litho/cache/ai_code_insight/13d811cb5f01480847f5763393ca3e29.json @@ -0,0 +1,83 @@ +{ + "data": { + "code_dossier": { + "name": "connector.rs", + "file_path": "crates/scrap/src/connector.rs", + "code_purpose": "util", + "importance_score": 0.8, + "description": "HTTP客户端构建工具,用于创建带有默认请求头和配置的reqwest Client实例", + "functions": [ + "new_builder", + "new" + ], + "interfaces": [ + "ClientOption" + ] + }, + "detailed_description": "该组件是一个HTTP客户端构造器工具,主要职责是根据提供的选项(如主机地址、用户代理)创建一个预配置的reqwest::ClientBuilder或Client实例。它设置了标准的HTTP请求头(User-Agent, Accept, Encoding等),启用了Cookie存储、超时控制和压缩支持,适用于网络爬虫场景下的HTTP请求发起。", + "responsibilities": [ + "封装HTTP客户端的创建逻辑", + "设置标准化的请求头以模拟浏览器行为", + "提供可配置的客户端构建选项", + "管理HTTP连接的默认行为(超时、压缩、Cookie等)" + ], + "interfaces": [ + { + "name": "ClientOption", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "user_agent", + "param_type": "Option", + "is_optional": true, + "description": "自定义User-Agent字符串" + }, + { + "name": "host", + "param_type": "String", + "is_optional": false, + "description": "目标主机地址" + } + ], + "return_type": null, + "description": "HTTP客户端配置选项" + } + ], + "dependencies": [ + { + "name": "reqwest", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "http_client", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "error_handling", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 43, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805575, + "prompt_hash": "13d811cb5f01480847f5763393ca3e29", + "token_usage": { + "input_tokens": 899, + "output_tokens": 560, + "total_tokens": 1459 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/143649b2e7df919a5a61a676170f594b.json b/.litho/cache/ai_code_insight/143649b2e7df919a5a61a676170f594b.json new file mode 100644 index 0000000..e6481e9 --- /dev/null +++ b/.litho/cache/ai_code_insight/143649b2e7df919a5a61a676170f594b.json @@ -0,0 +1,89 @@ +{ + "data": { + "code_dossier": { + "name": "SearchBar.svelte", + "file_path": "app/src/routes/main/widgets/SearchBar.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "搜索栏UI组件,支持输入绑定和刷新操作。", + "functions": [], + "interfaces": [ + "SearchBarProps" + ] + }, + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于呈现主界面中的搜索栏。它接收`store`和`articles_store`作为属性,其中`store.filterText`双向绑定到搜索输入框,实现用户输入的实时过滤。占位符文本通过国际化函数`$_`动态获取。当当前视图未指定具体feed时(!articles_store.isFeedSpecified),显示一个刷新按钮,点击后调用`articles_store.updateFeeds`方法更新数据源。", + "responsibilities": [ + "提供用户搜索输入界面", + "将用户输入绑定到状态管理store", + "根据数据源状态条件性渲染刷新按钮", + "支持多语言占位符文本显示", + "触发文章列表的数据更新操作" + ], + "interfaces": [ + { + "name": "SearchBarProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "store", + "param_type": "any", + "is_optional": false, + "description": "包含filterText的状态对象" + }, + { + "name": "articles_store", + "param_type": "ArticlesStore", + "is_optional": false, + "description": "文章数据管理store,提供updateFeeds方法和isFeedSpecified状态" + } + ], + "return_type": null, + "description": "SearchBar组件的属性类型定义" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "SearchBarProps", + "path": "./types", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "IconRefresh", + "path": "lucide-svelte/icons/refresh-cw", + "is_external": true, + "line_number": 4, + "dependency_type": "component", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 26, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805830, + "prompt_hash": "143649b2e7df919a5a61a676170f594b", + "token_usage": { + "input_tokens": 623, + "output_tokens": 654, + "total_tokens": 1277 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1445c7ab0cb786bdd8cdfbf520276166.json b/.litho/cache/ai_code_insight/1445c7ab0cb786bdd8cdfbf520276166.json new file mode 100644 index 0000000..aca00bc --- /dev/null +++ b/.litho/cache/ai_code_insight/1445c7ab0cb786bdd8cdfbf520276166.json @@ -0,0 +1,159 @@ +{ + "data": { + "code_dossier": { + "name": "article_record.rs", + "file_path": "crates/recorder/src/entity/article_record.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义文章记录的数据模型,用于存储源链接、标题、内容版本、阅读状态等信息。", + "functions": [], + "interfaces": [ + "Model", + "Relation", + "ActiveModelBehavior" + ] + }, + "detailed_description": "该组件是SeaORM实体模型,代表数据库中`t_article_record`表的结构。它包含文章的元数据(如标题、源链接)、多个版本的内容(原始提取、优化后、熔合后)、发布与创建日期、阅读状态和收藏状态。主要用于持久化文章抓取与处理结果,支持后续的内容展示与用户交互功能。", + "responsibilities": [ + "定义文章记录的数据库表结构", + "提供序列化与反序列化能力以支持数据传输", + "维护文章内容的多种形态(原始、优化、导读等)", + "管理文章的阅读状态与分组归属" + ], + "interfaces": [ + { + "name": "Model", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "id", + "param_type": "i32", + "is_optional": false, + "description": null + }, + { + "name": "source_link", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "title", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "purged_content", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "head_read", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "optimized_content", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "melted_content", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "published_at", + "param_type": "chrono::NaiveDate", + "is_optional": false, + "description": null + }, + { + "name": "created_at", + "param_type": "chrono::NaiveDate", + "is_optional": false, + "description": null + }, + { + "name": "has_read", + "param_type": "bool", + "is_optional": false, + "description": null + }, + { + "name": "is_favorite", + "param_type": "bool", + "is_optional": false, + "description": null + }, + { + "name": "group_id", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "文章记录的核心数据结构" + }, + { + "name": "Relation", + "interface_type": "enum", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "定义与其他实体的关系(当前为空)" + }, + { + "name": "ActiveModelBehavior", + "interface_type": "trait_impl", + "visibility": "impl", + "parameters": [], + "return_type": null, + "description": "ActiveModel的行为实现(默认)" + } + ], + "dependencies": [ + { + "name": "sea_orm", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "database_orm", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 28, + "number_of_functions": 0, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024640, + "prompt_hash": "1445c7ab0cb786bdd8cdfbf520276166", + "token_usage": { + "input_tokens": 664, + "output_tokens": 887, + "total_tokens": 1551 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/16d65f6a97cf7bb81899e8e9abf10d32.json b/.litho/cache/ai_code_insight/16d65f6a97cf7bb81899e8e9abf10d32.json new file mode 100644 index 0000000..0ac4250 --- /dev/null +++ b/.litho/cache/ai_code_insight/16d65f6a97cf7bb81899e8e9abf10d32.json @@ -0,0 +1,77 @@ +{ + "data": { + "code_dossier": { + "name": "locks.rs", + "file_path": "app/src-tauri/src/daemon/locks.rs", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供守护进程相关的文件锁路径管理功能,用于协调后台任务的并发执行。", + "functions": [ + "get_lock_path" + ], + "interfaces": [ + "get_lock_path" + ] + }, + "detailed_description": "该组件定义了一个常量LOCK_FEEDS_SCHEDULE_UPDATE和一个函数get_lock_path。其主要作用是为守护进程(daemon)系统生成特定锁文件的路径,确保不同后台任务之间的协调运行,避免资源竞争。函数通过调用recorder模块中的工具方法,将锁文件定位在应用程序数据目录下的'daemons'子目录中,实现了路径的集中管理和隔离。", + "responsibilities": [ + "定义守护进程使用的锁文件名称常量", + "生成指定锁类型的完整文件路径", + "集成应用数据目录管理策略", + "支持多守护进程任务的并发控制机制", + "提供简洁的锁路径访问接口" + ], + "interfaces": [ + { + "name": "get_lock_path", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "locker_name", + "param_type": "&str", + "is_optional": false, + "description": "锁的名称标识" + } + ], + "return_type": "PathBuf", + "description": "根据锁名称生成对应的完整路径,位于daemons子目录下" + } + ], + "dependencies": [ + { + "name": "std::path::PathBuf", + "path": "std::path::PathBuf", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "recorder::path::get_appdata_file_in_dir", + "path": "recorder::path::get_appdata_file_in_dir", + "is_external": false, + "line_number": 3, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 9, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805971, + "prompt_hash": "16d65f6a97cf7bb81899e8e9abf10d32", + "token_usage": { + "input_tokens": 466, + "output_tokens": 629, + "total_tokens": 1095 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/184bb05e0d17bd85030e0cd1ab8da47d.json b/.litho/cache/ai_code_insight/184bb05e0d17bd85030e0cd1ab8da47d.json new file mode 100644 index 0000000..0ffb205 --- /dev/null +++ b/.litho/cache/ai_code_insight/184bb05e0d17bd85030e0cd1ab8da47d.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "capabilities.json", + "file_path": "app/src-tauri/gen/schemas/capabilities.json", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "定义应用程序不同运行环境下的能力集,包括权限、窗口访问和平台限制。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个JSON配置文件,用于声明Tauri应用中的各种capability(能力),每个capability包含标识符、描述、本地/远程策略、允许的窗口列表、权限列表以及可选的平台限制。主要用于安全模型控制,决定特定上下文(如主窗口或Web视图)可以执行哪些系统级操作。", + "responsibilities": [ + "定义应用的安全能力边界", + "管理不同功能模块的权限分配", + "控制capability对特定窗口的可见性与可用性", + "支持多平台的能力差异化配置" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024661, + "prompt_hash": "184bb05e0d17bd85030e0cd1ab8da47d", + "token_usage": { + "input_tokens": 763, + "output_tokens": 400, + "total_tokens": 1163 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1998bbf6a543ea876c074b34b7545191.json b/.litho/cache/ai_code_insight/1998bbf6a543ea876c074b34b7545191.json new file mode 100644 index 0000000..1a26896 --- /dev/null +++ b/.litho/cache/ai_code_insight/1998bbf6a543ea876c074b34b7545191.json @@ -0,0 +1,78 @@ +{ + "data": { + "code_dossier": { + "name": "llm_endpoint.rs", + "file_path": "crates/types/src/llm_endpoint.rs", + "code_purpose": "api", + "importance_score": 0.8, + "description": "定义与LLM服务(特别是Ollama)通信的端点结构,包含API基础URL、模型名称及聊天/生成接口路径。", + "functions": [ + "get_api_chat_completion", + "get_api_generate_completion" + ], + "interfaces": [ + "LLMEndPoint" + ] + }, + "detailed_description": "该组件定义了一个名为LLMEndPoint的结构体,用于封装与本地或远程LLM服务(目前仅支持Ollama)进行交互所需的配置信息。它包括API的基础URL、聊天和文本生成接口的具体路径以及使用的模型名称。通过实现Default trait,提供了默认配置,便于在开发或测试环境中快速初始化。此外,提供了两个方法来动态构建完整的API请求地址,增强了使用灵活性。", + "responsibilities": [ + "定义LLM服务端点的数据结构", + "提供默认的Ollama服务配置", + "构建完整的API请求URL", + "支持序列化与反序列化以适应网络传输" + ], + "interfaces": [ + { + "name": "LLMEndPoint", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "表示LLM服务端点的核心数据结构,包含API地址、路径和模型名。" + }, + { + "name": "get_api_chat_completion", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "String", + "description": "返回完整的聊天接口URL。" + }, + { + "name": "get_api_generate_completion", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "String", + "description": "返回完整的文本生成接口URL。" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 55, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758801090, + "prompt_hash": "1998bbf6a543ea876c074b34b7545191", + "token_usage": { + "input_tokens": 838, + "output_tokens": 653, + "total_tokens": 1491 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1a1a9b30ee6d8ae7b1da717e5300e481.json b/.litho/cache/ai_code_insight/1a1a9b30ee6d8ae7b1da717e5300e481.json new file mode 100644 index 0000000..83f1695 --- /dev/null +++ b/.litho/cache/ai_code_insight/1a1a9b30ee6d8ae7b1da717e5300e481.json @@ -0,0 +1,106 @@ +{ + "data": { + "code_dossier": { + "name": "sprite.svelte.ts", + "file_path": "app/src/routes/main/stores/sprite.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "负责管理侧边栏对话窗口的状态与交互逻辑,封装了与文章助手的聊天功能。", + "functions": [ + "create", + "send", + "toggle", + "cleanUp" + ], + "interfaces": [ + "StoreType", + "ConversationInput", + "ConversationMessage" + ] + }, + "detailed_description": "该组件是一个Svelte状态存储模块,用于管理一个可打开/关闭的对话界面(Sprite)的状态。它维护了对话历史记录、加载状态和可见性,并提供了发送消息给文章助手的功能。当用户发送输入时,组件会调用外部API进行处理,并将用户和系统的消息依次添加到历史中。同时通过loading store管理异步请求状态,在出错时进行错误捕获与报告。清理逻辑会在关闭窗口时重置历史和加载状态。", + "responsibilities": [ + "管理对话窗口的打开/关闭状态", + "维护与展示对话消息的历史记录", + "协调与文章助手API的异步通信", + "管理UI加载与错误状态", + "提供状态清理机制以释放资源" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": null, + "description": "定义了对外暴露的状态结构和方法集合,包括opened、history、loading、toggle、send等" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "exported", + "parameters": [ + { + "name": "context", + "param_type": "IContext", + "is_optional": false, + "description": "上下文对象,包含当前文章等运行时信息" + } + ], + "return_type": "StoreType", + "description": "工厂函数,用于创建并初始化Store实例" + }, + { + "name": "send", + "interface_type": "function", + "visibility": "internal", + "parameters": [ + { + "name": "input", + "param_type": "ConversationInput", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "Promise", + "description": "发送消息并更新对话历史,返回是否成功" + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": true, + "line_number": 4, + "dependency_type": "service", + "version": null + }, + { + "name": "loading.svelte", + "path": "./loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "store", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 90, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.4, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024179, + "prompt_hash": "1a1a9b30ee6d8ae7b1da717e5300e481", + "token_usage": { + "input_tokens": 927, + "output_tokens": 845, + "total_tokens": 1772 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1aff5469f8999556d9085f189b75755b.json b/.litho/cache/ai_code_insight/1aff5469f8999556d9085f189b75755b.json new file mode 100644 index 0000000..8e9e400 --- /dev/null +++ b/.litho/cache/ai_code_insight/1aff5469f8999556d9085f189b75755b.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "tauri.conf.json", + "file_path": "app/src-tauri/tauri.conf.json", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Tauri 框架的主配置文件,定义了应用元信息、构建流程、窗口设置、安全策略和打包选项。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该配置文件用于定制基于 Tauri 构建的桌面应用程序行为。它定义了应用的基本信息(如名称、版本、标识符),构建指令(开发与生产环境命令及前端资源路径),应用运行时的窗口配置(包括主窗口和预留窗口的尺寸与可见性),以及打包发布时的元数据(如版权、分类、图标等)。同时启用了 `tauri-plugin-feed-api` 插件并设置了请求超时时间,确保 RSS 等内容获取服务稳定运行。CSP 安全策略被禁用(设为 null),可能出于开发灵活性考虑,但在生产环境中存在安全风险。", + "responsibilities": [ + "管理应用元数据(名称、版本、标识符)", + "配置开发与构建生命周期命令", + "定义应用窗口布局与初始状态", + "控制应用打包行为与分发信息", + "集成并配置 Tauri 插件" + ], + "interfaces": [], + "dependencies": [ + { + "name": "tauri-plugin-feed-api", + "path": null, + "is_external": true, + "line_number": 58, + "dependency_type": "plugin", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 62, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.1, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024650, + "prompt_hash": "1aff5469f8999556d9085f189b75755b", + "token_usage": { + "input_tokens": 768, + "output_tokens": 569, + "total_tokens": 1337 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1b754b203996771c5a6dd71534bbdc15.json b/.litho/cache/ai_code_insight/1b754b203996771c5a6dd71534bbdc15.json new file mode 100644 index 0000000..400d2bb --- /dev/null +++ b/.litho/cache/ai_code_insight/1b754b203996771c5a6dd71534bbdc15.json @@ -0,0 +1,77 @@ +{ + "data": { + "code_dossier": { + "name": "loading.svelte.ts", + "file_path": "app/src/routes/main/stores/loading.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "实现一个响应式加载状态管理器,用于跟踪操作的加载、完成、错误等状态,并提供可读的状态文本。", + "functions": [ + "create" + ], + "interfaces": [ + "StoreType", + "Status" + ] + }, + "detailed_description": "该组件定义了一个基于Svelte状态管理机制的加载状态存储(Loading Store),通过`create`函数返回一个包含加载控制方法和只读状态属性的对象。支持四种状态:未设定(Unset)、加载中(Loading)、已完成(Completed)和错误(Error)。每个状态变更都会触发UI更新,且提供了`statusText`计算属性以返回对应状态的人性化中文描述,适用于前端界面中的加载提示展示。", + "responsibilities": [ + "管理异步操作的加载状态生命周期", + "提供统一的加载状态变更接口(load/unset/complete/error)", + "暴露可读的状态码与人类可读的状态文本映射", + "实现响应式状态更新以支持Svelte组件绑定" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义加载状态store的公开接口,包括控制方法和状态访问器" + }, + { + "name": "Status", + "interface_type": "enum", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "表示加载过程中的不同状态枚举值" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "initStatus", + "param_type": "Status", + "is_optional": true, + "description": "初始状态,默认为Status.Unset" + } + ], + "return_type": "StoreType", + "description": "创建并返回一个新的加载状态store实例" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 61, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024533, + "prompt_hash": "1b754b203996771c5a6dd71534bbdc15", + "token_usage": { + "input_tokens": 663, + "output_tokens": 701, + "total_tokens": 1364 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1cfacab2cbc2c6bd94c7d78ce762a3eb.json b/.litho/cache/ai_code_insight/1cfacab2cbc2c6bd94c7d78ce762a3eb.json new file mode 100644 index 0000000..71e3ddd --- /dev/null +++ b/.litho/cache/ai_code_insight/1cfacab2cbc2c6bd94c7d78ce762a3eb.json @@ -0,0 +1,251 @@ +{ + "data": { + "code_dossier": { + "name": "bing.rs", + "file_path": "crates/scrap/src/search/bing.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现Bing搜索引擎的网页内容抓取与解析功能,支持通过关键词搜索并提取文章标题、链接及摘要信息。集成HTML清洗、文本抽取和LLM内容处理流程。", + "functions": [ + "new", + "prepare_target_sources", + "convert", + "search_by_words" + ], + "interfaces": [ + "IProvider" + ] + }, + "detailed_description": "该组件实现了针对Bing搜索结果页的内容爬取与结构化提取逻辑。主要流程包括:1) 构造带编码关键词的Bing搜索URL;2) 使用reqwest客户端或Tauri运行时发起HTTP请求获取HTML;3) 利用scraper库解析DOM,通过CSS选择器提取每条搜索结果的标题、描述和链接;4) 对提取的链接进一步调用article_reader模块进行正文抓取与内容提炼;5) 将原始搜索片段与最终抓取内容整合为Article对象列表返回。整个过程支持可配置的LLM内容处理区域,并记录日志便于调试。", + "responsibilities": [ + "构建Bing搜索URL并发送查询请求", + "解析Bing搜索结果页面的HTML结构", + "提取搜索结果中的标题、摘要和链接信息", + "协调调用文章内容抓取服务以获取完整正文", + "将非结构化搜索结果转换为标准化Article数据模型" + ], + "interfaces": [ + { + "name": "new", + "interface_type": "constructor", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定用于内容处理的LLM区域配置" + } + ], + "return_type": "anyhow::Result", + "description": "初始化Provider实例,配置HTTP客户端和HTML选择器" + }, + { + "name": "prepare_target_sources", + "interface_type": "method", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "&str", + "is_optional": false, + "description": "原始Bing搜索结果HTML文本" + } + ], + "return_type": "anyhow::Result>", + "description": "从HTML中提取基础搜索结果项(仅含标题、链接、头部阅读提示)" + }, + { + "name": "convert", + "interface_type": "method", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "String", + "is_optional": false, + "description": "待处理的搜索结果HTML" + } + ], + "return_type": "anyhow::Result>", + "description": "将基础搜索结果扩展为包含全文内容的Article对象" + }, + { + "name": "search_by_words", + "interface_type": "trait_method", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "要搜索的关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri应用句柄,用于在GUI环境中执行网络请求" + } + ], + "return_type": "anyhow::Result>", + "description": "主入口方法:执行关键词搜索、获取结果并完成全流程解析" + }, + { + "name": "Provider", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "封装Bing搜索提供者的状态,包括HTTP客户端、选择器和LLM配置" + }, + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "统一搜索提供者接口契约" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "html_parser", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "desktop_framework", + "version": null + }, + { + "name": "urlencoding", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "utility", + "version": null + }, + { + "name": "types::Article", + "path": "types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + }, + { + "name": "crate::connector::ClientOption", + "path": "crate::connector", + "is_external": false, + "line_number": 9, + "dependency_type": "configuration", + "version": null + }, + { + "name": "crate::search::selector_extensions::ElementSelector", + "path": "crate::search::selector_extensions", + "is_external": false, + "line_number": 10, + "dependency_type": "extension", + "version": null + }, + { + "name": "crate::search::types::IProvider", + "path": "crate::search::types", + "is_external": false, + "line_number": 11, + "dependency_type": "interface", + "version": null + }, + { + "name": "crate::search::utils::trim_head_read_days_ago", + "path": "crate::search::utils", + "is_external": false, + "line_number": 12, + "dependency_type": "utility", + "version": null + }, + { + "name": "crate::search::utils::trim_html_with_script_and_style", + "path": "crate::search::utils", + "is_external": false, + "line_number": 12, + "dependency_type": "utility", + "version": null + }, + { + "name": "crate::simulator::scrap_text_by_url", + "path": "crate::simulator", + "is_external": false, + "line_number": 13, + "dependency_type": "service", + "version": null + }, + { + "name": "crate::article_reader", + "path": "crate::", + "is_external": false, + "line_number": 14, + "dependency_type": "service", + "version": null + }, + { + "name": "crate::connector", + "path": "crate::connector", + "is_external": false, + "line_number": 15, + "dependency_type": "service", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 7.0, + "lines_of_code": 134, + "number_of_functions": 4, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6875, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805479, + "prompt_hash": "1cfacab2cbc2c6bd94c7d78ce762a3eb", + "token_usage": { + "input_tokens": 1629, + "output_tokens": 1700, + "total_tokens": 3329 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1d1497c3971d256c8d887048a62f3ed9.json b/.litho/cache/ai_code_insight/1d1497c3971d256c8d887048a62f3ed9.json new file mode 100644 index 0000000..a1462d3 --- /dev/null +++ b/.litho/cache/ai_code_insight/1d1497c3971d256c8d887048a62f3ed9.json @@ -0,0 +1,66 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/articles/index.svelte.ts", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "文章模块的状态管理控制器,协调搜索与列表子模块的创建和依赖注入", + "functions": [ + "create" + ], + "interfaces": [] + }, + "detailed_description": "该组件是文章功能模块的核心状态管理协调器,负责初始化并组合两个关键子模块:搜索(search)和列表(list)。它通过`create`工厂函数接收上游任务状态(TasksStoreType),并将其实例化后的搜索模块传递给列表模块,形成依赖注入链。这种设计实现了关注点分离,使各子模块可独立维护,同时由父模块统一装配。", + "responsibilities": [ + "作为文章模块的状态管理入口点", + "协调搜索和列表子store的创建与组装", + "实现跨store的依赖注入(将search实例注入list)", + "封装子模块的初始化逻辑,提供简洁的外部接口" + ], + "interfaces": [], + "dependencies": [ + { + "name": "createSearch", + "path": "./search/index.svelte", + "is_external": false, + "line_number": 1, + "dependency_type": "function", + "version": null + }, + { + "name": "createList", + "path": "./list/index.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "function", + "version": null + }, + { + "name": "TasksStoreType", + "path": "../tasks.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 16, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805797, + "prompt_hash": "1d1497c3971d256c8d887048a62f3ed9", + "token_usage": { + "input_tokens": 495, + "output_tokens": 545, + "total_tokens": 1040 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1f3c0dc04e63c9306d560b83929bfdef.json b/.litho/cache/ai_code_insight/1f3c0dc04e63c9306d560b83929bfdef.json new file mode 100644 index 0000000..20fdb16 --- /dev/null +++ b/.litho/cache/ai_code_insight/1f3c0dc04e63c9306d560b83929bfdef.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "constrant.rs", + "file_path": "app/src-tauri/src/constrant.rs", + "code_purpose": "config", + "importance_score": 0.6, + "description": "定义了应用程序中多个窗口的标签、URL和标题常量,用于统一管理和配置Tauri应用的窗口元信息。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个纯配置模块,通过Rust的const关键字定义了一系列字符串常量,主要用于Tauri桌面应用中不同窗口的标识(label)、路由地址(url)和显示标题(title)。这些常量集中管理了UI层的关键元数据,避免在代码各处硬编码字符串,提升可维护性。当前定义了主窗口、外部端点信息窗口和关于窗口三组配置项。", + "responsibilities": [ + "集中管理应用窗口的唯一标识符(label)", + "统一维护窗口的导航路径(URL)配置", + "定义窗口的用户界面显示标题", + "提供编译时常量以确保类型安全和性能优化", + "避免魔法字符串,提高代码可读性和可维护性" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 11, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805957, + "prompt_hash": "1f3c0dc04e63c9306d560b83929bfdef", + "token_usage": { + "input_tokens": 537, + "output_tokens": 476, + "total_tokens": 1013 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1f59c370079b48d193d6a414f8cec863.json b/.litho/cache/ai_code_insight/1f59c370079b48d193d6a414f8cec863.json new file mode 100644 index 0000000..44bbd6a --- /dev/null +++ b/.litho/cache/ai_code_insight/1f59c370079b48d193d6a414f8cec863.json @@ -0,0 +1,173 @@ +{ + "data": { + "code_dossier": { + "name": "AISpritePanel.svelte", + "file_path": "app/src/routes/main/widgets/AISpritePanel.svelte", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "AI助手侧边栏交互面板,提供聊天界面、消息发送、状态展示等功能", + "functions": [ + "scrollChatBottom", + "addMessage", + "onPromptKeydown", + "toDateText" + ], + "interfaces": [ + "AISpriteProps" + ] + }, + "detailed_description": "该组件实现了一个浮动式AI助手对话面板,支持用户与AI进行文本交互。面板包含历史消息展示区(区分用户和AI消息)、实时加载指示器、输入框及发送按钮。通过store注入状态管理,控制面板显隐、消息历史、加载状态等。支持回车发送消息,并在发送时进行非空和防重复提交校验。使用Markdown渲染AI回复内容,具备国际化支持,UI基于Skeleton框架构建。", + "responsibilities": [ + "管理AI对话面板的显示与隐藏状态", + "处理用户输入并调用store发送消息", + "展示消息历史记录并区分用户与AI角色", + "提供加载状态反馈和用户操作提示", + "处理键盘事件(如回车发送)并滚动到底部" + ], + "interfaces": [ + { + "name": "AISpriteProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "store", + "param_type": "AISpriteProps['store']", + "is_optional": false, + "description": "包含opened、isLoading、history、send、toggle等方法的状态管理对象" + } + ], + "return_type": null, + "description": "定义组件所需属性接口" + }, + { + "name": "scrollChatBottom", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "behavior", + "param_type": "'auto' | 'instant' | 'smooth'", + "is_optional": true, + "description": "滚动行为动画类型" + } + ], + "return_type": "void", + "description": "将聊天容器滚动到底部" + }, + { + "name": "addMessage", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "Promise", + "description": "处理消息发送逻辑,包括验证、清空输入、调用store.send" + }, + { + "name": "onPromptKeydown", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "event", + "param_type": "KeyboardEvent", + "is_optional": false, + "description": "键盘事件对象" + } + ], + "return_type": "void", + "description": "监听输入框按键事件,回车触发发送" + }, + { + "name": "toDateText", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "timestamp", + "param_type": "string", + "is_optional": false, + "description": "时间戳字符串" + } + ], + "return_type": "string", + "description": "将时间戳转换为本地化日期时间字符串" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "AISpriteProps", + "path": "../widgets/types", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 4, + "dependency_type": "ui", + "version": null + }, + { + "name": "lucide-svelte", + "path": "lucide-svelte", + "is_external": true, + "line_number": 5, + "dependency_type": "icon", + "version": null + }, + { + "name": "Markdown", + "path": "$lib/widgets/Markdown.svelte", + "is_external": false, + "line_number": 6, + "dependency_type": "component", + "version": null + }, + { + "name": "toaster", + "path": "../stores/toast", + "is_external": false, + "line_number": 7, + "dependency_type": "store", + "version": null + }, + { + "name": "svelte", + "path": "svelte", + "is_external": true, + "line_number": 9, + "dependency_type": "framework", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 9.0, + "lines_of_code": 186, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.583, + "cohesion_score": 0.82 + } + }, + "timestamp": 1758801051, + "prompt_hash": "1f59c370079b48d193d6a414f8cec863", + "token_usage": { + "input_tokens": 1756, + "output_tokens": 1145, + "total_tokens": 2901 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/1fcf292b999dccf0c8214ea316144918.json b/.litho/cache/ai_code_insight/1fcf292b999dccf0c8214ea316144918.json new file mode 100644 index 0000000..0b3394d --- /dev/null +++ b/.litho/cache/ai_code_insight/1fcf292b999dccf0c8214ea316144918.json @@ -0,0 +1,158 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/index.svelte.ts", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "核心状态管理控制器,协调文章、任务、信息源等子模块的状态与行为", + "functions": [ + "createStore", + "setCurrentArticle", + "getCurrentArticle", + "scheduleUpdate", + "onSelectToday", + "onSelectWeekend", + "onSelectFavorite", + "onSelectUnread", + "setCurrentFeedId" + ], + "interfaces": [ + "IContext" + ] + }, + "detailed_description": "该组件是Svelte应用中的核心状态容器,通过`createStore`函数创建一个全局共享的状态管理实例。它整合了feeds、articles、tasks、reader和sprite等多个子store,并对外暴露统一的访问接口。组件负责维护当前选中的feed和文章状态,提供feed切换、内容更新调度、文章获取等关键功能。特别地,通过$effect实现了启动时的自动初始化逻辑:刷新feeds并默认选中今日feed,根据最新文章日期决定是否触发全量更新。组件广泛使用Svelte的反应式语法($state, $derived, $effect),体现了典型的响应式编程模式。", + "responsibilities": [ + "作为主页面的核心状态管理中枢,协调多个子状态模块(feeds/articles/tasks等)", + "维护当前选中的信息源(Feed)和文章(Article)的全局状态", + "提供信息源切换、内容更新调度、文章读取等核心业务操作接口", + "实现应用启动时的自动初始化与数据预加载逻辑", + "处理跨模块的状态同步与依赖注入(通过context机制)" + ], + "interfaces": [ + { + "name": "IContext", + "interface_type": "type", + "visibility": "imported", + "parameters": [], + "return_type": null, + "description": "定义了上下文对象的结构,包含currentArticle和currentFeedId两个只读属性" + } + ], + "dependencies": [ + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 1, + "dependency_type": "type", + "version": null + }, + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 3, + "dependency_type": "variable", + "version": null + }, + { + "name": "isRecentFamilyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 4, + "dependency_type": "function", + "version": null + }, + { + "name": "isSpecifyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 5, + "dependency_type": "function", + "version": null + }, + { + "name": "SPECIFY_FEED_IDSET", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 6, + "dependency_type": "constant", + "version": null + }, + { + "name": "createArticles", + "path": "./articles/index.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "function", + "version": null + }, + { + "name": "createTasks", + "path": "./tasks.svelte", + "is_external": false, + "line_number": 8, + "dependency_type": "function", + "version": null + }, + { + "name": "createFeeds", + "path": "./feeds.svelte", + "is_external": false, + "line_number": 9, + "dependency_type": "function", + "version": null + }, + { + "name": "createReader", + "path": "./reader.svelte", + "is_external": false, + "line_number": 10, + "dependency_type": "function", + "version": null + }, + { + "name": "createSprite", + "path": "./sprite.svelte", + "is_external": false, + "line_number": 11, + "dependency_type": "function", + "version": null + }, + { + "name": "currentDateText", + "path": "$lib/utils/date", + "is_external": false, + "line_number": 12, + "dependency_type": "function", + "version": null + }, + { + "name": "IContext", + "path": "./context", + "is_external": false, + "line_number": 13, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 14.0, + "lines_of_code": 203, + "number_of_functions": 14, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.68, + "cohesion_score": 0.82 + } + }, + "timestamp": 1758801026, + "prompt_hash": "1fcf292b999dccf0c8214ea316144918", + "token_usage": { + "input_tokens": 1813, + "output_tokens": 1118, + "total_tokens": 2931 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/21f7ea14dab5aaddb082bf74224314e0.json b/.litho/cache/ai_code_insight/21f7ea14dab5aaddb082bf74224314e0.json new file mode 100644 index 0000000..003c1f8 --- /dev/null +++ b/.litho/cache/ai_code_insight/21f7ea14dab5aaddb082bf74224314e0.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "loading.ts", + "file_path": "app/src/lib/types/loading.ts", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义加载状态的枚举类型,用于表示异步操作的不同阶段", + "functions": [], + "interfaces": [ + "LoadingStatus" + ] + }, + "detailed_description": "该组件定义了一个名为LoadingStatus的枚举类型,包含三个状态值:Loading(加载中)、Completed(已完成)和Error(出错)。该枚举用于统一管理系统中所有异步操作的加载状态,为前端UI提供标准化的状态标识,便于根据不同的加载状态展示相应的用户界面。", + "responsibilities": [ + "定义系统级的加载状态枚举", + "提供类型安全的状态管理机制", + "作为其他组件状态判断的依据", + "确保加载状态的一致性和可维护性" + ], + "interfaces": [ + { + "name": "LoadingStatus", + "interface_type": "enum", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "表示异步操作的三种可能状态:加载中、已完成、出错" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 7, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805987, + "prompt_hash": "21f7ea14dab5aaddb082bf74224314e0", + "token_usage": { + "input_tokens": 423, + "output_tokens": 438, + "total_tokens": 861 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/2384216ebbf7041d48073d079243f7bb.json b/.litho/cache/ai_code_insight/2384216ebbf7041d48073d079243f7bb.json new file mode 100644 index 0000000..3c33ce7 --- /dev/null +++ b/.litho/cache/ai_code_insight/2384216ebbf7041d48073d079243f7bb.json @@ -0,0 +1,173 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/feeds/create_or_edit/+page.svelte", + "source_summary": "", + "code_purpose": "page", + "importance_score": 0.8, + "description": "Svelte页面组件,用于创建或编辑订阅源的表单界面。支持两种模式:创建和编辑。根据选择的数据获取方式(scrap/rss)动态调整输入字段标签和占位符,并通过Tauri API与主窗口通信完成保存操作。", + "functions": [ + "onSave", + "onCancel" + ], + "interfaces": [ + "formErrorName", + "formErrorFetcherId", + "formErrorData", + "canSave", + "formLabelData", + "formInputPlaceHolderData" + ] + }, + "detailed_description": "该组件是SvelteKit路由系统中的一个页面级组件,负责渲染‘创建/编辑’订阅源的UI表单。组件初始化时从URL参数中读取当前操作模式(mode)、ID、名称、数据等信息并填充到表单中。提供两个主要交互函数:onSave用于提交更改并关闭窗口,onCancel取消操作。表单包含名称输入、抓取类型选择及对应数据输入框,其标签和提示文本根据所选fetcher类型动态变化。错误提示机制确保必填项非空,且仅在所有验证通过后才允许保存。最终通过Tauri的window.emit向父窗口发送回调事件以通知结果。", + "responsibilities": [ + "解析URL参数初始化表单数据", + "管理创建/编辑两种模式下的状态逻辑", + "实现表单输入验证与动态UI更新", + "处理保存和取消操作并与宿主窗口通信", + "提供国际化文本支持与用户反馈" + ], + "interfaces": [ + { + "name": "formErrorName", + "interface_type": "derived_state", + "visibility": "private", + "parameters": [], + "return_type": "boolean", + "description": "计算属性:判断feed名称是否为空" + }, + { + "name": "formErrorFetcherId", + "interface_type": "derived_state", + "visibility": "private", + "parameters": [], + "return_type": "boolean", + "description": "计算属性:判断抓取器ID是否为空" + }, + { + "name": "formErrorData", + "interface_type": "derived_state", + "visibility": "private", + "parameters": [], + "return_type": "boolean", + "description": "计算属性:判断数据内容是否为空" + }, + { + "name": "canSave", + "interface_type": "derived_state", + "visibility": "private", + "parameters": [], + "return_type": "boolean", + "description": "计算属性:综合判断是否可执行保存操作" + }, + { + "name": "formLabelData", + "interface_type": "derived_state", + "visibility": "private", + "parameters": [], + "return_type": "string", + "description": "根据当前fetcher_id动态生成数据输入框的标签文本" + }, + { + "name": "formInputPlaceHolderData", + "interface_type": "derived_state", + "visibility": "private", + "parameters": [], + "return_type": "string", + "description": "根据当前fetcher_id动态生成数据输入框的占位符文本" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": false, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "@tauri-apps/api/window", + "path": "@tauri-apps/api/window", + "is_external": true, + "line_number": 3, + "dependency_type": "native_api", + "version": null + }, + { + "name": "$lib/widgets/SaveOperatePanel.svelte", + "path": "$lib/widgets/SaveOperatePanel.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "component", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 5, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 6, + "dependency_type": "api_client", + "version": null + }, + { + "name": "$lib/utils/id", + "path": "$lib/utils/id", + "is_external": false, + "line_number": 7, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 8, + "dependency_type": "type_definition", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 9, + "dependency_type": "utility", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 10.0, + "lines_of_code": 136, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 9.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024524, + "prompt_hash": "2384216ebbf7041d48073d079243f7bb", + "token_usage": { + "input_tokens": 1617, + "output_tokens": 1336, + "total_tokens": 2953 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/25217391845516e5b71dc0101c6b2cae.json b/.litho/cache/ai_code_insight/25217391845516e5b71dc0101c6b2cae.json new file mode 100644 index 0000000..8550f60 --- /dev/null +++ b/.litho/cache/ai_code_insight/25217391845516e5b71dc0101c6b2cae.json @@ -0,0 +1,48 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/recorder/src/entity/mod.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "该模块作为实体模块的根,用于组织和导出文章记录相关的数据结构。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust模块定义文件(mod.rs),其主要作用是将`article_record`模块声明为当前`entity`模块的公共子模块。此文件本身不包含具体逻辑,而是作为模块系统的一部分,用于组织代码结构,使得`article_record`中定义的数据模型可以在上级模块中通过`entity::article_record`路径访问。它体现了Rust中典型的模块化设计模式,用于封装与文章记录相关的实体类型。", + "responsibilities": [ + "声明并导出 article_record 子模块", + "作为 entity 模块的入口点,提供模块结构组织", + "支持其他模块对文章记录实体的引用和复用" + ], + "interfaces": [], + "dependencies": [ + { + "name": "article_record", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024640, + "prompt_hash": "25217391845516e5b71dc0101c6b2cae", + "token_usage": { + "input_tokens": 418, + "output_tokens": 475, + "total_tokens": 893 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/2586645484a5567b61efc57503b2c3a0.json b/.litho/cache/ai_code_insight/2586645484a5567b61efc57503b2c3a0.json new file mode 100644 index 0000000..15dfc1a --- /dev/null +++ b/.litho/cache/ai_code_insight/2586645484a5567b61efc57503b2c3a0.json @@ -0,0 +1,85 @@ +{ + "data": { + "code_dossier": { + "name": "utils.rs", + "file_path": "crates/scrap/src/search/utils.rs", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供HTML内容清洗和文本处理的辅助函数,用于搜索引擎爬虫的数据预处理阶段。", + "functions": [ + "trim_head_read_days_ago", + "trim_html_with_script_and_style", + "trim_to" + ], + "interfaces": [ + "trim_head_read_days_ago", + "trim_html_with_script_and_style" + ] + }, + "detailed_description": "该组件包含三个核心函数:trim_head_read_days_ago用于清理表示时间间隔的字符串,移除多种语言(中文、英文)的时间后缀如'天之前'、'days ago'等;trim_html_with_script_and_style负责从原始HTML中提取主体内容,过滤掉script、style、meta等非正文标签,保留body内的有效内容并重构为标准HTML结构;trim_to是私有辅助函数,实现基于指定前缀的字符串截断逻辑。整体功能聚焦于网络爬虫数据采集后的预处理环节,确保后续分析模块能接收到干净、结构化的文本内容。", + "responsibilities": [ + "清理时间相关的文本后缀", + "过滤HTML中的非必要标签以提取主要内容", + "提供通用的字符串截断工具方法" + ], + "interfaces": [ + { + "name": "trim_head_read_days_ago", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "head_read", + "param_type": "String", + "is_optional": false, + "description": "包含时间信息的原始字符串" + } + ], + "return_type": "String", + "description": "去除多种语言格式的时间后缀,返回纯数字字符串" + }, + { + "name": "trim_html_with_script_and_style", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "html_text", + "param_type": "&str", + "is_optional": false, + "description": "原始HTML文本" + } + ], + "return_type": "String", + "description": "返回去除特定标签后的HTML内容" + } + ], + "dependencies": [ + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 39, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805579, + "prompt_hash": "2586645484a5567b61efc57503b2c3a0", + "token_usage": { + "input_tokens": 838, + "output_tokens": 724, + "total_tokens": 1562 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/26381acd2859d55167419934fb8212e0.json b/.litho/cache/ai_code_insight/26381acd2859d55167419934fb8212e0.json new file mode 100644 index 0000000..657202d --- /dev/null +++ b/.litho/cache/ai_code_insight/26381acd2859d55167419934fb8212e0.json @@ -0,0 +1,183 @@ +{ + "data": { + "code_dossier": { + "name": "ArticleReader.svelte", + "file_path": "app/src/routes/main/widgets/ArticleReader.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "文章阅读器组件,支持多种阅读模式和交互功能", + "functions": [ + "copyLink", + "openOriginalPage", + "refreshByEnhancedScraper", + "switchStar" + ], + "interfaces": [ + "ArticleReaderProps", + "ArticleReadMode" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,用于展示文章内容并提供多种阅读模式。它通过Tabs组件实现优化内容、熔炼内容和原始页面三种视图切换。组件从props接收articleId和store,使用$effect自动查询文章数据。提供了复制链接、打开原文、刷新内容和收藏文章等功能按钮。支持国际化文本显示,并集成了Tauri的剪贴板操作和外部应用打开能力。", + "responsibilities": [ + "管理文章阅读界面的状态和交互", + "提供多模式文章内容展示(优化/熔炼/原始)", + "处理用户与文章的交互操作(收藏、分享等)", + "集成第三方API实现系统级功能调用", + "响应式更新文章内容数据" + ], + "interfaces": [ + { + "name": "ArticleReaderProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "articleId", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "store", + "param_type": "any", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticleReadMode", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": null + }, + { + "name": "copyLink", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "Promise", + "description": null + }, + { + "name": "switchStar", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "article", + "param_type": "Article", + "is_optional": false, + "description": null + } + ], + "return_type": "void", + "description": null + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 3, + "dependency_type": "ui", + "version": null + }, + { + "name": "lucide-svelte", + "path": "lucide-svelte", + "is_external": true, + "line_number": 4, + "dependency_type": "icon", + "version": null + }, + { + "name": "$lib/widgets/ArticleRenderWidget.svelte", + "path": "$lib/widgets/ArticleRenderWidget.svelte", + "is_external": false, + "line_number": 9, + "dependency_type": "component", + "version": null + }, + { + "name": "$lib/widgets/EmbedWebView.svelte", + "path": "$lib/widgets/EmbedWebView.svelte", + "is_external": false, + "line_number": 10, + "dependency_type": "component", + "version": null + }, + { + "name": "./types", + "path": "./types", + "is_external": false, + "line_number": 11, + "dependency_type": "type", + "version": null + }, + { + "name": "$lib/types/article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 12, + "dependency_type": "type", + "version": null + }, + { + "name": "@tauri-apps/plugin-clipboard-manager", + "path": "@tauri-apps/plugin-clipboard-manager", + "is_external": true, + "line_number": 13, + "dependency_type": "plugin", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 15, + "dependency_type": "api", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 16, + "dependency_type": "util", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 9.0, + "lines_of_code": 156, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.64, + "cohesion_score": 0.78 + } + }, + "timestamp": 1759024210, + "prompt_hash": "26381acd2859d55167419934fb8212e0", + "token_usage": { + "input_tokens": 1614, + "output_tokens": 1042, + "total_tokens": 2656 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/27ca3638a157126364647d701beedbb0.json b/.litho/cache/ai_code_insight/27ca3638a157126364647d701beedbb0.json new file mode 100644 index 0000000..b08936c --- /dev/null +++ b/.litho/cache/ai_code_insight/27ca3638a157126364647d701beedbb0.json @@ -0,0 +1,114 @@ +{ + "data": { + "code_dossier": { + "name": "EmbedWebView.svelte", + "file_path": "app/src/lib/widgets/EmbedWebView.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "一个用于嵌入外部网页的Svelte组件,支持加载状态管理和可见性感知加载优化。", + "functions": [ + "onLoadEventHandler", + "onVisiblityChanged" + ], + "interfaces": [ + "EmbedWebViewProps" + ] + }, + "detailed_description": "该组件封装了一个可嵌入的Web视图(iframe),主要用于在应用内部安全地展示外部网页内容。它通过`src`属性接收目标URL,并利用自定义的`observeVisiblity`指令监听页面元素的可见性变化,实现懒加载优化:仅当组件进入视口时才请求资源。组件提供了加载状态反馈机制,使用`LoadingStatus`枚举跟踪加载过程,并通过Progress组件显示加载动画。事件处理方面,监听iframe的`load`事件以更新状态并通知父级组件。此外,通过`$effect.pre`运行副作用,在每次`src`变更时重新绑定事件监听器,确保生命周期同步。", + "responsibilities": [ + "管理嵌入式Web页面的加载生命周期", + "提供基于可见性的懒加载优化策略", + "展示加载进度与状态反馈给用户", + "安全地渲染第三方网页内容", + "向父组件暴露加载开始和结束的回调通知" + ], + "interfaces": [ + { + "name": "EmbedWebViewProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "src", + "param_type": "string", + "is_optional": false, + "description": "要嵌入的网页URL" + }, + { + "name": "onLoadStart", + "param_type": "() => void", + "is_optional": true, + "description": "加载开始时的回调函数" + }, + { + "name": "onLoadEnd", + "param_type": "(src: string) => void", + "is_optional": true, + "description": "加载完成时的回调函数" + } + ], + "return_type": null, + "description": "定义EmbedWebView组件的输入属性类型" + }, + { + "name": "onLoadEventHandler", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "void", + "description": "处理iframe加载完成事件,更新状态并触发回调" + } + ], + "dependencies": [ + { + "name": "$lib/utils/dom", + "path": "app/src/lib/utils/dom", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "$lib/types/loading", + "path": "app/src/lib/types/loading", + "is_external": false, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "./types", + "path": "app/src/lib/widgets/types", + "is_external": false, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 79, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805755, + "prompt_hash": "27ca3638a157126364647d701beedbb0", + "token_usage": { + "input_tokens": 899, + "output_tokens": 930, + "total_tokens": 1829 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/28ca872aad808bbe93155e72c9cad232.json b/.litho/cache/ai_code_insight/28ca872aad808bbe93155e72c9cad232.json new file mode 100644 index 0000000..b855f7e --- /dev/null +++ b/.litho/cache/ai_code_insight/28ca872aad808bbe93155e72c9cad232.json @@ -0,0 +1,81 @@ +{ + "data": { + "code_dossier": { + "name": "MarkdownImg.svelte", + "file_path": "app/src/lib/widgets/MarkdownImg.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.6, + "description": "一个用于渲染 Markdown 图像的 Svelte 组件,支持错误处理和备用文本显示。", + "functions": [ + "onerror" + ], + "interfaces": [ + "Props" + ] + }, + "detailed_description": "该组件是一个轻量级的 Svelte UI 组件,旨在安全地渲染由 Markdown 生成的图像标签。它接收可选的 href(图像源)、title 和 alt 文本(通过 text 传递),并在图像加载失败时触发 onerror 回调,将 error 状态设置为 true,从而防止损坏的图像影响用户体验。当发生错误时,整个 img 标签不会被渲染(通过 {#if !error} 控制)。此外,组件使用 $props() 自动解构传入的属性,并利用 Svelte 的反应式 $state 实现内部状态管理。", + "responsibilities": [ + "接收并解析图像相关的属性(src, title, alt)", + "实现图像加载失败的错误处理机制", + "通过条件渲染避免显示损坏的图像", + "提供基础的用户反馈(控制台警告)", + "保持轻量和可复用性作为UI组件" + ], + "interfaces": [ + { + "name": "Props", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "href", + "param_type": "string", + "is_optional": true, + "description": "图像的源地址,对应 标签的 src 属性" + }, + { + "name": "title", + "param_type": "string", + "is_optional": true, + "description": "图像的标题提示,对应 title 属性" + }, + { + "name": "text", + "param_type": "string", + "is_optional": true, + "description": "图像的替代文本,对应 alt 属性" + } + ], + "return_type": null, + "description": "定义组件接受的所有可选输入属性" + }, + { + "name": "onerror", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "void", + "description": "图像加载失败时的事件处理器,设置 error 状态并输出警告日志" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024714, + "prompt_hash": "28ca872aad808bbe93155e72c9cad232", + "token_usage": { + "input_tokens": 516, + "output_tokens": 735, + "total_tokens": 1251 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/28ff941c3c855b21c493373ddec83237.json b/.litho/cache/ai_code_insight/28ff941c3c855b21c493373ddec83237.json new file mode 100644 index 0000000..14f42b0 --- /dev/null +++ b/.litho/cache/ai_code_insight/28ff941c3c855b21c493373ddec83237.json @@ -0,0 +1,82 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/intelligent/src/article_processor/types.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "定义文章处理器的统一接口,支持异步处理和责任链模式。", + "functions": [], + "interfaces": [ + "IArticleProcessor" + ] + }, + "detailed_description": "该组件定义了 `IArticleProcessor` trait,作为文章处理流水线中各处理器的统一接口规范。所有实现该 trait 的结构体均可参与文章处理的责任链调度。`process` 方法接收不可变引用的 `Article` 和 `LLMInstructOption` 配置,返回一个异步 Future,输出为 `anyhow::Result
`,确保非阻塞 I/O 与错误传播能力。此设计支持构建可扩展、松耦合的文章处理管道。", + "responsibilities": [ + "定义文章处理器的标准接口", + "支持异步非阻塞处理流程", + "保证输入数据不可变性以维护状态一致性", + "支持通过 LLM 指令选项进行参数化处理", + "为责任链模式提供基础抽象" + ], + "interfaces": [ + { + "name": "IArticleProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "文章处理器的核心 trait,用于实现责任链模式中的处理器节点。" + }, + { + "name": "process", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "input", + "param_type": "&Article", + "is_optional": false, + "description": "待处理的文章内容,为不可变引用" + }, + { + "name": "opt", + "param_type": "LLMInstructOption", + "is_optional": false, + "description": "LLM 指令配置选项" + } + ], + "return_type": "impl std::future::Future>", + "description": "处理文章的方法,接受不可变引用的 Article 和 LLMInstructOption,返回异步 Result。" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 12, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024609, + "prompt_hash": "28ff941c3c855b21c493373ddec83237", + "token_usage": { + "input_tokens": 616, + "output_tokens": 708, + "total_tokens": 1324 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/2964aa5f4475545302528c3e59b9be6d.json b/.litho/cache/ai_code_insight/2964aa5f4475545302528c3e59b9be6d.json new file mode 100644 index 0000000..42b4632 --- /dev/null +++ b/.litho/cache/ai_code_insight/2964aa5f4475545302528c3e59b9be6d.json @@ -0,0 +1,70 @@ +{ + "data": { + "code_dossier": { + "name": "application_context.rs", + "file_path": "crates/feed_api_rs/src/application_context.rs", + "code_purpose": "entry", + "importance_score": 0.6, + "description": "定义应用程序上下文结构及其宿主接口,用于在系统各组件间传递配置信息。", + "functions": [ + "new", + "get_context", + "copy_context" + ], + "interfaces": [ + "ContextHost" + ] + }, + "detailed_description": "该组件定义了`ApplicationContext`结构体,用于封装应用运行所需的配置数据(AppConfig和UserConfig)。同时提供了`ContextHost` trait 和 `ContextHostWrapper` 实现,使得其他组件可以通过统一接口安全地访问或复制应用上下文。此设计支持依赖注入模式,增强了系统的模块化和可测试性。", + "responsibilities": [ + "封装应用程序的全局配置信息", + "提供对配置信息的安全访问机制", + "支持上下文的克隆与传递以供不同组件使用", + "定义上下文宿主的标准行为接口" + ], + "interfaces": [ + { + "name": "ContextHost", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "context", + "param_type": "ApplicationContext", + "is_optional": false, + "description": "初始化宿主时传入的应用上下文实例" + } + ], + "return_type": null, + "description": "定义上下文宿主的行为契约,包括创建、获取和复制上下文实例。" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 35, + "number_of_functions": 3, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.1, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805860, + "prompt_hash": "2964aa5f4475545302528c3e59b9be6d", + "token_usage": { + "input_tokens": 599, + "output_tokens": 564, + "total_tokens": 1163 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/2c8e64968ba6cdc2c3960d8d9081704a.json b/.litho/cache/ai_code_insight/2c8e64968ba6cdc2c3960d8d9081704a.json new file mode 100644 index 0000000..5b7cb16 --- /dev/null +++ b/.litho/cache/ai_code_insight/2c8e64968ba6cdc2c3960d8d9081704a.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "zh.json", + "file_path": "app/src/lib/i18n/locales/zh.json", + "code_purpose": "config", + "importance_score": 0.6, + "description": "中文语言包配置文件,包含应用内所有用户界面的文本内容,支持多语言国际化(i18n)。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个JSON格式的多语言资源配置文件,用于存储应用程序中所有中文界面文本。其结构采用嵌套命名空间方式组织,如 'common'、'main'、'reader'、'settings' 等模块化分组,便于维护和查找。每个键值对代表一个可本地化的字符串,广泛应用于UI渲染、按钮标签、提示信息、设置项等场景。该文件通过i18n框架被前端代码动态引用,实现语言切换功能。", + "responsibilities": [ + "提供应用界面所需的全部中文显示文本", + "支持系统的多语言切换与国际化能力", + "按功能模块组织语言资源,提升可维护性", + "为UI组件提供一致的文案标准" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 183, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758806003, + "prompt_hash": "2c8e64968ba6cdc2c3960d8d9081704a", + "token_usage": { + "input_tokens": 2850, + "output_tokens": 463, + "total_tokens": 3313 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/2dd6a833ecceec8cb69bc89759a5debe.json b/.litho/cache/ai_code_insight/2dd6a833ecceec8cb69bc89759a5debe.json new file mode 100644 index 0000000..5dc7906 --- /dev/null +++ b/.litho/cache/ai_code_insight/2dd6a833ecceec8cb69bc89759a5debe.json @@ -0,0 +1,92 @@ +{ + "data": { + "code_dossier": { + "name": "optimizer.rs", + "file_path": "crates/intelligent/src/article_processor/optimizer.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "实现文章内容优化的LLM处理逻辑,通过预设系统提示和用户指令对文本进行AI驱动的优化。", + "functions": [ + "new_processor" + ], + "interfaces": [ + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件负责构建一个基于大语言模型的文章优化处理器。它实现了IPresetArticleLLMProcessor接口,利用固定的系统提示(SYSTEM_PROMPT)和用户提示(USER_PROMPT_COMMAND_OPTIMIZE)来配置LLM行为,专注于对文章特定部分进行质量优化。其核心是通过低温度参数(0.1)确保输出的稳定性和确定性,适用于需要一致性优化结果的场景。", + "responsibilities": [ + "实现IPresetArticleLLMProcessor接口以创建标准化的LLM处理器", + "定义并加载用于文章优化的系统级和用户级提示模板", + "配置针对优化任务微调的AI生成参数(如低温度值)", + "封装ArticleLLMProcessor的实例化过程,提供一致的初始化逻辑" + ], + "interfaces": [ + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了创建预设型文章LLM处理器的标准方法,由Optimizer实现以支持统一的处理器工厂模式" + }, + { + "name": "new_processor", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定要处理的文章段落或章节信息" + } + ], + "return_type": "anyhow::Result", + "description": "根据输入的段落信息和预设提示创建一个新的文章优化处理器实例" + } + ], + "dependencies": [ + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor}", + "path": "crate::article_processor::llm_processor", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805899, + "prompt_hash": "2dd6a833ecceec8cb69bc89759a5debe", + "token_usage": { + "input_tokens": 601, + "output_tokens": 833, + "total_tokens": 1434 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/2ed047563eba803562f7491c91607abd.json b/.litho/cache/ai_code_insight/2ed047563eba803562f7491c91607abd.json new file mode 100644 index 0000000..a90c2aa --- /dev/null +++ b/.litho/cache/ai_code_insight/2ed047563eba803562f7491c91607abd.json @@ -0,0 +1,42 @@ +{ + "data": { + "code_dossier": { + "name": "text.ts", + "file_path": "app/src/lib/utils/text.ts", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供文本处理相关的通用工具函数,包括空值判断、模板替换和代码块包装去除等功能。", + "functions": [ + "isTextEmpty", + "format", + "removeCodeBlockWrapper" + ], + "interfaces": [] + }, + "detailed_description": "该组件包含三个纯函数,用于处理字符串操作。isTextEmpty用于判断字符串是否为空或null;format实现基于占位符的模板字符串填充;removeCodeBlockWrapper通过正则表达式移除Markdown风格的代码块包裹符号(如```language和```)。", + "responsibilities": [ + "判断文本内容是否为空", + "执行模板字符串的变量替换", + "清理Markdown代码块的包裹语法" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 23, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805993, + "prompt_hash": "2ed047563eba803562f7491c91607abd", + "token_usage": { + "input_tokens": 644, + "output_tokens": 346, + "total_tokens": 990 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/302afdf662f68b6d1cbe3b6f2ac0c320.json b/.litho/cache/ai_code_insight/302afdf662f68b6d1cbe3b6f2ac0c320.json new file mode 100644 index 0000000..7c3aac5 --- /dev/null +++ b/.litho/cache/ai_code_insight/302afdf662f68b6d1cbe3b6f2ac0c320.json @@ -0,0 +1,155 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/articles/list/index.svelte.ts", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "文章列表状态管理器,负责数据加载、分页、搜索过滤和任务协调", + "functions": [ + "create", + "generateTaskIdForUpdateFeed", + "notifyDatasourceUpdated", + "updateFeeds", + "attachInitLoadingFuture", + "refresh", + "loadMore" + ], + "interfaces": [ + "StoreType", + "Associations" + ] + }, + "detailed_description": "该组件是Svelte应用中的状态存储模块,专为管理文章列表的展示逻辑而设计。它封装了与文章数据获取、分页加载、搜索过滤及异步任务协调相关的所有状态和行为。通过依赖注入方式接收search和tasks两个关联store,实现跨模块状态联动。核心功能包括:初始化加载文章内容、下拉刷新、上滑加载更多、响应搜索关键词变化并实时更新过滤结果。采用$state和$effect构建响应式状态系统,并利用loading.svelte提供统一的加载状态管理。支持通过associatedFeedId动态切换数据源,并通过tasks store避免重复请求。", + "responsibilities": [ + "管理文章列表的分组数据显示状态", + "处理文章数据的初始化加载与增量加载(分页)", + "响应搜索条件变化并执行全文检索更新视图", + "协调与其他功能模块(如任务队列、搜索)的状态同步", + "对外暴露标准化的数据访问与操作接口" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义文章列表store的完整结构,包含状态字段和方法集合" + }, + { + "name": "Associations", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义外部依赖的store类型集合,用于依赖注入" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "exported", + "parameters": [ + { + "name": "associations", + "param_type": "Associations", + "is_optional": false, + "description": null + } + ], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个具备完整功能的文章列表store实例" + }, + { + "name": "generateTaskIdForUpdateFeed", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "associatedFeedId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "string", + "description": "根据feedId生成唯一的任务标识符,用于去重控制" + } + ], + "dependencies": [ + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "svelte", + "path": "svelte", + "is_external": true, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "$lib/types/article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "../../../widgets/types", + "path": "../../../widgets/types", + "is_external": false, + "line_number": 4, + "dependency_type": "import", + "version": null + }, + { + "name": "../../loading.svelte", + "path": "../../loading.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "import", + "version": null + }, + { + "name": "../search/index.svelte", + "path": "../search/index.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "import", + "version": null + }, + { + "name": "../../tasks.svelte", + "path": "../../tasks.svelte", + "is_external": false, + "line_number": 8, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 11.0, + "lines_of_code": 221, + "number_of_functions": 7, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 8.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758800993, + "prompt_hash": "302afdf662f68b6d1cbe3b6f2ac0c320", + "token_usage": { + "input_tokens": 2179, + "output_tokens": 1173, + "total_tokens": 3352 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/317264bc9a41525642223799077c4818.json b/.litho/cache/ai_code_insight/317264bc9a41525642223799077c4818.json new file mode 100644 index 0000000..1a351de --- /dev/null +++ b/.litho/cache/ai_code_insight/317264bc9a41525642223799077c4818.json @@ -0,0 +1,76 @@ +{ + "data": { + "code_dossier": { + "name": "+layout.ts", + "file_path": "app/src/routes/+layout.ts", + "source_summary": "", + "code_purpose": "router", + "importance_score": 0.6, + "description": "SvelteKit布局加载函数,用于初始化国际化并设置浏览器语言环境", + "functions": [ + "load" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit应用中的布局级加载器(+layout.ts),在页面渲染前执行。其主要功能是在客户端环境中初始化国际化支持:检测浏览器的默认语言并设置当前locale,然后等待本地化资源加载完成。通过await waitLocale()确保所有i18n资源准备就绪后再渲染页面内容,避免出现未翻译的文本。prerender设为true表示该布局可被预渲染。", + "responsibilities": [ + "初始化应用的国际化系统", + "根据浏览器语言自动设置当前locale", + "等待本地化资源加载完成以确保正确渲染", + "配置布局的预渲染行为", + "作为路由布局的入口加载逻辑" + ], + "interfaces": [], + "dependencies": [ + { + "name": "$lib/i18n", + "path": "$lib/i18n", + "is_external": false, + "line_number": 1, + "dependency_type": "initialization", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": true, + "line_number": 2, + "dependency_type": "environment", + "version": null + }, + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 3, + "dependency_type": "internationalization", + "version": null + }, + { + "name": "./$types", + "path": "./$types", + "is_external": false, + "line_number": 4, + "dependency_type": "typing", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.3076923076923077, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024726, + "prompt_hash": "317264bc9a41525642223799077c4818", + "token_usage": { + "input_tokens": 496, + "output_tokens": 577, + "total_tokens": 1073 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/33036e527c7041f1d59d97031c90ab46.json b/.litho/cache/ai_code_insight/33036e527c7041f1d59d97031c90ab46.json new file mode 100644 index 0000000..ef522e1 --- /dev/null +++ b/.litho/cache/ai_code_insight/33036e527c7041f1d59d97031c90ab46.json @@ -0,0 +1,93 @@ +{ + "data": { + "code_dossier": { + "name": "init_llm.rs", + "file_path": "crates/feed_api_rs/src/startup/init_llm.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "初始化LLM提供者,根据配置启动相应的本地大模型服务。", + "functions": [ + "call" + ], + "interfaces": [ + "call" + ] + }, + "detailed_description": "该组件负责在应用启动时初始化指定的大型语言模型(LLM)提供程序。当前主要支持Ollama作为后端运行时,通过查询其平台状态并采取相应措施:若未安装则记录信息;若已安装但未运行,则尝试唤醒服务;若正在运行则不做操作。对于非Ollama的其他提供者类型,执行空初始化任务以保持流程一致性。", + "responsibilities": [ + "检测并处理Ollama服务的运行状态", + "根据LLM配置决定是否需要唤醒本地模型服务", + "统一不同LLM提供者的初始化流程", + "集成到系统启动任务框架中,保证可扩展性和可观测性" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "llm_section", + "param_type": "&LLMSection", + "is_optional": false, + "description": "包含LLM配置信息的引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "异步初始化LLM提供者,依据配置激活对应的服务准备逻辑" + } + ], + "dependencies": [ + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "logging", + "version": null + }, + { + "name": "ollama", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "service_client", + "version": null + }, + { + "name": "types", + "path": null, + "is_external": false, + "line_number": 3, + "dependency_type": "model", + "version": null + }, + { + "name": "super::task::InitTask", + "path": "crates/feed_api_rs/src/startup/task.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "framework", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 38, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024295, + "prompt_hash": "33036e527c7041f1d59d97031c90ab46", + "token_usage": { + "input_tokens": 840, + "output_tokens": 673, + "total_tokens": 1513 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/342836c19b10875183c4eb597d4130ad.json b/.litho/cache/ai_code_insight/342836c19b10875183c4eb597d4130ad.json new file mode 100644 index 0000000..ef3f3c9 --- /dev/null +++ b/.litho/cache/ai_code_insight/342836c19b10875183c4eb597d4130ad.json @@ -0,0 +1,70 @@ +{ + "data": { + "code_dossier": { + "name": "locks.rs", + "file_path": "app/src-tauri/src/daemon/locks.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供守护进程相关的文件锁路径管理功能,用于协调后台任务的并发执行", + "functions": [ + "get_lock_path" + ], + "interfaces": [ + "LOCK_FEEDS_SCHEDULE_UPDATE" + ] + }, + "detailed_description": "该组件定义了一个常量LOCK_FEEDS_SCHEDULE_UPDATE和一个工具函数get_lock_path。其主要功能是为守护进程(daemon)系统生成特定锁文件的完整路径,通过调用recorder模块的get_appdata_file_in_dir函数,将锁文件统一存储在'appdata/daemons/'目录下。这种设计实现了锁文件路径的集中管理和命名规范化。", + "responsibilities": [ + "管理守护进程相关的锁文件路径生成", + "提供标准化的锁文件命名约定", + "封装锁文件存储位置的细节实现", + "确保锁文件路径的跨平台兼容性" + ], + "interfaces": [ + { + "name": "LOCK_FEEDS_SCHEDULE_UPDATE", + "interface_type": "const", + "visibility": "pub", + "parameters": [], + "return_type": "&str", + "description": "用于feeds定时更新任务的锁文件名称常量" + } + ], + "dependencies": [ + { + "name": "std::path::PathBuf", + "path": "std::path::PathBuf", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "recorder::path::get_appdata_file_in_dir", + "path": "recorder::path::get_appdata_file_in_dir", + "is_external": false, + "line_number": 3, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 9, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024672, + "prompt_hash": "342836c19b10875183c4eb597d4130ad", + "token_usage": { + "input_tokens": 474, + "output_tokens": 558, + "total_tokens": 1032 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/34a006e9861ea50feae34bd3850e924a.json b/.litho/cache/ai_code_insight/34a006e9861ea50feae34bd3850e924a.json new file mode 100644 index 0000000..f1151f0 --- /dev/null +++ b/.litho/cache/ai_code_insight/34a006e9861ea50feae34bd3850e924a.json @@ -0,0 +1,81 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/i18n/index.ts", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "国际化模块的初始化入口,负责加载多语言资源并配置默认语言环境。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是Svelte应用中i18n(国际化)系统的初始化入口。它通过导入svelte-i18n库的核心函数init和addMessages,注册英文(en)和中文(zh)的语言包,并基于getLocale()获取当前用户的首选语言,fallbackLocale作为备用语言进行初始化配置。整个逻辑在模块加载时自动执行,无需显式调用,确保应用启动时语言环境已正确设置。", + "responsibilities": [ + "加载并注册多语言消息(en, zh)", + "初始化i18n系统的核心配置", + "设置回退语言和初始语言", + "作为i18n功能的统一接入点" + ], + "interfaces": [], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + }, + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "library", + "version": null + }, + { + "name": "./settings", + "path": "app/src/lib/i18n/settings", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "./locales/en.json", + "path": "app/src/lib/i18n/locales/en.json", + "is_external": false, + "line_number": 4, + "dependency_type": "resource", + "version": null + }, + { + "name": "./locales/zh.json", + "path": "app/src/lib/i18n/locales/zh.json", + "is_external": false, + "line_number": 5, + "dependency_type": "resource", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 5.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024467, + "prompt_hash": "34a006e9861ea50feae34bd3850e924a", + "token_usage": { + "input_tokens": 488, + "output_tokens": 568, + "total_tokens": 1056 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3601d5b1a0cbbc7ae3a39665a71cc938.json b/.litho/cache/ai_code_insight/3601d5b1a0cbbc7ae3a39665a71cc938.json new file mode 100644 index 0000000..4761b12 --- /dev/null +++ b/.litho/cache/ai_code_insight/3601d5b1a0cbbc7ae3a39665a71cc938.json @@ -0,0 +1,110 @@ +{ + "data": { + "code_dossier": { + "name": "types.ts", + "file_path": "app/src/lib/widgets/types.ts", + "code_purpose": "widget", + "importance_score": 0.6, + "description": "定义了前端组件所需的类型接口,主要用于文章渲染和嵌入式Web视图的类型约束。", + "functions": [], + "interfaces": [ + "MarkdownProps", + "ArticleRenderProps", + "EmbedWebViewProps", + "ArticleRenderType" + ] + }, + "detailed_description": "该组件是一个类型定义文件,用于为前端UI组件提供统一的类型系统支持。主要包含两个核心部分:一是与文章内容渲染相关的类型(如MarkdownProps、ArticleRenderProps和ArticleRenderType),二是嵌入式WebView的属性类型定义(EmbedWebViewProps)。这些类型被其他UI组件引用以确保类型安全,特别是在处理动态内容渲染时。", + "responsibilities": [ + "定义文章内容渲染所需的通用类型结构", + "提供嵌入式Web视图组件的输入参数类型", + "通过联合类型限定渲染方式的合法取值范围", + "作为共享类型模块供多个UI组件引用" + ], + "interfaces": [ + { + "name": "MarkdownProps", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticleRenderProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticleRenderType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": null + }, + { + "name": "EmbedWebViewProps", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "src", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "onLoadStart", + "param_type": "(src: string) => void", + "is_optional": true, + "description": null + }, + { + "name": "onLoadEnd", + "param_type": "(src: string) => void", + "is_optional": true, + "description": null + } + ], + "return_type": null, + "description": null + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 14, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758806022, + "prompt_hash": "3601d5b1a0cbbc7ae3a39665a71cc938", + "token_usage": { + "input_tokens": 485, + "output_tokens": 692, + "total_tokens": 1177 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/384468e60cfc1eb91df8f0f4dff09582.json b/.litho/cache/ai_code_insight/384468e60cfc1eb91df8f0f4dff09582.json new file mode 100644 index 0000000..e414f72 --- /dev/null +++ b/.litho/cache/ai_code_insight/384468e60cfc1eb91df8f0f4dff09582.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "env.rs", + "file_path": "app/src-tauri/src/env.rs", + "code_purpose": "util", + "importance_score": 0.6, + "description": "用于判断当前程序是否以守护进程模式启动的工具模块。", + "functions": [ + "is_daemon" + ], + "interfaces": [ + "is_daemon" + ] + }, + "detailed_description": "该组件提供了一个简单的函数 `is_daemon`,用于检查当前程序的启动参数是否匹配预定义的守护进程启动标识(DAEMON_FEEDS_SCHEDULE_UPDATE)。它通过读取命令行第一个参数并与常量进行比较,返回布尔值表示是否处于守护进程模式。此逻辑被用于条件性地启动后台任务调度。", + "responsibilities": [ + "解析命令行参数以确定启动模式", + "提供简洁的API来判断是否运行在守护进程模式", + "与系统环境交互获取启动参数", + "支持基于启动模式的条件执行逻辑" + ], + "interfaces": [ + { + "name": "is_daemon", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "bool", + "description": "检测当前进程是否以守护进程方式启动" + } + ], + "dependencies": [ + { + "name": "DAEMON_FEEDS_SCHEDULE_UPDATE", + "path": "crate::daemon::args::DAEMON_FEEDS_SCHEDULE_UPDATE", + "is_external": false, + "line_number": 1, + "dependency_type": "constant", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805968, + "prompt_hash": "384468e60cfc1eb91df8f0f4dff09582", + "token_usage": { + "input_tokens": 451, + "output_tokens": 505, + "total_tokens": 956 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3a52713ea84e03bbcbc65df9bbebbe05.json b/.litho/cache/ai_code_insight/3a52713ea84e03bbcbc65df9bbebbe05.json new file mode 100644 index 0000000..6aecb96 --- /dev/null +++ b/.litho/cache/ai_code_insight/3a52713ea84e03bbcbc65df9bbebbe05.json @@ -0,0 +1,110 @@ +{ + "data": { + "code_dossier": { + "name": "selector_extensions.rs", + "file_path": "crates/scrap/src/search/selector_extensions.rs", + "code_purpose": "util", + "importance_score": 0.8, + "description": "为scraper库的ElementRef和Html类型扩展便捷的选择器方法,用于提取文本内容和属性值。", + "functions": [ + "select_text", + "select_attr_text" + ], + "interfaces": [ + "ElementSelector" + ] + }, + "detailed_description": "该组件定义了一个名为ElementSelector的trait,并为scraper crate中的ElementRef和Html类型实现了该trait。它提供了两个核心方法:select_text用于根据CSS选择器获取匹配元素的文本内容,select_attr_text用于获取匹配元素指定属性的值。两个实现版本(针对ElementRef和Html)逻辑一致,均使用select方法查找第一个匹配元素,若未找到则返回错误,否则提取相应信息。所有错误均通过anyhow::Result进行包装,提供清晰的上下文信息。", + "responsibilities": [ + "为HTML元素查询提供统一的文本提取接口", + "封装CSS选择器查询失败的错误处理逻辑", + "扩展scraper库原生类型的实用功能", + "提供属性值的安全提取机制" + ], + "interfaces": [ + { + "name": "ElementSelector", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "为支持选择操作的类型定义文本和属性提取的公共接口" + }, + { + "name": "select_text", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "self", + "param_type": "self", + "is_optional": false, + "description": null + }, + { + "name": "selector", + "param_type": "&Selector", + "is_optional": false, + "description": "用于查找元素的CSS选择器" + } + ], + "return_type": "anyhow::Result", + "description": "根据给定的选择器查找第一个匹配元素并返回其文本内容" + }, + { + "name": "select_attr_text", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "self", + "param_type": "self", + "is_optional": false, + "description": null + }, + { + "name": "selector", + "param_type": "&Selector", + "is_optional": false, + "description": "用于查找元素的CSS选择器" + }, + { + "name": "attr", + "param_type": "&str", + "is_optional": false, + "description": "要提取值的HTML属性名称" + } + ], + "return_type": "anyhow::Result", + "description": "根据给定的选择器查找第一个匹配元素并返回指定属性的值" + } + ], + "dependencies": [ + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 15.0, + "lines_of_code": 57, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805533, + "prompt_hash": "3a52713ea84e03bbcbc65df9bbebbe05", + "token_usage": { + "input_tokens": 987, + "output_tokens": 880, + "total_tokens": 1867 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3a6c3b61af5a5ca06048c051e1cb4fdc.json b/.litho/cache/ai_code_insight/3a6c3b61af5a5ca06048c051e1cb4fdc.json new file mode 100644 index 0000000..3e99884 --- /dev/null +++ b/.litho/cache/ai_code_insight/3a6c3b61af5a5ca06048c051e1cb4fdc.json @@ -0,0 +1,150 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/types/src/lib.rs", + "code_purpose": "model", + "importance_score": 0.8, + "description": "定义系统核心数据结构和配置模型,包括文章、用户配置、LLM配置等。", + "functions": [ + "rename_feed", + "change_feed_data", + "remove_feed", + "find_feeds_package", + "find_feeds_package_mut", + "find_feed", + "add_feeds_packages", + "remove_feeds_package", + "rename_feeds_package" + ], + "interfaces": [ + "Article", + "LLMInstructOption", + "AppConfigLogSection", + "DiagnosticSection", + "OutputType", + "ScrapProviderType", + "LLMProviderType", + "LLMProvider", + "PlatformLLMProvider", + "GLMLLMProvider", + "OpenAILLMProvider", + "OllamaLLMProvider", + "LLMSection", + "DaemonSection", + "ScrapSection", + "AppConfig", + "UserConfig", + "FeedsPackage", + "FeedTargetDescription", + "ConversationMessageRoleType", + "ConversationMessagePayloadType", + "ConversationMessage" + ] + }, + "detailed_description": "该组件是系统的核心模型定义文件,负责声明所有业务相关的数据结构。主要包括:1) 应用配置模型(AppConfig),包含LLM、爬虫、日志等模块的配置;2) 用户配置模型(UserConfig),管理订阅包和订阅项;3) LLM相关模型,支持多种提供商的配置;4) 对话消息模型,用于表示聊天交互中的消息。所有结构都实现了序列化/反序列化和克隆功能,便于数据持久化和传输。", + "responsibilities": [ + "定义系统核心数据模型和配置结构", + "提供用户配置的增删改查操作接口", + "支持多种LLM提供商的配置管理", + "实现数据结构的序列化与反序列化能力", + "维护订阅包和订阅项的层级关系" + ], + "interfaces": [ + { + "name": "UserConfig", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "用户配置主结构,包含订阅包列表" + }, + { + "name": "AppConfig", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "应用配置主结构,包含LLM、爬虫、日志等配置" + }, + { + "name": "rename_feed", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "new_name", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "bool", + "description": "重命名指定的feed" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "serialization", + "version": null + }, + { + "name": "strum", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "enum_utils", + "version": null + }, + { + "name": "std::cmp::Ordering", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "crate::llm_endpoint::LLMEndPoint", + "path": "crates/types/src/llm_endpoint.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 18.0, + "lines_of_code": 378, + "number_of_functions": 9, + "number_of_classes": 24, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801101, + "prompt_hash": "3a6c3b61af5a5ca06048c051e1cb4fdc", + "token_usage": { + "input_tokens": 3314, + "output_tokens": 956, + "total_tokens": 4270 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3ce2a51137321e383baab4d8660cb641.json b/.litho/cache/ai_code_insight/3ce2a51137321e383baab4d8660cb641.json new file mode 100644 index 0000000..502dc1e --- /dev/null +++ b/.litho/cache/ai_code_insight/3ce2a51137321e383baab4d8660cb641.json @@ -0,0 +1,80 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/i18n/index.ts", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "国际化模块的初始化入口,负责加载多语言资源并配置默认语言环境。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是Svelte应用中i18n(国际化)系统的初始化入口。它通过导入svelte-i18n库的核心函数init和addMessages,完成以下逻辑:首先将英文(en)和中文(zh)的语言包注册到系统中;然后调用init方法初始化国际化运行时,设置回退语言(fallbackLocale)和初始语言(initialLocale),其中初始语言由getLocale()动态获取。整个过程在模块加载时自动执行,无需外部显式调用,确保应用启动时语言环境已正确配置。", + "responsibilities": [ + "注册支持的多语言消息包(en/zh)", + "初始化国际化运行时环境", + "配置默认与回退语言选项", + "作为i18n子系统的统一入口点" + ], + "interfaces": [], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + }, + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "library", + "version": null + }, + { + "name": "./settings", + "path": "app/src/lib/i18n/settings", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "./locales/en.json", + "path": "app/src/lib/i18n/locales/en.json", + "is_external": false, + "line_number": 4, + "dependency_type": "resource", + "version": null + }, + { + "name": "./locales/zh.json", + "path": "app/src/lib/i18n/locales/zh.json", + "is_external": false, + "line_number": 5, + "dependency_type": "resource", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 5.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805731, + "prompt_hash": "3ce2a51137321e383baab4d8660cb641", + "token_usage": { + "input_tokens": 479, + "output_tokens": 609, + "total_tokens": 1088 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3d09d8e5ba7eeae9c7c8a362fdd5673b.json b/.litho/cache/ai_code_insight/3d09d8e5ba7eeae9c7c8a362fdd5673b.json new file mode 100644 index 0000000..ffe6e0b --- /dev/null +++ b/.litho/cache/ai_code_insight/3d09d8e5ba7eeae9c7c8a362fdd5673b.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/windows/index.ts", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "该文件作为窗口模块的入口,集中导出窗口相关功能,当前仅导出打开设置窗口的功能。", + "functions": [ + "openSettings" + ], + "interfaces": [] + }, + "detailed_description": "该组件是窗口管理模块的主入口文件,通过重新导出从 './settings' 模块导入的 open 函数(重命名为 openSettings),为上层模块提供统一的窗口操作接口。它起到了模块聚合和API封装的作用,隐藏了内部模块结构,提升了调用方的使用便利性和代码的可维护性。", + "responsibilities": [ + "作为窗口模块的公共访问入口", + "封装并导出打开设置窗口的功能", + "统一模块对外暴露的API接口", + "解耦调用方与具体实现模块的直接依赖" + ], + "interfaces": [], + "dependencies": [ + { + "name": "./settings", + "path": "app/src/lib/windows/settings", + "is_external": false, + "line_number": 1, + "dependency_type": "module_import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 3, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805720, + "prompt_hash": "3d09d8e5ba7eeae9c7c8a362fdd5673b", + "token_usage": { + "input_tokens": 421, + "output_tokens": 441, + "total_tokens": 862 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3dc084d733458d35d323fcc4de0e37fb.json b/.litho/cache/ai_code_insight/3dc084d733458d35d323fcc4de0e37fb.json new file mode 100644 index 0000000..dbfef3c --- /dev/null +++ b/.litho/cache/ai_code_insight/3dc084d733458d35d323fcc4de0e37fb.json @@ -0,0 +1,116 @@ +{ + "data": { + "code_dossier": { + "name": "tasks.svelte.ts", + "file_path": "app/src/routes/main/stores/tasks.svelte.ts", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "任务状态管理Store,用于跟踪异步操作的加载状态", + "functions": [ + "createPending", + "create" + ], + "interfaces": [ + "StoreType", + "PendingItem" + ] + }, + "detailed_description": "该组件是一个Svelte状态管理Store,专门用于管理系统中所有异步任务的加载状态。它通过维护一个待处理任务列表(pendings),每个任务包含描述、关联的loadingStore和Promise,实现对并发异步操作的统一状态追踪。组件提供添加、查询和移除待处理任务的功能,并基于所有子任务的状态派生出全局的pendingStatus和对应的显示文本pendingStatusText。当某个任务完成时,会自动从列表中清理已完成的任务。", + "responsibilities": [ + "管理应用中所有异步任务的生命周期状态", + "聚合多个并发异步操作的整体状态(加载/错误/完成)", + "提供任务注册与查询接口供其他组件使用", + "生成用户友好的状态显示文本" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "任务Store的主要接口类型,定义了状态属性和操作方法" + }, + { + "name": "PendingItem", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "表示单个待处理任务的数据结构" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个新的任务Store实例" + }, + { + "name": "createPending", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "description", + "param_type": "string", + "is_optional": false, + "description": "任务描述文本" + }, + { + "name": "promise", + "param_type": "Promise", + "is_optional": false, + "description": "要监控的异步Promise" + } + ], + "return_type": "PendingItem", + "description": "创建一个新的待处理任务项" + } + ], + "dependencies": [ + { + "name": "LoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 1, + "dependency_type": "type import", + "version": null + }, + { + "name": "createLoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "function import", + "version": null + }, + { + "name": "Status", + "path": "./loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "enum import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 7.0, + "lines_of_code": 85, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801027, + "prompt_hash": "3dc084d733458d35d323fcc4de0e37fb", + "token_usage": { + "input_tokens": 996, + "output_tokens": 884, + "total_tokens": 1880 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3f03f24fcb16f0dcbb365762049970f1.json b/.litho/cache/ai_code_insight/3f03f24fcb16f0dcbb365762049970f1.json new file mode 100644 index 0000000..14ef981 --- /dev/null +++ b/.litho/cache/ai_code_insight/3f03f24fcb16f0dcbb365762049970f1.json @@ -0,0 +1,363 @@ +{ + "data": { + "code_dossier": { + "name": "FeedsList.svelte", + "file_path": "app/src/routes/main/widgets/FeedsList.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "Svelte组件,用于展示和管理用户订阅源列表,支持分组展开、上下文菜单操作及快捷入口。", + "functions": [ + "createRefreshFeedsAction", + "createFeedPackageMenus", + "createFeedMenus", + "toggleExpand", + "expandGroup", + "onAddFeedPressed" + ], + "interfaces": [ + "listSection", + "listSectionWithAction", + "listItem", + "listItemInner", + "listGroupItem" + ] + }, + "detailed_description": "该组件实现了一个结构化的侧边栏导航界面,用于显示用户的RSS订阅包(FeedsPackage)及其内部的订阅项(Feed)。支持通过点击切换分组展开状态,并为每个订阅包和订阅项提供右键上下文菜单以执行创建、编辑、删除等操作。同时集成了‘今日’、‘本周’、‘收藏’、‘未读’等聚合视图入口。所有UI文本均通过i18n国际化处理,交互行为通过事件回调与外部store通信,保证了逻辑解耦。组件使用Svelte的状态驱动机制($state)管理展开状态,并利用自定义use指令disableContextMenu禁用默认右键菜单。", + "responsibilities": [ + "渲染订阅源层级结构并支持分组展开/折叠", + "提供上下文菜单支持对订阅包和订阅项进行增删改操作", + "集成国际化文本与动态提示消息", + "响应用户交互并通过回调通知父级组件状态变化", + "管理本地UI状态如分组展开状态" + ], + "interfaces": [ + { + "name": "listSection", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": "标题文本" + } + ], + "return_type": null, + "description": "渲染一个无操作的标题区段" + }, + { + "name": "listSectionWithAction", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "onclick", + "param_type": "Function", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "渲染带可点击图标的标题区段" + }, + { + "name": "listItem", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "onclick", + "param_type": "Function", + "is_optional": false, + "description": null + }, + { + "name": "stateSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "menus", + "param_type": "Array", + "is_optional": true, + "description": null + } + ], + "return_type": null, + "description": "通用列表项,可选绑定上下文菜单" + }, + { + "name": "listItemInner", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "stateSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "列表项内部样式封装" + }, + { + "name": "listGroupItem", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "onclick", + "param_type": "Function", + "is_optional": false, + "description": null + }, + { + "name": "stateSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "menus", + "param_type": "Array", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "带上下文菜单的分组标题项" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": null, + "dependency_type": "internationalization", + "version": null + }, + { + "name": "@tauri-apps/plugin-dialog", + "path": "@tauri-apps/plugin-dialog", + "is_external": true, + "line_number": null, + "dependency_type": "plugin", + "version": null + }, + { + "name": "$lib/widgets/ContextMenuProvider.svelte", + "path": "$lib/widgets/ContextMenuProvider.svelte", + "is_external": false, + "line_number": null, + "dependency_type": "component", + "version": null + }, + { + "name": "lucide-svelte/icons/plus", + "path": "lucide-svelte/icons/plus", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/folder", + "path": "lucide-svelte/icons/folder", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/folder-open", + "path": "lucide-svelte/icons/folder-open", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/circle-plus", + "path": "lucide-svelte/icons/circle-plus", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/package", + "path": "lucide-svelte/icons/package", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/newspaper", + "path": "lucide-svelte/icons/newspaper", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/settings", + "path": "lucide-svelte/icons/settings", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/globe", + "path": "lucide-svelte/icons/globe", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/file-heart", + "path": "lucide-svelte/icons/file-heart", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/eye-off", + "path": "lucide-svelte/icons/eye-off", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "./types", + "path": "./types", + "is_external": false, + "line_number": null, + "dependency_type": "type", + "version": null + }, + { + "name": "../stores/loading.svelte", + "path": "../stores/loading.svelte", + "is_external": false, + "line_number": null, + "dependency_type": "store", + "version": null + }, + { + "name": "$lib/windows/index", + "path": "$lib/windows/index", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": null, + "dependency_type": "type", + "version": null + }, + { + "name": "$lib/windows/lite-edit", + "path": "$lib/windows/lite-edit", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": null, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": null, + "dependency_type": "utility", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 263, + "number_of_functions": 6, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 19.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024220, + "prompt_hash": "3f03f24fcb16f0dcbb365762049970f1", + "token_usage": { + "input_tokens": 2273, + "output_tokens": 1996, + "total_tokens": 4269 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/3f28221975c41db1eee84e4d518e5805.json b/.litho/cache/ai_code_insight/3f28221975c41db1eee84e4d518e5805.json new file mode 100644 index 0000000..fb7f30b --- /dev/null +++ b/.litho/cache/ai_code_insight/3f28221975c41db1eee84e4d518e5805.json @@ -0,0 +1,265 @@ +{ + "data": { + "code_dossier": { + "name": "feeds.svelte.ts", + "file_path": "app/src/routes/main/stores/feeds.svelte.ts", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "管理用户订阅源(feeds)的Svelte状态存储,提供增删改查及刷新功能。", + "functions": [ + "create", + "refresh", + "findPackagesOwnerByFeedId", + "addFeedsPackage", + "removeFeedsPackage", + "renameFeedsPackage", + "addFeed", + "removeFeed", + "renameFeed" + ], + "interfaces": [ + "StoreType", + "FeedsPackage", + "FeedTargetDescription", + "LoadingStore", + "Status" + ] + }, + "detailed_description": "该组件是一个Svelte状态存储模块,用于管理用户的订阅包(FeedsPackage)及其内部的订阅项(Feed)。它封装了对后端API的调用,通过featuresApi实现数据的加载、创建、删除和重命名操作。组件使用$state()进行响应式状态管理,并结合loading.svelte中的加载状态机制,在数据请求过程中维护UI的状态反馈。核心功能包括:初始化加载状态、获取所有订阅包、查找特定feed所属的包、以及对包和feed的CRUD操作。返回的对象暴露了feedPackages的只读访问器,确保外部无法直接修改内部状态。", + "responsibilities": [ + "管理用户订阅源的数据状态", + "协调与后端API的通信", + "维护加载状态以支持UI反馈", + "提供安全的响应式数据访问接口", + "实现订阅包和订阅项的增删改查逻辑" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "export", + "parameters": [], + "return_type": null, + "description": "定义feeds store的结构,包含loadingStore、feedPackages和多个操作方法" + }, + { + "name": "FeedsPackage", + "interface_type": "type", + "visibility": "import", + "parameters": [], + "return_type": null, + "description": "表示一组订阅源的集合类型" + }, + { + "name": "FeedTargetDescription", + "interface_type": "type", + "visibility": "import", + "parameters": [], + "return_type": null, + "description": "描述单个订阅源目标的信息类型" + }, + { + "name": "LoadingStore", + "interface_type": "type", + "visibility": "import", + "parameters": [], + "return_type": null, + "description": "来自loading.svelte的状态管理类型" + }, + { + "name": "Status", + "interface_type": "enum", + "visibility": "import", + "parameters": [], + "return_type": null, + "description": "加载状态枚举值" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "export", + "parameters": [], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个新的feeds store实例" + }, + { + "name": "refresh", + "interface_type": "method", + "visibility": "public", + "parameters": [], + "return_type": "Promise", + "description": "从API重新获取所有订阅包数据并更新本地状态" + }, + { + "name": "findPackagesOwnerByFeedId", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": "要查找的feed的唯一标识符" + } + ], + "return_type": "FeedsPackage | undefined", + "description": "根据feedId查找其所属的订阅包" + }, + { + "name": "addFeedsPackage", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "feedsPackage", + "param_type": "FeedsPackage", + "is_optional": false, + "description": "要添加的订阅包对象" + } + ], + "return_type": "Promise", + "description": "向后端添加新的订阅包" + }, + { + "name": "removeFeedsPackage", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": "要删除的订阅包ID" + } + ], + "return_type": "Promise", + "description": "从后端删除指定ID的订阅包" + }, + { + "name": "renameFeedsPackage", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": "要重命名的订阅包ID" + }, + { + "name": "newName", + "param_type": "string", + "is_optional": false, + "description": "新的包名称" + } + ], + "return_type": "Promise", + "description": "重命名指定ID的订阅包" + }, + { + "name": "addFeed", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": "目标订阅包ID" + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": "要添加的feed描述对象" + } + ], + "return_type": "Promise", + "description": "向指定订阅包中添加新的feed" + }, + { + "name": "removeFeed", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": "包含目标feed的订阅包ID" + }, + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": "要删除的feed ID" + } + ], + "return_type": "Promise", + "description": "从指定订阅包中删除指定feed" + }, + { + "name": "renameFeed", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": "包含目标feed的订阅包ID" + }, + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": "要重命名的feed ID" + }, + { + "name": "newName", + "param_type": "string", + "is_optional": false, + "description": "新的feed名称" + } + ], + "return_type": "Promise", + "description": "重命名指定订阅包中的指定feed" + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "LoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 86, + "number_of_functions": 9, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801035, + "prompt_hash": "3f28221975c41db1eee84e4d518e5805", + "token_usage": { + "input_tokens": 1035, + "output_tokens": 1742, + "total_tokens": 2777 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/407d1b0c806c69dd0e4f23770b0fd741.json b/.litho/cache/ai_code_insight/407d1b0c806c69dd0e4f23770b0fd741.json new file mode 100644 index 0000000..d7853de --- /dev/null +++ b/.litho/cache/ai_code_insight/407d1b0c806c69dd0e4f23770b0fd741.json @@ -0,0 +1,72 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "app/src-tauri/src/daemon/mod.rs", + "source_summary": "", + "code_purpose": "other", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust模块的组织文件,用于将daemon功能域下的多个子模块(args, feeds_update, launcher, locks)进行聚合和封装。它本身不包含具体实现逻辑,而是通过pub(crate)关键字将内部模块暴露给当前crate的其他部分使用,起到模块路由和命名空间管理的作用。", + "responsibilities": [ + "组织和聚合daemon相关的子模块", + "提供统一的模块访问入口", + "控制模块的可见性范围(仅限当前crate)" + ], + "interfaces": [], + "dependencies": [ + { + "name": "args", + "path": "app/src-tauri/src/daemon/args", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "feeds_update", + "path": "app/src-tauri/src/daemon/feeds_update", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "launcher", + "path": "app/src-tauri/src/daemon/launcher", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "locks", + "path": "app/src-tauri/src/daemon/locks", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 4, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.8, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024675, + "prompt_hash": "407d1b0c806c69dd0e4f23770b0fd741", + "token_usage": { + "input_tokens": 431, + "output_tokens": 458, + "total_tokens": 889 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/409faa45e7903f096fdb6535f11b4a99.json b/.litho/cache/ai_code_insight/409faa45e7903f096fdb6535f11b4a99.json new file mode 100644 index 0000000..d22da34 --- /dev/null +++ b/.litho/cache/ai_code_insight/409faa45e7903f096fdb6535f11b4a99.json @@ -0,0 +1,92 @@ +{ + "data": { + "code_dossier": { + "name": "melt.rs", + "file_path": "crates/intelligent/src/article_processor/melt.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "实现文章处理中的LLM预设处理器,用于生成特定提示的AI内容。", + "functions": [ + "new_processor" + ], + "interfaces": [ + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件实现了IPresetArticleLLMProcessor trait,负责创建一个基于预定义系统提示和用户提示的文章LLM处理器。其主要功能是通过封装固定的SYSTEM_PROMPT和USER_PROMPT_COMMAND_PURGE提示模板,结合传入的LLMSection配置,初始化并返回一个ArticleLLMProcessor实例。该处理器可能用于‘熔合’或‘提炼’文章内容,执行如摘要、重构或清理等语义转换任务。温度参数设置为0.7,表明输出具有一定创造性但保持可控。", + "responsibilities": [ + "实现预设的LLM处理器创建逻辑", + "加载并管理固定的提示模板(system prompt 和 user prompt)", + "配置LLM调用参数(如temperature)", + "作为ArticleLLMProcessor的工厂构建器" + ], + "interfaces": [ + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了创建预设LLM处理器的标准接口" + }, + { + "name": "new_processor", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定LLM服务的目标区域或配置" + } + ], + "return_type": "anyhow::Result", + "description": "根据给定的LLMSection创建并返回一个配置好的ArticleLLMProcessor实例" + } + ], + "dependencies": [ + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crate::article_processor::llm_processor", + "is_external": false, + "line_number": 5, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 3.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805895, + "prompt_hash": "409faa45e7903f096fdb6535f11b4a99", + "token_usage": { + "input_tokens": 592, + "output_tokens": 754, + "total_tokens": 1346 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4230e4241fbad156d9cd4ba191a62b35.json b/.litho/cache/ai_code_insight/4230e4241fbad156d9cd4ba191a62b35.json new file mode 100644 index 0000000..b8ea224 --- /dev/null +++ b/.litho/cache/ai_code_insight/4230e4241fbad156d9cd4ba191a62b35.json @@ -0,0 +1,49 @@ +{ + "data": { + "code_dossier": { + "name": "default.json", + "file_path": "app/src-tauri/capabilities/default.json", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Capability configuration for the In-App window in a Tauri desktop application, defining allowed windows and permissions.", + "functions": [], + "interfaces": [] + }, + "detailed_description": "This configuration file defines a capability set named 'default' for a Tauri-based desktop application. It specifies which windows are available in the app (such as main, settings, about, and various feed-related windows) and grants a comprehensive set of permissions required for core functionality including window management, webview creation, event handling, shell operations, clipboard access, feed API interaction, autostart control, OS integration, and user dialogs. The schema reference ensures structural validity against the desktop-schema.json specification.", + "responsibilities": [ + "Defines the set of available windows within the application", + "Grants essential permissions for core desktop functionalities", + "Serves as a security boundary by explicitly listing allowed capabilities", + "Provides configuration for role-based access control in the Tauri framework" + ], + "interfaces": [], + "dependencies": [ + { + "name": "../gen/schemas/desktop-schema.json", + "path": "app/src-tauri/gen/schemas/desktop-schema.json", + "is_external": false, + "line_number": 1, + "dependency_type": "$schema", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 43, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.02, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024655, + "prompt_hash": "4230e4241fbad156d9cd4ba191a62b35", + "token_usage": { + "input_tokens": 675, + "output_tokens": 406, + "total_tokens": 1081 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4244b60930d605826ddec5305e747392.json b/.litho/cache/ai_code_insight/4244b60930d605826ddec5305e747392.json new file mode 100644 index 0000000..8169752 --- /dev/null +++ b/.litho/cache/ai_code_insight/4244b60930d605826ddec5305e747392.json @@ -0,0 +1,127 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/feedsPackage/create_or_edit/+page.svelte", + "code_purpose": "page", + "importance_score": 0.8, + "description": "Svelte页面组件,用于创建或编辑订阅包。支持两种模式:创建和编辑,通过URL参数控制。提供表单输入、验证和保存操作。", + "functions": [ + "onSave", + "onCancel" + ], + "interfaces": [ + "Mode" + ] + }, + "detailed_description": "该组件是一个Svelte前端页面,实现订阅包的创建与编辑功能。通过URL参数(mode, id, name, callbackEventId)动态加载数据并决定操作模式。在浏览器环境中解析查询参数初始化状态。包含一个文本输入字段用于输入订阅包名称,使用实时派生值进行非空验证。提供保存和取消按钮,触发后通过Tauri API与原生后端通信,并关闭当前窗口。错误信息会显示在界面底部。组件使用了国际化、上下文菜单禁用、字符串ID生成等工具函数。", + "responsibilities": [ + "处理订阅包的创建与编辑业务逻辑", + "管理表单状态与用户输入验证", + "与原生API交互完成数据持久化", + "处理窗口通信与生命周期控制", + "提供用户友好的UI反馈与错误提示" + ], + "interfaces": [ + { + "name": "Mode", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "定义操作模式的联合类型,支持'create'和'edit'两种状态" + }, + { + "name": "onSave", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "Promise", + "description": "保存操作处理器,根据当前模式调用相应的API方法添加或重命名订阅包" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$app/environment", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "framework", + "version": null + }, + { + "name": "@tauri-apps/api/window", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "native", + "version": null + }, + { + "name": "$lib/widgets/SaveOperatePanel.svelte", + "path": "$lib/widgets/SaveOperatePanel.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "component", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 6, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 7, + "dependency_type": "api", + "version": null + }, + { + "name": "$lib/utils/id", + "path": "$lib/utils/id", + "is_external": false, + "line_number": 8, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 9, + "dependency_type": "utility", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 90, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.88, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758805774, + "prompt_hash": "4244b60930d605826ddec5305e747392", + "token_usage": { + "input_tokens": 1089, + "output_tokens": 951, + "total_tokens": 2040 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/42a132f0aa9f8db040bde57dd56293d5.json b/.litho/cache/ai_code_insight/42a132f0aa9f8db040bde57dd56293d5.json new file mode 100644 index 0000000..b4597ad --- /dev/null +++ b/.litho/cache/ai_code_insight/42a132f0aa9f8db040bde57dd56293d5.json @@ -0,0 +1,122 @@ +{ + "data": { + "code_dossier": { + "name": "llm_glm.rs", + "file_path": "crates/llm/src/providers/llm_glm.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现基于GLM大语言模型的补全服务,通过适配OpenAI兼容接口完成请求。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了针对智谱AI GLM系列大模型的补全功能。它通过封装一个通用的OpenAI类接口(OpenAILikeCompletionService),将GLMProvider配置转换为OpenAILLMProvider格式,从而复用已有的OpenAI兼容逻辑进行HTTP通信。其主要作用是作为适配层,使系统能够以统一方式调用不同厂商但协议相似的大模型服务。", + "responsibilities": [ + "将GLM模型提供商配置适配为OpenAI兼容格式", + "构建并初始化GLM补全服务实例", + "代理调用底层OpenAI-like服务完成文本补全", + "处理GLM特有的初始化参数并传递至通用服务层", + "确保与系统中其他LLM提供者的一致性接口" + ], + "interfaces": [ + { + "name": "GLMCompletionService::new", + "interface_type": "constructor", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&GLMLLMProvider", + "is_optional": false, + "description": "GLM模型配置信息" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "目标选项(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "创建新的GLM补全服务实例" + }, + { + "name": "CompletionService::completion", + "interface_type": "trait_method", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行补全请求并返回结果" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types::{GLMLLMProvider, OpenAILLMProvider}", + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "connector", + "path": "crate::connector", + "is_external": false, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "llm_openaibase_like", + "path": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "is_external": false, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "types", + "path": "crate::providers::types::{AITargetOption, CompletionService}", + "is_external": false, + "line_number": 5, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 33, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.57, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024259, + "prompt_hash": "42a132f0aa9f8db040bde57dd56293d5", + "token_usage": { + "input_tokens": 769, + "output_tokens": 853, + "total_tokens": 1622 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/42c6c3b8b38361d0b870e0fd40c71928.json b/.litho/cache/ai_code_insight/42c6c3b8b38361d0b870e0fd40c71928.json new file mode 100644 index 0000000..cd5d082 --- /dev/null +++ b/.litho/cache/ai_code_insight/42c6c3b8b38361d0b870e0fd40c71928.json @@ -0,0 +1,128 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/feedsPackage/create_or_edit/+page.svelte", + "source_summary": "", + "code_purpose": "page", + "importance_score": 0.8, + "description": "Svelte页面组件,用于创建或编辑信息源包。通过URL参数判断操作模式(创建/编辑),提供表单输入和保存/取消操作面板。", + "functions": [ + "onSave", + "onCancel" + ], + "interfaces": [ + "Mode" + ] + }, + "detailed_description": "该组件是SvelteKit路由驱动的前端页面,负责渲染创建或编辑信息源包的UI界面。组件根据URL中的查询参数动态设置模式(create/edit)、ID、名称及回调事件ID。在浏览器环境中解析参数并初始化状态。用户输入包名后,通过`onSave`调用底层API执行添加或重命名操作,并通过Tauri的窗口系统触发回调事件后关闭窗口。`onCancel`则直接关闭窗口而不保存。界面包含输入验证、错误提示和操作面板,支持国际化文本显示。", + "responsibilities": [ + "解析URL参数初始化页面状态", + "提供信息源包名称的输入与验证功能", + "调用API实现创建或编辑信息源包的业务逻辑", + "通过Tauri窗口系统处理跨进程通信与窗口关闭", + "展示操作结果反馈与错误提示信息" + ], + "interfaces": [ + { + "name": "Mode", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "定义页面操作模式的联合类型,支持'create'和'edit'两种状态" + }, + { + "name": "onSave", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "Promise", + "description": "处理保存操作:创建时调用add_feeds_package添加新包;编辑时调用rename_feeds_package修改名称" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$app/environment", + "path": null, + "is_external": false, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "@tauri-apps/api/window", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "desktop", + "version": null + }, + { + "name": "$lib/widgets/SaveOperatePanel.svelte", + "path": null, + "is_external": false, + "line_number": 4, + "dependency_type": "ui_component", + "version": null + }, + { + "name": "$lib/utils/text", + "path": null, + "is_external": false, + "line_number": 5, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": null, + "is_external": false, + "line_number": 6, + "dependency_type": "api_client", + "version": null + }, + { + "name": "$lib/utils/id", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": null, + "is_external": false, + "line_number": 8, + "dependency_type": "utility", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 90, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 8.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024502, + "prompt_hash": "42c6c3b8b38361d0b870e0fd40c71928", + "token_usage": { + "input_tokens": 1097, + "output_tokens": 948, + "total_tokens": 2045 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/431062a9c86b129c09193fcede2669c2.json b/.litho/cache/ai_code_insight/431062a9c86b129c09193fcede2669c2.json new file mode 100644 index 0000000..6b070a7 --- /dev/null +++ b/.litho/cache/ai_code_insight/431062a9c86b129c09193fcede2669c2.json @@ -0,0 +1,202 @@ +{ + "data": { + "code_dossier": { + "name": "Cargo.toml", + "file_path": "app/src-tauri/Cargo.toml", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Tauri 应用的构建与依赖管理配置文件,定义了项目元信息、库类型、构建依赖、运行时依赖及编译优化选项。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该 Cargo.toml 文件是 Tauri 框架驱动的桌面应用程序的核心配置文件。它不仅声明了项目的名称、版本、作者和 Rust 版本(edition 2024),还通过 [lib] 配置指定了生成多种库格式(静态库、动态库等),以支持跨平台原生集成。文件中明确划分了构建期依赖(tauri-build)和运行时依赖,包括 Sentry 错误追踪、文件锁机制(fslock)、多个 Tauri 官方插件(shell、clipboard、os、dialog、autostart、single-instance)以及对本地 workspace 内部 crate 的路径依赖(如 feed_api_rs、types、recorder 等)。此外,依赖项大量使用 workspace 共享配置,确保版本一致性并简化维护。编译配置(profile.release)启用了高级优化(LTO、opt-level=3)、panic 处理策略(abort)和符号剥离控制,针对发布版本进行了性能调优。", + "responsibilities": [ + "定义项目元数据和构建属性", + "管理外部第三方依赖与内部 workspace crate 依赖", + "配置 Tauri 构建系统所需的构建依赖", + "设定不同构建环境(dev/release)的编译优化策略", + "声明库的输出类型以支持多目标链接" + ], + "interfaces": [], + "dependencies": [ + { + "name": "tauri-build", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "build-dependencies", + "version": "2.3.0" + }, + { + "name": "sentry", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "0.41.0" + }, + { + "name": "fslock", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "0.2.1" + }, + { + "name": "tauri-plugin-shell", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "2.3.0" + }, + { + "name": "tauri-plugin-clipboard-manager", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "2.3.0" + }, + { + "name": "tauri-plugin-os", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "2.3.0" + }, + { + "name": "tauri-plugin-dialog", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "2.3.1" + }, + { + "name": "tauri-plugin-autostart", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "2.5.0" + }, + { + "name": "tauri-plugin-single-instance", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": "2.3.1" + }, + { + "name": "feed_api_rs", + "path": "../../crates/feed_api_rs", + "is_external": false, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "types", + "path": "../../crates/types", + "is_external": false, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "recorder", + "path": "../../crates/recorder", + "is_external": false, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "ollama", + "path": "../../crates/ollama", + "is_external": false, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "tauri-plugin-feed-api", + "path": "../../crates/tauri-plugin-feed-api", + "is_external": false, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "serde_json", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": null + }, + { + "name": "spdlog-rs", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "dependencies", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 53, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024660, + "prompt_hash": "431062a9c86b129c09193fcede2669c2", + "token_usage": { + "input_tokens": 784, + "output_tokens": 1283, + "total_tokens": 2067 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/43e1e3e6bba003342ce2aee7ad187bcd.json b/.litho/cache/ai_code_insight/43e1e3e6bba003342ce2aee7ad187bcd.json new file mode 100644 index 0000000..f3a9a39 --- /dev/null +++ b/.litho/cache/ai_code_insight/43e1e3e6bba003342ce2aee7ad187bcd.json @@ -0,0 +1,131 @@ +{ + "data": { + "code_dossier": { + "name": "article_recorder_service.rs", + "file_path": "crates/recorder/src/article_recorder_service.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "文章记录服务,负责对文章记录进行增删改查、状态管理及搜索功能。", + "functions": [ + "initialize", + "update_content", + "insert", + "exists_by_source", + "query_backward", + "query_favorite", + "query_unread", + "query_backward_in_duration", + "count", + "mark_as_read", + "set_favorite", + "query_by_id", + "dispose", + "search_contents_by_keyword" + ], + "interfaces": [ + "ArticleRecorderService" + ] + }, + "detailed_description": "该组件实现了对文章记录(Article Record)的完整业务逻辑封装,主要职责包括:1) 管理文章记录的生命周期(插入、更新、删除);2) 提供多维度查询能力(按分组、收藏、未读、时间范围等);3) 支持内容搜索功能,基于标题、导读和正文进行模糊匹配;4) 维护阅读状态与收藏状态。服务通过依赖注入 Operator 模块实现与数据库的交互,遵循了清晰的职责分离原则。所有操作均为异步执行,适配现代Rust异步运行时环境。", + "responsibilities": [ + "管理文章记录的增删改查操作", + "维护文章的阅读和收藏状态", + "提供多条件查询接口支持前端展示需求", + "实现基于关键词的内容全文检索功能", + "协调Operator完成数据持久化操作" + ], + "interfaces": [ + { + "name": "ArticleRecorderService", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "文章记录服务主结构体,封装了对文章记录的所有业务操作" + } + ], + "dependencies": [ + { + "name": "chrono::NaiveDate", + "path": "chrono", + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::ColumnTrait", + "path": "sea_orm", + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::Condition", + "path": "sea_orm", + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::IntoActiveModel", + "path": "sea_orm", + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::ActiveValue::Set", + "path": "sea_orm", + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::prelude::Expr", + "path": "sea_orm", + "is_external": true, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::entity::article_record", + "path": "./crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::operator::Operator", + "path": "./crates/recorder/src/operator.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 9.0, + "lines_of_code": 157, + "number_of_functions": 14, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 8.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805603, + "prompt_hash": "43e1e3e6bba003342ce2aee7ad187bcd", + "token_usage": { + "input_tokens": 2186, + "output_tokens": 916, + "total_tokens": 3102 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4495bdbcc08212704207f665b788462a.json b/.litho/cache/ai_code_insight/4495bdbcc08212704207f665b788462a.json new file mode 100644 index 0000000..2ccf4d4 --- /dev/null +++ b/.litho/cache/ai_code_insight/4495bdbcc08212704207f665b788462a.json @@ -0,0 +1,67 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/articles/index.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "文章管理模块的状态容器工厂,协调搜索与列表子模块的创建和依赖注入。", + "functions": [ + "create" + ], + "interfaces": [] + }, + "detailed_description": "该组件作为文章管理功能的核心状态管理协调器,负责初始化并组合两个关键子模块:搜索(search)和列表(list)。通过依赖注入的方式接收来自任务模块(tasks)的状态存储,并将其与本地创建的搜索状态一起传递给列表模块,实现跨模块状态联动。采用工厂函数模式返回结构化的状态对象,便于上层组件解构使用。", + "responsibilities": [ + "初始化文章搜索状态管理模块", + "初始化文章列表状态管理模块并注入依赖", + "协调tasks、search与list三者之间的状态依赖关系", + "提供统一的工厂接口创建复合状态结构" + ], + "interfaces": [], + "dependencies": [ + { + "name": "createSearch", + "path": "./search/index.svelte", + "is_external": false, + "line_number": 1, + "dependency_type": "function", + "version": null + }, + { + "name": "createList", + "path": "./list/index.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "function", + "version": null + }, + { + "name": "TasksStoreType", + "path": "../tasks.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 16, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.375, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024521, + "prompt_hash": "4495bdbcc08212704207f665b788462a", + "token_usage": { + "input_tokens": 504, + "output_tokens": 562, + "total_tokens": 1066 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/457b7b302d7f71e51e11ab1a7640eb42.json b/.litho/cache/ai_code_insight/457b7b302d7f71e51e11ab1a7640eb42.json new file mode 100644 index 0000000..36f87ad --- /dev/null +++ b/.litho/cache/ai_code_insight/457b7b302d7f71e51e11ab1a7640eb42.json @@ -0,0 +1,58 @@ +{ + "data": { + "code_dossier": { + "name": "connector.rs", + "file_path": "crates/llm/src/connector.rs", + "code_purpose": "util", + "importance_score": 0.6, + "description": "构建并配置用于HTTP请求的reqwest客户端,设置超时、Gzip和Deflate压缩支持。", + "functions": [ + "new" + ], + "interfaces": [] + }, + "detailed_description": "该组件负责创建一个预配置的reqwest::Client实例,用于后续的HTTP通信。它设置了60秒的全局请求超时,并启用了Gzip和Deflate内容编码压缩,以优化网络传输效率。此客户端通常被LLM相关服务用于调用远程API。", + "responsibilities": [ + "初始化HTTP客户端实例", + "配置请求超时策略", + "启用响应内容的压缩支持", + "提供可靠的网络传输基础组件" + ], + "interfaces": [], + "dependencies": [ + { + "name": "std::time::Duration", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805851, + "prompt_hash": "457b7b302d7f71e51e11ab1a7640eb42", + "token_usage": { + "input_tokens": 466, + "output_tokens": 390, + "total_tokens": 856 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/45cb436521235e4d034a71e22730e6cf.json b/.litho/cache/ai_code_insight/45cb436521235e4d034a71e22730e6cf.json new file mode 100644 index 0000000..b004cd6 --- /dev/null +++ b/.litho/cache/ai_code_insight/45cb436521235e4d034a71e22730e6cf.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "id.ts", + "file_path": "app/src/lib/utils/id.ts", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "生成基于时间戳的字符串ID", + "functions": [ + "genStringId" + ], + "interfaces": [] + }, + "detailed_description": "该组件提供了一个简单的函数 genStringId,用于生成基于当前时间戳的字符串形式的唯一ID。通过调用 Date.now() 获取毫秒级时间戳,并将其转换为字符串返回。适用于需要轻量级、无依赖ID生成的场景。", + "responsibilities": [ + "生成基于时间戳的唯一字符串ID", + "提供轻量级ID生成能力", + "避免外部依赖实现基本标识生成功能" + ], + "interfaces": [ + { + "name": "genStringId", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "string", + "description": "生成一个基于当前时间戳的字符串ID" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 5, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024694, + "prompt_hash": "45cb436521235e4d034a71e22730e6cf", + "token_usage": { + "input_tokens": 429, + "output_tokens": 364, + "total_tokens": 793 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/45eec785a9d081d4337b1a060cee24d6.json b/.litho/cache/ai_code_insight/45eec785a9d081d4337b1a060cee24d6.json new file mode 100644 index 0000000..0a3c9ed --- /dev/null +++ b/.litho/cache/ai_code_insight/45eec785a9d081d4337b1a060cee24d6.json @@ -0,0 +1,75 @@ +{ + "data": { + "code_dossier": { + "name": "scrap_host.rs", + "file_path": "crates/tauri-plugin-feed-api/src/scrap_host.rs", + "code_purpose": "api", + "importance_score": 0.8, + "description": null, + "functions": [ + "scrap_text_by_url" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了基于Tauri框架的网页内容抓取功能,通过创建一个隐藏的Webview窗口加载指定URL,并在页面加载完成后执行JavaScript提取document.innerHTML。使用Tokio异步运行时和oneshot通道实现结果回调机制,确保异步操作的安全完成。当前仅支持单次抓取,通过WINDOW_SCRAP_HOST常量标识窗口实例,防止并发抓取。", + "responsibilities": [ + "管理用于网页抓取的Webview窗口生命周期", + "执行网页内容提取并返回HTML字符串", + "防止并发抓取操作的资源竞争", + "处理异步通信和事件监听机制", + "提供安全的跨线程资源清理机制" + ], + "interfaces": [], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "std", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "framework", + "version": null + }, + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 9, + "dependency_type": "runtime", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 55, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805618, + "prompt_hash": "45eec785a9d081d4337b1a060cee24d6", + "token_usage": { + "input_tokens": 879, + "output_tokens": 511, + "total_tokens": 1390 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4690c42a7d2da0891ef9c1416e1c7273.json b/.litho/cache/ai_code_insight/4690c42a7d2da0891ef9c1416e1c7273.json new file mode 100644 index 0000000..4b28ec8 --- /dev/null +++ b/.litho/cache/ai_code_insight/4690c42a7d2da0891ef9c1416e1c7273.json @@ -0,0 +1,105 @@ +{ + "data": { + "code_dossier": { + "name": "init_user_profile.rs", + "file_path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "初始化用户配置文件,支持从本地TOML文件加载或创建默认配置", + "functions": [ + "call", + "sync_to", + "default_user_profile" + ], + "interfaces": [ + "call", + "sync_to", + "default_user_profile" + ] + }, + "detailed_description": "该组件负责在应用启动时初始化用户个人资料。主要逻辑包括:尝试从指定路径读取user_config.toml配置文件,若文件不存在则生成默认用户配置并持久化到磁盘。提供异步加载和写入功能,确保非阻塞I/O操作。默认配置包含一个预设的订阅包,用于新用户引导体验。", + "responsibilities": [ + "管理用户配置的生命周期初始化", + "实现用户配置的持久化存储与读取", + "提供默认用户配置的生成逻辑", + "协调异步文件I/O操作" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result>", + "description": "启动用户配置初始化任务,返回可执行的异步任务" + }, + { + "name": "sync_to", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "user_config", + "param_type": "&UserConfig", + "is_optional": false, + "description": "要持久化的用户配置引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "将给定的用户配置同步保存到磁盘文件" + }, + { + "name": "default_user_profile", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "UserConfig", + "description": "生成系统默认的用户配置实例" + } + ], + "dependencies": [ + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "async_runtime", + "version": null + }, + { + "name": "recorder::path::get_appdata_file", + "path": "recorder::path", + "is_external": false, + "line_number": 6, + "dependency_type": "utility", + "version": null + }, + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 56, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024288, + "prompt_hash": "4690c42a7d2da0891ef9c1416e1c7273", + "token_usage": { + "input_tokens": 874, + "output_tokens": 738, + "total_tokens": 1612 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/48514e90f10df015b57da543b49c0bbc.json b/.litho/cache/ai_code_insight/48514e90f10df015b57da543b49c0bbc.json new file mode 100644 index 0000000..ce32c6b --- /dev/null +++ b/.litho/cache/ai_code_insight/48514e90f10df015b57da543b49c0bbc.json @@ -0,0 +1,99 @@ +{ + "data": { + "code_dossier": { + "name": "api.ts", + "file_path": "app/src/lib/hybrid-apis/feed/api.ts", + "code_purpose": "api", + "importance_score": 0.8, + "description": "定义了用于管理信息流(feeds)包、文章内容、应用配置及AI辅助交互的异步接口契约。", + "functions": [], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件定义了一个名为 FeaturesAPI 的 TypeScript 接口,封装了一系列用于管理信息流订阅、内容获取、应用配置和 AI 功能集成的异步操作。这些方法主要面向前端与后端(或 Tauri 原生层)之间的通信,提供了对 feeds 包的增删改查、文章内容的读取与更新、Ollama 模型服务的控制、外部网页打开、文本抓取以及基于文章内容的聊天助手等功能。所有方法均返回 Promise 类型,表明其为异步调用,符合现代 Web 和混合应用的通信模式。", + "responsibilities": [ + "定义信息流(feeds)及其分组(package)的管理接口", + "提供文章内容的读取、查询与关键字搜索功能", + "管理应用程序配置与本地 AI 服务(如 Ollama)的交互接口", + "支持文章内容提取与智能问答等高级功能的 API 契约定义" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "interface", + "visibility": "export", + "parameters": [], + "return_type": null, + "description": "核心接口,声明了所有与 feed 管理、内容处理和 AI 交互相关的异步方法。" + } + ], + "dependencies": [ + { + "name": "Option", + "path": "../tauri-regular", + "is_external": false, + "line_number": 1, + "dependency_type": "type-import", + "version": null + }, + { + "name": "AppConfig", + "path": "./types", + "is_external": false, + "line_number": 3, + "dependency_type": "type-import", + "version": null + }, + { + "name": "ArticleModel", + "path": "./types", + "is_external": false, + "line_number": 4, + "dependency_type": "type-import", + "version": null + }, + { + "name": "ConversationMessage", + "path": "./types", + "is_external": false, + "line_number": 5, + "dependency_type": "type-import", + "version": null + }, + { + "name": "FeedsPackage", + "path": "./types", + "is_external": false, + "line_number": 6, + "dependency_type": "type-import", + "version": null + }, + { + "name": "FeedTargetDescription", + "path": "./types", + "is_external": false, + "line_number": 7, + "dependency_type": "type-import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 73, + "number_of_functions": 19, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 6.0, + "cohesion_score": 0.92 + } + }, + "timestamp": 1758805703, + "prompt_hash": "48514e90f10df015b57da543b49c0bbc", + "token_usage": { + "input_tokens": 852, + "output_tokens": 799, + "total_tokens": 1651 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4990d2a248b5115727059f32e1a3bd34.json b/.litho/cache/ai_code_insight/4990d2a248b5115727059f32e1a3bd34.json new file mode 100644 index 0000000..87a4651 --- /dev/null +++ b/.litho/cache/ai_code_insight/4990d2a248b5115727059f32e1a3bd34.json @@ -0,0 +1,93 @@ +{ + "data": { + "code_dossier": { + "name": "optimizer.rs", + "file_path": "crates/intelligent/src/article_processor/optimizer.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "实现文章内容优化的LLM处理器,通过预设系统提示和用户指令模板对文本进行AI驱动的优化处理。", + "functions": [ + "new_processor" + ], + "interfaces": [ + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件实现了IPresetArticleLLMProcessor接口,专门用于创建一个针对文章优化任务的LLM处理器。它使用固定的系统提示(SYSTEM_PROMPT)和用户后缀提示(USER_PROMPT_COMMAND_OPTIMIZE),配置低温度参数(0.1)以确保输出稳定性,从而实现对文章特定部分的精细化优化。其主要作用是封装优化任务所需的AI模型参数和提示工程策略。", + "responsibilities": [ + "实现文章优化专用的LLM处理器工厂方法", + "配置适用于内容优化的AI模型参数(如低温度值)", + "管理并注入优化任务所需的系统与用户提示模板", + "遵循预设处理器规范,保证接口一致性" + ], + "interfaces": [ + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result", + "description": "定义预设型文章LLM处理器的创建规范" + }, + { + "name": "new_processor", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "待处理的文章段落信息" + } + ], + "return_type": "anyhow::Result", + "description": "根据给定的LLM段落信息创建优化处理器实例" + } + ], + "dependencies": [ + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor}", + "path": "crate::article_processor::llm_processor", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 3.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024623, + "prompt_hash": "4990d2a248b5115727059f32e1a3bd34", + "token_usage": { + "input_tokens": 609, + "output_tokens": 781, + "total_tokens": 1390 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4ca53e004fa88b3e64b0a167212fe7c5.json b/.litho/cache/ai_code_insight/4ca53e004fa88b3e64b0a167212fe7c5.json new file mode 100644 index 0000000..9bad915 --- /dev/null +++ b/.litho/cache/ai_code_insight/4ca53e004fa88b3e64b0a167212fe7c5.json @@ -0,0 +1,43 @@ +{ + "data": { + "code_dossier": { + "name": "text.ts", + "file_path": "app/src/lib/utils/text.ts", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供文本处理相关的通用工具函数,包括判空、模板替换和去除代码块包装等。", + "functions": [ + "isTextEmpty", + "format", + "removeCodeBlockWrapper" + ], + "interfaces": [] + }, + "detailed_description": "该组件包含三个纯函数,用于处理字符串操作:isTextEmpty 判断字符串是否为空或 null;format 使用键值对替换模板中的占位符;removeCodeBlockWrapper 移除 Markdown 风格的代码块包裹符号(如 ```language 和 ```)。所有函数均为无副作用的工具函数,适合在多处复用。", + "responsibilities": [ + "判断文本是否为空值", + "执行字符串模板变量替换", + "去除 Markdown 代码块的包裹符号" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 23, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024691, + "prompt_hash": "4ca53e004fa88b3e64b0a167212fe7c5", + "token_usage": { + "input_tokens": 652, + "output_tokens": 363, + "total_tokens": 1015 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4dcaa642b6730282a912b5099ee87e53.json b/.litho/cache/ai_code_insight/4dcaa642b6730282a912b5099ee87e53.json new file mode 100644 index 0000000..f2f26c1 --- /dev/null +++ b/.litho/cache/ai_code_insight/4dcaa642b6730282a912b5099ee87e53.json @@ -0,0 +1,235 @@ +{ + "data": { + "code_dossier": { + "name": "baidu.rs", + "file_path": "crates/scrap/src/search/baidu.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "百度搜索引擎结果抓取与解析组件,负责从百度搜索页面提取文章信息并进一步获取内容摘要", + "functions": [ + "new", + "prepare_target_sources", + "convert", + "search_by_words", + "adjust_date_str" + ], + "interfaces": [ + "IProvider" + ] + }, + "detailed_description": "该组件实现了针对百度搜索结果页的爬虫功能。主要流程包括:构造带时间范围限制的百度搜索URL,获取HTML响应,使用CSS选择器解析搜索结果条目(标题、链接、发布时间等),处理相对日期格式,并通过异步方式调用文章阅读器获取目标网页正文内容。存在重定向问题导致内容抓取失败的风险。组件封装了HTML解析逻辑和网络请求细节,提供统一接口供上层调用。", + "responsibilities": [ + "构建百度搜索请求URL并执行搜索", + "解析百度搜索结果页面的HTML结构提取文章元数据", + "转换相对日期字符串为标准格式", + "协调调用文章阅读器获取目标网页全文内容", + "实现搜索引擎提供商接口协议" + ], + "interfaces": [ + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "创建Provider实例,初始化HTTP客户端和CSS选择器" + }, + { + "name": "prepare_target_sources", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result>", + "description": "解析HTML文本,提取搜索结果中的文章元数据列表" + }, + { + "name": "convert", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result>", + "description": "将搜索结果元数据转换为包含完整内容的文章对象" + }, + { + "name": "search_by_words", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": null + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": null + } + ], + "return_type": "anyhow::Result>", + "description": "根据关键词搜索并返回文章列表,实现了IProvider trait" + }, + { + "name": "adjust_date_str", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "lossy_date_str", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": "String", + "description": "将'X天前'等相对时间表述转换为具体日期" + }, + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "搜索引擎提供商接口,定义了search_by_words方法契约" + }, + { + "name": "Provider", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "百度搜索服务提供者,包含客户端、选择器和LLM配置" + } + ], + "dependencies": [ + { + "name": "chrono", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "reqwest", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 6, + "dependency_type": "use", + "version": null + }, + { + "name": "types", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::connector", + "path": "crates/scrap/src/connector/mod.rs", + "is_external": false, + "line_number": 9, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::search::types", + "path": "crates/scrap/src/search/types.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::search::utils", + "path": "crates/scrap/src/search/utils.rs", + "is_external": false, + "line_number": 11, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::simulator", + "path": "crates/scrap/src/simulator/mod.rs", + "is_external": false, + "line_number": 12, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::article_reader", + "path": "crates/scrap/src/article_reader/mod.rs", + "is_external": false, + "line_number": 13, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 12.0, + "lines_of_code": 181, + "number_of_functions": 5, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 11.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758805537, + "prompt_hash": "4dcaa642b6730282a912b5099ee87e53", + "token_usage": { + "input_tokens": 2230, + "output_tokens": 1460, + "total_tokens": 3690 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/4f7185e3eabcb3c804d621f9ddeb4e6d.json b/.litho/cache/ai_code_insight/4f7185e3eabcb3c804d621f9ddeb4e6d.json new file mode 100644 index 0000000..67558ac --- /dev/null +++ b/.litho/cache/ai_code_insight/4f7185e3eabcb3c804d621f9ddeb4e6d.json @@ -0,0 +1,126 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/scrap/src/search/mod.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "搜索功能的聚合模块,封装了多种搜索引擎提供商的统一接口。", + "functions": [ + "search_by_words", + "fetch" + ], + "interfaces": [ + "IProvider", + "IFetcher" + ] + }, + "detailed_description": "该组件是搜索功能的核心聚合模块,通过枚举类型ScrapProviderEnums统一管理不同的搜索引擎实现(如百度、必应)。它实现了IProvider和IFetcher两个核心接口,提供了基于关键词搜索和内容抓取的功能。组件采用代理模式,将具体的搜索请求转发给内部封装的实际提供商实例,并记录关键日志信息用于调试和监控。", + "responsibilities": [ + "统一管理多种搜索引擎提供商的实例", + "提供标准化的搜索接口供上层调用", + "实现基于关键词的文章搜索功能", + "集成日志记录与监控能力", + "协调搜索结果的获取与返回" + ], + "interfaces": [ + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义搜索引擎提供商的基本行为契约" + }, + { + "name": "IFetcher", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义内容抓取器的标准接口" + }, + { + "name": "search_by_words", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "搜索关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "应用句柄,用于跨平台操作" + } + ], + "return_type": "anyhow::Result>", + "description": "根据关键词执行搜索并返回文章列表" + } + ], + "dependencies": [ + { + "name": "::types", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::search::types::IProvider", + "path": "crates/scrap/src/search/types.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 50, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024345, + "prompt_hash": "4f7185e3eabcb3c804d621f9ddeb4e6d", + "token_usage": { + "input_tokens": 773, + "output_tokens": 846, + "total_tokens": 1619 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/501c146ce5aba3f2a64a6fd27f67b120.json b/.litho/cache/ai_code_insight/501c146ce5aba3f2a64a6fd27f67b120.json new file mode 100644 index 0000000..5060b94 --- /dev/null +++ b/.litho/cache/ai_code_insight/501c146ce5aba3f2a64a6fd27f67b120.json @@ -0,0 +1,154 @@ +{ + "data": { + "code_dossier": { + "name": "task.rs", + "file_path": "crates/feed_api_rs/src/startup/task.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "定义了异步任务初始化器和具体实现,用于执行启动阶段的任务并收集执行状态与耗时。", + "functions": [ + "TaskInitializer::start", + "TaskInitializer::dump", + "InitTask::default" + ], + "interfaces": [ + "TaskInitializer", + "InitTask" + ] + }, + "detailed_description": "该组件定义了一个通用的异步任务执行框架,主要用于应用启动过程中关键任务的执行与监控。`TaskInitializer` 是一个 trait,规定了任务启动和状态转储的行为;`InitTask` 是其实现结构体,负责实际执行传入的异步函数,记录执行时间、结果状态,并通过日志输出执行信息。成功时标记为 Completed 并记录耗时,失败时标记为 Error 并记录错误日志。此设计支持对初始化流程的可观测性。", + "responsibilities": [ + "提供异步任务的统一执行入口", + "管理任务的生命周期状态(运行、完成、错误)", + "记录任务执行耗时并进行性能监控", + "输出结构化日志以支持调试与运维观察", + "暴露任务状态快照用于系统健康检查" + ], + "interfaces": [ + { + "name": "TaskInitializer", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "TResult", + "param_type": "generic", + "is_optional": false, + "description": "任务返回结果的包装类型" + }, + { + "name": "TData", + "param_type": "generic", + "is_optional": false, + "description": "任务实际产出的数据类型" + } + ], + "return_type": null, + "description": "定义任务初始化行为的抽象接口" + }, + { + "name": "InitTask", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "TData", + "param_type": "generic", + "is_optional": false, + "description": "内部存储的数据类型" + } + ], + "return_type": null, + "description": "具体实现 TaskInitializer 的结构体,携带执行结果、耗时和状态" + }, + { + "name": "start", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "task_name", + "param_type": "&str", + "is_optional": false, + "description": "任务名称,用于日志标识" + }, + { + "name": "function", + "param_type": "F: FnOnce() -> Fut, Fut: Future>", + "is_optional": false, + "description": "被包装执行的异步闭包" + } + ], + "return_type": "impl Future>", + "description": "异步执行给定任务,更新状态并记录日志" + }, + { + "name": "dump", + "interface_type": "method", + "visibility": "public", + "parameters": [], + "return_type": "TaskDump", + "description": "导出当前任务的状态快照" + }, + { + "name": "default", + "interface_type": "impl Default", + "visibility": "public", + "parameters": [], + "return_type": "InitTask", + "description": "提供 InitTask 的默认构造方式" + } + ], + "dependencies": [ + { + "name": "std::future::Future", + "path": "std::future::Future", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "tokio::time::Instant", + "path": "tokio::time::Instant", + "is_external": true, + "line_number": 4, + "dependency_type": "async_runtime", + "version": null + }, + { + "name": "anyhow", + "path": "anyhow::Result", + "is_external": true, + "line_number": 6, + "dependency_type": "error_handling", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 64, + "number_of_functions": 3, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.57, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801197, + "prompt_hash": "501c146ce5aba3f2a64a6fd27f67b120", + "token_usage": { + "input_tokens": 859, + "output_tokens": 1140, + "total_tokens": 1999 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5064170bf87b00f6a19aafbdb3522d45.json b/.litho/cache/ai_code_insight/5064170bf87b00f6a19aafbdb3522d45.json new file mode 100644 index 0000000..2fdd042 --- /dev/null +++ b/.litho/cache/ai_code_insight/5064170bf87b00f6a19aafbdb3522d45.json @@ -0,0 +1,87 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/themes/index.ts", + "code_purpose": "util", + "importance_score": 0.8, + "description": "主题管理工具模块,用于获取、设置和应用应用程序的UI主题(亮色/暗色模式)。", + "functions": [ + "getTheme", + "setTheme", + "applyTheme", + "setWebInnerOnly" + ], + "interfaces": [ + "ThemePresets" + ] + }, + "detailed_description": "该组件是一个主题管理工具,负责处理应用程序的亮色和暗色主题切换。它通过localStorage持久化用户选择的主题,并调用Tauri API同步到原生应用层。同时,通过操作DOM类名来更新网页的视觉样式。`getTheme`从本地存储读取当前主题;`setTheme`保存主题并同步到应用层;`applyTheme`初始化或重新应用当前主题;`setWebInnerOnly`仅更新Web界面的CSS类。", + "responsibilities": [ + "管理应用程序的主题状态(亮色/暗色模式)", + "在localStorage中持久化用户主题偏好", + "与Tauri原生API通信以设置应用级主题", + "通过DOM操作更新Web界面的视觉样式" + ], + "interfaces": [ + { + "name": "ThemePresets", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": null, + "description": "定义支持的主题类型,仅限'light'和'dark'两种选项。" + }, + { + "name": "getTheme", + "interface_type": "function", + "visibility": "exported", + "parameters": [], + "return_type": "ThemePresets", + "description": "从localStorage中读取用户保存的主题设置,若未设置则返回默认值'light'。" + }, + { + "name": "setTheme", + "interface_type": "function", + "visibility": "exported", + "parameters": [ + { + "name": "theme", + "param_type": "ThemePresets", + "is_optional": false, + "description": "要设置的主题值,必须为'light'或'dark'" + } + ], + "return_type": "void", + "description": "将指定主题保存到localStorage并通知Tauri应用层进行全局主题设置。" + } + ], + "dependencies": [ + { + "name": "@tauri-apps/api/app", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "module_import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 27, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805736, + "prompt_hash": "5064170bf87b00f6a19aafbdb3522d45", + "token_usage": { + "input_tokens": 588, + "output_tokens": 729, + "total_tokens": 1317 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/509778d785842a165f6ec9f0e18014a0.json b/.litho/cache/ai_code_insight/509778d785842a165f6ec9f0e18014a0.json new file mode 100644 index 0000000..b8958d6 --- /dev/null +++ b/.litho/cache/ai_code_insight/509778d785842a165f6ec9f0e18014a0.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "zh.json", + "file_path": "app/src/lib/i18n/locales/zh.json", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "中文语言包配置文件,包含应用所有界面的文本内容翻译与展示文案。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个标准的JSON格式国际化(i18n)语言包,用于存储应用程序的中文界面文本。其结构按功能模块组织,如 common、main、reader、settings 等,每个模块下定义了对应的用户可见字符串,包括按钮标签、提示信息、菜单名称、对话框文本等。该文件不包含任何业务逻辑或可执行代码,纯粹作为资源配置使用,由前端框架在运行时根据当前语言环境动态加载并注入到UI组件中。", + "responsibilities": [ + "提供完整的中文用户界面文本资源", + "支持多语言切换下的文案映射", + "按功能模块组织翻译内容以提高可维护性", + "为表单验证、错误提示、操作反馈等场景提供本地化消息" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 183, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024700, + "prompt_hash": "509778d785842a165f6ec9f0e18014a0", + "token_usage": { + "input_tokens": 2858, + "output_tokens": 488, + "total_tokens": 3346 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/51362896b1facc80650e24ea8c5c785d.json b/.litho/cache/ai_code_insight/51362896b1facc80650e24ea8c5c785d.json new file mode 100644 index 0000000..79ad9b3 --- /dev/null +++ b/.litho/cache/ai_code_insight/51362896b1facc80650e24ea8c5c785d.json @@ -0,0 +1,41 @@ +{ + "data": { + "code_dossier": { + "name": "date.ts", + "file_path": "app/src/lib/utils/date.ts", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供日期格式化工具函数,将当前日期转换为YYYY-MM-DD字符串格式", + "functions": [ + "currentDateText" + ], + "interfaces": [] + }, + "detailed_description": "该组件包含一个工具函数currentDateText,用于获取当前日期并将其格式化为'YYYY-MM-DD'的字符串格式。函数通过JavaScript内置Date对象获取当前年、月、日,并对月份和日期进行补零处理,确保输出格式统一。主要服务于需要标准日期字符串表示的业务场景。", + "responsibilities": [ + "获取当前系统日期", + "将日期格式化为标准的YYYY-MM-DD字符串格式", + "确保月份和日期的两位数显示(补零处理)", + "提供可复用的日期格式化功能" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805994, + "prompt_hash": "51362896b1facc80650e24ea8c5c785d", + "token_usage": { + "input_tokens": 487, + "output_tokens": 383, + "total_tokens": 870 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/514d4c0b04d3d780ce01311309910cd8.json b/.litho/cache/ai_code_insight/514d4c0b04d3d780ce01311309910cd8.json new file mode 100644 index 0000000..b15a986 --- /dev/null +++ b/.litho/cache/ai_code_insight/514d4c0b04d3d780ce01311309910cd8.json @@ -0,0 +1,49 @@ +{ + "data": { + "code_dossier": { + "name": "FeedPackageEditPanel.svelte", + "file_path": "app/src/routes/main/widgets/FeedPackageEditPanel.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [ + "FeedPackageEditPanel" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,用于编辑信息流包(Feed Package)。由于源代码为空,无法确定其具体实现逻辑和功能细节。理想情况下,此类组件应提供表单输入、数据绑定、验证和提交功能,以支持用户对feed package的创建或修改操作。", + "responsibilities": [ + "作为信息流包编辑功能的UI容器", + "提供用户交互界面以编辑feed package数据", + "协调表单输入与数据提交逻辑" + ], + "interfaces": [ + { + "name": "FeedPackageEditPanel", + "interface_type": "component", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": null + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805830, + "prompt_hash": "514d4c0b04d3d780ce01311309910cd8", + "token_usage": { + "input_tokens": 410, + "output_tokens": 359, + "total_tokens": 769 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/53bacdb24378ff0ad9c4663c1b4e0fa7.json b/.litho/cache/ai_code_insight/53bacdb24378ff0ad9c4663c1b4e0fa7.json new file mode 100644 index 0000000..c2722fc --- /dev/null +++ b/.litho/cache/ai_code_insight/53bacdb24378ff0ad9c4663c1b4e0fa7.json @@ -0,0 +1,48 @@ +{ + "data": { + "code_dossier": { + "name": "toast.ts", + "file_path": "app/src/routes/main/stores/toast.ts", + "code_purpose": "util", + "importance_score": 0.8, + "description": "定义了两个全局通知toaster实例,用于在应用不同位置显示提示消息", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件使用@skeletonlabs/skeleton-svelte库的createToaster函数创建了两个预配置的toaster实例:globalToaster位于屏幕右下角,偏移30px;spriteToaster位于屏幕左下角,偏移128px。这两个实例可在应用各处导入使用,提供统一的通知展示样式和位置策略。", + "responsibilities": [ + "创建并导出全局通知toaster实例", + "定义通知组件的显示位置策略", + "提供统一的UI反馈机制", + "封装第三方通知库的初始化配置" + ], + "interfaces": [], + "dependencies": [ + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 10, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.1, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805787, + "prompt_hash": "53bacdb24378ff0ad9c4663c1b4e0fa7", + "token_usage": { + "input_tokens": 463, + "output_tokens": 387, + "total_tokens": 850 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5469f38188f245cce5d35a46f815b166.json b/.litho/cache/ai_code_insight/5469f38188f245cce5d35a46f815b166.json new file mode 100644 index 0000000..8be73bb --- /dev/null +++ b/.litho/cache/ai_code_insight/5469f38188f245cce5d35a46f815b166.json @@ -0,0 +1,67 @@ +{ + "data": { + "code_dossier": { + "name": "utils.ts", + "file_path": "app/src/lib/windows/utils.ts", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供Tauri桌面应用中窗口管理的工具函数,支持单例窗口展示和带回调的窗口打开功能。", + "functions": [ + "openWithCallback", + "showWindowSingleton" + ], + "interfaces": [] + }, + "detailed_description": "该组件封装了Tauri框架下窗口操作的核心逻辑。`showWindowSingleton` 函数用于确保指定标签的窗口在整个应用中仅存在一个实例,若已存在则聚焦该窗口,否则创建新窗口;`openWithCallback` 函数在此基础上扩展,允许在目标窗口关闭时通过事件机制触发回调函数,实现跨窗口通信。两个函数均基于Tauri的Window和Webview API构建,增强了窗口管理的复用性和一致性。", + "responsibilities": [ + "管理Tauri应用中的单例窗口生命周期", + "实现跨窗口异步回调通信机制", + "封装底层Tauri窗口API以提高调用安全性与一致性", + "处理URL参数拼接以传递回调事件标识" + ], + "interfaces": [], + "dependencies": [ + { + "name": "@tauri-apps/api/window", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "@tauri-apps/api/webview", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "@tauri-apps/api/event", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 43, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805724, + "prompt_hash": "5469f38188f245cce5d35a46f815b166", + "token_usage": { + "input_tokens": 710, + "output_tokens": 570, + "total_tokens": 1280 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/54dae1e05c3a4d3ee0f0e0df7f5317a8.json b/.litho/cache/ai_code_insight/54dae1e05c3a4d3ee0f0e0df7f5317a8.json new file mode 100644 index 0000000..eb1d517 --- /dev/null +++ b/.litho/cache/ai_code_insight/54dae1e05c3a4d3ee0f0e0df7f5317a8.json @@ -0,0 +1,88 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/llm/src/providers/mod.rs", + "code_purpose": "router", + "importance_score": 0.6, + "description": "LLM服务提供者的模块路由文件,组织不同LLM实现的内部模块结构", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是LLM功能模块的子模块聚合器,负责将多个具体的LLM服务提供者(如Mistral、Ollama、GLM、OpenAI兼容接口等)以及共享类型定义进行模块化组织。它通过pub和pub(crate)关键字控制模块的可见性,形成清晰的内部架构边界。作为路由组件,它不包含具体业务逻辑,而是承担着命名空间管理和访问控制的职责。", + "responsibilities": [ + "聚合管理所有LLM服务提供者的实现模块", + "通过可见性控制(pub/pub(crate))管理模块的外部访问权限", + "为上层模块提供统一的LLM提供者访问入口", + "维护LLM功能模块的内部目录结构和组织规范" + ], + "interfaces": [], + "dependencies": [ + { + "name": "llm_mistral", + "path": "crates/llm/src/providers/llm_mistral", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_ollama", + "path": "crates/llm/src/providers/llm_ollama", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_platform", + "path": "crates/llm/src/providers/llm_platform", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "types", + "path": "crates/llm/src/providers/types", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_glm", + "path": "crates/llm/src/providers/llm_glm", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_openaibase_like", + "path": "crates/llm/src/providers/llm_openaibase_like", + "is_external": false, + "line_number": 6, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805854, + "prompt_hash": "54dae1e05c3a4d3ee0f0e0df7f5317a8", + "token_usage": { + "input_tokens": 438, + "output_tokens": 660, + "total_tokens": 1098 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/54e89df6ef71b3e6a4c03591745171e6.json b/.litho/cache/ai_code_insight/54e89df6ef71b3e6a4c03591745171e6.json new file mode 100644 index 0000000..9407942 --- /dev/null +++ b/.litho/cache/ai_code_insight/54e89df6ef71b3e6a4c03591745171e6.json @@ -0,0 +1,60 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/feed_api_rs/src/startup/types.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义任务状态枚举和任务转储数据结构,用于表示任务的生命周期状态和执行时长信息。", + "functions": [], + "interfaces": [ + "Status", + "TaskDump" + ] + }, + "detailed_description": "该组件定义了两个核心类型:`Status` 枚举用于表示任务的生命周期状态(未启动、运行中、已完成、已中止、错误),`TaskDump` 结构体用于封装任务的状态和持续时间(以纳秒为单位)。这些类型主要用于任务监控、状态跟踪和性能分析场景。通过 `Clone` 和 `Copy` trait 的派生,确保了类型的高效复制语义,适用于高频传递的上下文。", + "responsibilities": [ + "定义任务的生命周期状态模型", + "封装任务执行状态与耗时信息", + "提供轻量级、可复制的数据传输对象", + "支持系统内任务状态的序列化与日志记录" + ], + "interfaces": [ + { + "name": "Status", + "interface_type": "enum", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "表示任务的五种可能状态:未启动、运行中、已完成、已中止、错误。" + }, + { + "name": "TaskDump", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "包含任务当前状态和执行持续时间的只读快照结构体。" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 14, + "number_of_functions": 0, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024592, + "prompt_hash": "54e89df6ef71b3e6a4c03591745171e6", + "token_usage": { + "input_tokens": 465, + "output_tokens": 590, + "total_tokens": 1055 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5602eecf348eaeca4f0eb4632f85cbcb.json b/.litho/cache/ai_code_insight/5602eecf348eaeca4f0eb4632f85cbcb.json new file mode 100644 index 0000000..05bc100 --- /dev/null +++ b/.litho/cache/ai_code_insight/5602eecf348eaeca4f0eb4632f85cbcb.json @@ -0,0 +1,496 @@ +{ + "data": { + "code_dossier": { + "name": "api.rs", + "file_path": "crates/feed_api_rs/src/features/api.rs", + "code_purpose": "api", + "importance_score": 0.8, + "description": "功能模块的门面API定义,提供统一接口供外部调用者访问核心功能。", + "functions": [], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件定义了名为FeaturesAPI的trait,作为系统功能模块的门面接口。它封装了订阅管理(添加、删除、重命名订阅包和订阅)、内容更新与读取、文章状态标记、应用配置管理、Ollama程序生命周期控制、外部文章打开、基于AI的文章交互以及关键词搜索等核心功能。所有方法均采用异步设计,返回impl Future,符合现代Rust异步编程范式。接口通过引用传递参数,保证效率,并广泛使用anyhow::Result进行错误处理,提升了API的健壮性和可维护性。", + "responsibilities": [ + "提供统一的功能访问接口(门面模式)", + "管理用户订阅内容(增删改查)", + "协调内容更新与数据存储", + "支持AI辅助阅读功能", + "管理系统配置与第三方服务集成" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "trait", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "功能模块的门面API定义,集中暴露系统核心功能。" + }, + { + "name": "add_feeds_package", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "feeds_package", + "param_type": "FeedsPackage", + "is_optional": false, + "description": "要添加的订阅包对象" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于添加订阅包,会同步到用户配置存储模块。如果订阅包已经存在,函数将返回一个错误。" + }, + { + "name": "remove_feeds_package", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "要删除的订阅包ID" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于删除订阅包,会同步到用户配置存储模块。如果订阅包不存在,函数将返回一个错误。" + }, + { + "name": "rename_feeds_package", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "要重命名的订阅包ID" + }, + { + "name": "new_name", + "param_type": "&str", + "is_optional": false, + "description": "新的订阅包名称" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于重命名订阅包,会同步到用户配置存储模块。如果订阅包不存在,函数将返回一个错误。" + }, + { + "name": "add_feed", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "目标订阅包ID" + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": "要添加的订阅描述" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于添加订阅到订阅包,会同步到用户配置存储模块。如果订阅已经存在,函数将返回一个错误。" + }, + { + "name": "remove_feed", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "所属订阅包ID" + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": "要移除的订阅ID" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于移除订阅包中的订阅,会同步到用户配置存储模块。如果订阅不存在,函数将返回一个错误。" + }, + { + "name": "rename_feed", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "所属订阅包ID" + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": "要重命名的订阅ID" + }, + { + "name": "new_name", + "param_type": "&str", + "is_optional": false, + "description": "新的订阅名称" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于重命名订阅包中的订阅,会同步到用户配置存储模块。如果订阅不存在,函数将返回一个错误。" + }, + { + "name": "change_feed_data", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "所属订阅包ID" + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": "要修改的订阅ID" + }, + { + "name": "data", + "param_type": "Vec", + "is_optional": false, + "description": "新的数据源列表" + } + ], + "return_type": "impl std::future::Future>", + "description": "用于修改订阅的数据源。" + }, + { + "name": "get_feeds_packages", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "impl std::future::Future>", + "description": "获得所有的订阅包信息。" + }, + { + "name": "get_feeds_by_package", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "要查询的订阅包ID" + } + ], + "return_type": "impl std::future::Future>", + "description": "获得指定订阅包中的订阅信息。" + }, + { + "name": "update_feed_contents", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "订阅包ID" + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": "订阅ID" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "可选的应用句柄用于UI通知" + } + ], + "return_type": "impl std::future::Future>", + "description": "更新订阅内容,将爬取数据源并做内容提取和总结、同步到数据存储模块。" + }, + { + "name": "read_feed_contents", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": "订阅ID" + }, + { + "name": "offset", + "param_type": "u64", + "is_optional": false, + "description": "分页偏移量" + }, + { + "name": "count", + "param_type": "u64", + "is_optional": false, + "description": "每页数量" + } + ], + "return_type": "impl std::future::Future>>", + "description": "读取订阅内容列表。" + }, + { + "name": "query_by_id", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "id", + "param_type": "i32", + "is_optional": false, + "description": "文章记录ID" + } + ], + "return_type": "impl std::future::Future>>", + "description": "根据ID查询单个文章记录。" + }, + { + "name": "mark_as_read", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "id", + "param_type": "i32", + "is_optional": false, + "description": "文章记录ID" + } + ], + "return_type": "impl std::future::Future>", + "description": "将指定文章标记为已读。" + }, + { + "name": "set_favorite", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "id", + "param_type": "i32", + "is_optional": false, + "description": "文章记录ID" + }, + { + "name": "is_favorite", + "param_type": "bool", + "is_optional": false, + "description": "是否收藏" + } + ], + "return_type": "impl std::future::Future>", + "description": "设置文章收藏状态。" + }, + { + "name": "get_app_config", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "impl std::future::Future>", + "description": "读取AppConfig。" + }, + { + "name": "set_app_config", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "app_config", + "param_type": "AppConfig", + "is_optional": false, + "description": "新的应用配置" + } + ], + "return_type": "impl std::future::Future>", + "description": "覆盖存储AppConfig。" + }, + { + "name": "get_ollama_status", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "impl std::future::Future>", + "description": "获取Ollama程序运行状态。" + }, + { + "name": "download_ollama", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "impl std::future::Future>", + "description": "下载Ollama程序。" + }, + { + "name": "launch_ollama", + "interface_type": "method", + "visibility": "pub", + "parameters": [], + "return_type": "impl std::future::Future>", + "description": "启动Ollama程序。" + }, + { + "name": "open_article_external", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "url", + "param_type": "&str", + "is_optional": false, + "description": "文章URL" + } + ], + "return_type": "impl std::future::Future>", + "description": "在外部浏览器中打开文章。" + }, + { + "name": "update_article_by_source", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "article_id", + "param_type": "i32", + "is_optional": false, + "description": "文章ID" + }, + { + "name": "source_text", + "param_type": "String", + "is_optional": false, + "description": "新的原始文本内容" + } + ], + "return_type": "impl std::future::Future>", + "description": "根据原始文本更新文章内容。" + }, + { + "name": "chat_with_article_assistant", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "article_id", + "param_type": "i32", + "is_optional": false, + "description": "文章ID" + }, + { + "name": "user_prompt", + "param_type": "&str", + "is_optional": false, + "description": "用户输入提示" + }, + { + "name": "history", + "param_type": "Vec", + "is_optional": false, + "description": "对话历史" + } + ], + "return_type": "impl std::future::Future>", + "description": "与文章助手进行对话。" + }, + { + "name": "search_contents_by_keyword", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "keyword", + "param_type": "&str", + "is_optional": false, + "description": "搜索关键词" + }, + { + "name": "offset", + "param_type": "u64", + "is_optional": false, + "description": "分页偏移量" + }, + { + "name": "count", + "param_type": "u64", + "is_optional": false, + "description": "每页数量" + } + ], + "return_type": "impl std::future::Future>>", + "description": "根据关键词搜索内容。" + } + ], + "dependencies": [ + { + "name": "ollama", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "recorder", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "types", + "path": null, + "is_external": false, + "line_number": 4, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 136, + "number_of_functions": 7, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 4.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805634, + "prompt_hash": "5602eecf348eaeca4f0eb4632f85cbcb", + "token_usage": { + "input_tokens": 1774, + "output_tokens": 3272, + "total_tokens": 5046 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/566758005c7599d9c1887e14c77d54b4.json b/.litho/cache/ai_code_insight/566758005c7599d9c1887e14c77d54b4.json new file mode 100644 index 0000000..68bf461 --- /dev/null +++ b/.litho/cache/ai_code_insight/566758005c7599d9c1887e14c77d54b4.json @@ -0,0 +1,234 @@ +{ + "data": { + "code_dossier": { + "name": "feeds.svelte.ts", + "file_path": "app/src/routes/main/stores/feeds.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "管理用户订阅源(feeds)的聚合状态与操作,提供本地状态存储及远程API同步能力。", + "functions": [ + "create", + "refresh", + "findPackagesOwnerByFeedId", + "addFeedsPackage", + "removeFeedsPackage", + "renameFeedsPackage", + "addFeed", + "removeFeed", + "renameFeed" + ], + "interfaces": [ + "StoreType", + "FeedsPackage", + "FeedTargetDescription", + "LoadingStore", + "Status" + ] + }, + "detailed_description": "该组件是一个Svelte状态管理模块,用于在前端维护用户订阅包(FeedsPackage)及其内部订阅项(Feed)的集合。它封装了对后端feeds服务的所有CRUD操作,并通过loading.svelte提供的加载状态机制统一处理异步请求的状态反馈(加载中、成功、失败)。组件暴露一个`create`工厂函数返回响应式store实例,包含当前feedPackages列表和多个操作方法。所有修改操作均通过`featuresApi`代理到后端实现,读取操作如`findPackagesOwnerByFeedId`则在本地内存中完成。支持自动刷新、增删改包/订阅等功能,是feeds功能域的核心协调者。", + "responsibilities": [ + "提供响应式的feeds数据存储与访问", + "协调本地状态与远程API的数据同步", + "封装feeds相关的所有业务操作接口", + "管理异步操作的加载状态与错误处理", + "实现基于ID的feed归属查询逻辑" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": null, + "description": "定义feeds store的结构,包括状态字段和可调用方法" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "exported", + "parameters": [], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个新的feeds store实例" + }, + { + "name": "refresh", + "interface_type": "method", + "visibility": "internal", + "parameters": [], + "return_type": "Promise", + "description": "从后端重新拉取所有feeds packages并更新本地状态" + }, + { + "name": "addFeedsPackage", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "feedsPackage", + "param_type": "FeedsPackage", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "添加新的feeds package并通过API持久化" + }, + { + "name": "removeFeedsPackage", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "根据ID删除指定的feeds package" + }, + { + "name": "renameFeedsPackage", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "newName", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "重命名指定ID的feeds package" + }, + { + "name": "addFeed", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "向指定package添加新的feed" + }, + { + "name": "removeFeed", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "从指定package中移除feed" + }, + { + "name": "renameFeed", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "packageId", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "newName", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "重命名指定feed" + }, + { + "name": "findPackagesOwnerByFeedId", + "interface_type": "method", + "visibility": "internal", + "parameters": [ + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "FeedsPackage | undefined", + "description": "根据feed ID查找其所属的package" + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "api-client", + "version": null + }, + { + "name": "LoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "state-utils", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 86, + "number_of_functions": 9, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024183, + "prompt_hash": "566758005c7599d9c1887e14c77d54b4", + "token_usage": { + "input_tokens": 1043, + "output_tokens": 1447, + "total_tokens": 2490 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/57ab254f6508149592b0ffef9299d668.json b/.litho/cache/ai_code_insight/57ab254f6508149592b0ffef9299d668.json new file mode 100644 index 0000000..f916f05 --- /dev/null +++ b/.litho/cache/ai_code_insight/57ab254f6508149592b0ffef9299d668.json @@ -0,0 +1,47 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/recorder/src/lib.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "定义了文章记录器的核心模块结构,包括服务、实体、操作器和路径管理。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件作为recorder功能的模块入口,通过pub mod声明导出了article_recorder_service、entity、operator和path四个核心子模块。它本身不包含具体实现,而是组织和封装了与文章记录相关的数据访问、业务逻辑和服务接口。其中operator模块负责数据库操作,entity定义数据模型,path处理文件路径,article_recorder_service可能封装高层业务逻辑。整体构成一个完整的文章记录数据管理单元。", + "responsibilities": [ + "组织和导出文章记录功能的相关模块", + "提供模块化结构以支持数据库操作和数据模型访问", + "作为其他组件访问recorder功能的统一入口" + ], + "interfaces": [], + "dependencies": [ + { + "name": "operator", + "path": "./crates/recorder/src/operator.rs", + "is_external": false, + "line_number": null, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 4, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805926, + "prompt_hash": "57ab254f6508149592b0ffef9299d668", + "token_usage": { + "input_tokens": 1705, + "output_tokens": 481, + "total_tokens": 2186 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5812b5594d8525d3532de9b18e171f96.json b/.litho/cache/ai_code_insight/5812b5594d8525d3532de9b18e171f96.json new file mode 100644 index 0000000..d47f286 --- /dev/null +++ b/.litho/cache/ai_code_insight/5812b5594d8525d3532de9b18e171f96.json @@ -0,0 +1,84 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/about/+page.svelte", + "source_summary": "", + "code_purpose": "page", + "importance_score": 0.8, + "description": "关于页面的Svelte组件,展示应用名称、版本信息及引擎版本,并提供访问官网按钮。", + "functions": [ + "onVisitHome" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit路由系统中的一个页面组件(+page.svelte),用于渲染应用的'关于'页面。在浏览器环境中,它异步获取应用名称、应用版本和Tauri运行时版本,并通过$state响应式变量更新UI。界面包含应用logo、名称、版本信息以及一个跳转到主页的按钮。右键菜单被禁用以提升用户体验一致性。", + "responsibilities": [ + "展示应用元信息(名称、版本)", + "加载并显示Tauri引擎版本", + "提供外部链接入口(官网访问)", + "管理页面级UI交互逻辑", + "防止右键上下文菜单弹出" + ], + "interfaces": [], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "@tauri-apps/api/app", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "api", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 4, + "dependency_type": "service", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": false, + "line_number": 5, + "dependency_type": "framework", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 6, + "dependency_type": "util", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 37, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 5.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024508, + "prompt_hash": "5812b5594d8525d3532de9b18e171f96", + "token_usage": { + "input_tokens": 742, + "output_tokens": 583, + "total_tokens": 1325 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/58b773ecbd9fd26592f36347631a3c29.json b/.litho/cache/ai_code_insight/58b773ecbd9fd26592f36347631a3c29.json new file mode 100644 index 0000000..a67048a --- /dev/null +++ b/.litho/cache/ai_code_insight/58b773ecbd9fd26592f36347631a3c29.json @@ -0,0 +1,66 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/llm/src/providers/types.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义LLM服务所需的核心数据类型和接口契约,包括AI参数配置和Completion服务抽象。", + "functions": [], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件定义了两个核心结构:AITargetOption 和 CompletionService。AITargetOption 是一个可序列化的配置结构体,用于封装调用大型语言模型(LLM)时的生成参数,如 temperature、seed、top_k、top_p 和 num_ctx,并为这些参数提供了合理的默认值。CompletionService 是一个异步 trait,抽象了 LLM 的 completion 能力,要求实现者提供一个异步方法 `completion`,接收字符串输入并返回 `anyhow::Result` 类型的结果,支持异步非阻塞调用。整体上,此文件作为 LLM 模块的数据建模与接口规范层,为上层调用者和底层实现者提供统一契约。", + "responsibilities": [ + "定义LLM生成请求的参数配置模型", + "为AI生成服务提供统一的异步接口契约", + "确保配置项具备合理默认值以降低使用成本", + "支持序列化以便于网络传输或持久化" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "pub", + "parameters": [ + { + "name": "message", + "param_type": "String", + "is_optional": false, + "description": "用户输入的prompt文本" + } + ], + "return_type": "impl std::future::Future>", + "description": "LLM Generate服务代理,用于调用Completion能力" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 28, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805842, + "prompt_hash": "58b773ecbd9fd26592f36347631a3c29", + "token_usage": { + "input_tokens": 609, + "output_tokens": 656, + "total_tokens": 1265 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5c768c8d6c8e6dd66ab215dce47b3f34.json b/.litho/cache/ai_code_insight/5c768c8d6c8e6dd66ab215dce47b3f34.json new file mode 100644 index 0000000..b453d27 --- /dev/null +++ b/.litho/cache/ai_code_insight/5c768c8d6c8e6dd66ab215dce47b3f34.json @@ -0,0 +1,48 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/llm/src/lib.rs", + "code_purpose": "agent", + "importance_score": 0.6, + "description": "LLM功能的核心模块入口,组织和导出LLM智能Agent相关组件", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是LLM系统的核心模块定义文件,通过mod关键字声明并公开了三个子模块:llm_agent(智能Agent核心逻辑)、providers(LLM服务提供商集成)和connector(HTTP客户端连接器)。它作为整个LLM功能的门面(facade),负责模块化组织和API导出,但本身不包含具体业务逻辑实现。其主要作用是建立代码的模块结构和访问控制边界。", + "responsibilities": [ + "作为LLM功能模块的根命名空间,提供统一的API导出入口", + "组织和管理LLM相关的子模块(agent、providers、connector)", + "控制模块间可见性与访问权限(通过pub关键字控制导出)", + "建立系统的模块化架构基础,支持功能解耦" + ], + "interfaces": [], + "dependencies": [ + { + "name": "connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 3, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805851, + "prompt_hash": "5c768c8d6c8e6dd66ab215dce47b3f34", + "token_usage": { + "input_tokens": 477, + "output_tokens": 476, + "total_tokens": 953 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5d3e653fa78c2a1cdd0adff16b3ca232.json b/.litho/cache/ai_code_insight/5d3e653fa78c2a1cdd0adff16b3ca232.json new file mode 100644 index 0000000..0c26880 --- /dev/null +++ b/.litho/cache/ai_code_insight/5d3e653fa78c2a1cdd0adff16b3ca232.json @@ -0,0 +1,88 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/scrap/src/search/types.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义搜索功能所需的数据类型和核心接口,特别是文章搜索提供者的抽象行为。", + "functions": [], + "interfaces": [ + "IProvider" + ] + }, + "detailed_description": "该组件定义了一个名为 IProvider 的 trait,用于抽象文章搜索服务的行为。其主要功能是为不同类型的搜索提供者(如本地搜索、网络搜索等)提供统一的异步接口。该 trait 包含一个 search_by_words 方法,接受关键词列表和可选的应用程序句柄,并返回一个异步 Future,解析为包含 Article 对象向量的结果。此设计支持插件化架构,允许在运行时注入不同的搜索实现。", + "responsibilities": [ + "定义搜索提供者的统一接口契约", + "支持基于关键词的异步文章搜索操作", + "通过泛型 Runtime 和 AppHandle 实现与 Tauri 框架的集成", + "作为不同类型搜索实现(如全文搜索、语义搜索)的抽象基类" + ], + "interfaces": [ + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "搜索提供者的抽象接口,定义了基于关键词搜索文章的方法。" + }, + { + "name": "search_by_words", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "用于搜索的关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri 应用句柄,用于访问应用状态或资源" + } + ], + "return_type": "impl std::future::Future>>", + "description": "执行基于关键词的文章搜索操作,支持异步处理和应用上下文传递。" + } + ], + "dependencies": [ + { + "name": "tauri", + "path": "tauri::{AppHandle, Runtime}", + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "types::Article", + "path": "types::Article", + "is_external": false, + "line_number": 2, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 10, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805916, + "prompt_hash": "5d3e653fa78c2a1cdd0adff16b3ca232", + "token_usage": { + "input_tokens": 472, + "output_tokens": 786, + "total_tokens": 1258 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5de2c8e6ae487ed907ad51fae5bbda30.json b/.litho/cache/ai_code_insight/5de2c8e6ae487ed907ad51fae5bbda30.json new file mode 100644 index 0000000..1cd71f7 --- /dev/null +++ b/.litho/cache/ai_code_insight/5de2c8e6ae487ed907ad51fae5bbda30.json @@ -0,0 +1,49 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/recorder/src/lib.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "定义了文章记录器的核心模块结构,包括服务、实体、操作器和路径管理。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是文章记录功能的模块入口,通过pub声明暴露article_recorder_service、entity、path等公共模块,并内部封装operator模块。其主要作用是组织和导出与文章记录相关的数据访问逻辑和服务接口。实际的数据操作由operator模块中的Operator结构体实现,包括数据库初始化、增删改查等操作。整体设计遵循Rust的模块化原则,将不同职责分离到独立模块中。", + "responsibilities": [ + "组织和导出文章记录相关功能模块", + "提供模块边界控制(公有/私有)", + "协调子模块之间的依赖关系", + "作为外部访问文章记录功能的统一入口" + ], + "interfaces": [], + "dependencies": [ + { + "name": "operator", + "path": "./crates/recorder/src/operator.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 4, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024642, + "prompt_hash": "5de2c8e6ae487ed907ad51fae5bbda30", + "token_usage": { + "input_tokens": 1713, + "output_tokens": 483, + "total_tokens": 2196 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5e9a3ba874f09a3229ccac54845fb3c8.json b/.litho/cache/ai_code_insight/5e9a3ba874f09a3229ccac54845fb3c8.json new file mode 100644 index 0000000..fb5c5d7 --- /dev/null +++ b/.litho/cache/ai_code_insight/5e9a3ba874f09a3229ccac54845fb3c8.json @@ -0,0 +1,105 @@ +{ + "data": { + "code_dossier": { + "name": "types.ts", + "file_path": "app/src/lib/widgets/types.ts", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.6, + "description": "定义前端UI组件所需的数据结构和类型,支持Markdown渲染、HTML内容展示及嵌入式WebView功能。", + "functions": [], + "interfaces": [ + "MarkdownProps", + "ArticleRenderProps", + "EmbedWebViewProps", + "ArticleRenderType" + ] + }, + "detailed_description": "该文件是一个TypeScript类型定义文件,主要用于声明前端UI组件(特别是富文本和嵌入式内容展示)所需的接口与联合类型。其中,MarkdownProps用于传递Markdown内容字符串;ArticleRenderProps是其同名类型别名,表明可复用性设计;ArticleRenderType为字面量联合类型,用于区分内容渲染方式(markdown或html);EmbedWebViewProps则定义了嵌入式WebView的属性,包括源地址和可选的加载生命周期回调函数。所有类型均通过export type导出,供其他组件安全引用。", + "responsibilities": [ + "定义Markdown内容渲染所需的属性结构", + "提供文章内容渲染类型的枚举支持(markdown/html)", + "声明嵌入式WebView组件的输入参数及事件回调机制", + "促进类型安全的跨组件通信", + "减少重复类型声明,提升代码可维护性" + ], + "interfaces": [ + { + "name": "MarkdownProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": "要渲染的Markdown格式文本内容" + } + ], + "return_type": null, + "description": "描述包含Markdown字符串值的对象结构" + }, + { + "name": "ArticleRenderProps", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": "MarkdownProps", + "description": "MarkdownProps的类型别名,用于语义化区分用途" + }, + { + "name": "ArticleRenderType", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": "'markdown' | 'html'", + "description": "表示文章渲染方式的字面量联合类型" + }, + { + "name": "EmbedWebViewProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "src", + "param_type": "string", + "is_optional": false, + "description": "嵌入网页的URL地址" + }, + { + "name": "onLoadStart", + "param_type": "(src: string) => void", + "is_optional": true, + "description": "页面开始加载时触发的回调" + }, + { + "name": "onLoadEnd", + "param_type": "(src: string) => void", + "is_optional": true, + "description": "页面加载完成时触发的回调" + } + ], + "return_type": null, + "description": "定义嵌入式WebView的行为配置属性" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 14, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024714, + "prompt_hash": "5e9a3ba874f09a3229ccac54845fb3c8", + "token_usage": { + "input_tokens": 493, + "output_tokens": 927, + "total_tokens": 1420 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/5f9c5382a31c90a4968f7b418edc9099.json b/.litho/cache/ai_code_insight/5f9c5382a31c90a4968f7b418edc9099.json new file mode 100644 index 0000000..bc68040 --- /dev/null +++ b/.litho/cache/ai_code_insight/5f9c5382a31c90a4968f7b418edc9099.json @@ -0,0 +1,76 @@ +{ + "data": { + "code_dossier": { + "name": "simulator.rs", + "file_path": "crates/scrap/src/simulator.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": null, + "functions": [ + "scrap_text_by_url" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了一个基于Tauri框架的网页内容抓取模拟器,通过创建隐藏的Webview窗口加载指定URL,并在页面加载后执行JavaScript代码提取document.documentElement.innerHTML。使用异步通道接收事件响应结果,并支持超时控制和资源清理。核心机制利用了Tauri的eval与事件监听能力,在无头模式下完成DOM内容抓取。", + "responsibilities": [ + "管理用于网页抓取的专用Webview窗口生命周期", + "执行远程页面内容提取并返回HTML源码", + "通过互斥锁确保同一时间仅运行一个抓取任务", + "处理页面加载超时及异常情况下的资源释放", + "与前端通过自定义事件通信获取执行结果" + ], + "interfaces": [], + "dependencies": [ + { + "name": "once_cell", + "path": "once_cell::sync::Lazy", + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog::error", + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": "tauri::{async_runtime, AppHandle, Listener, Manager, Runtime, Url, WebviewUrl, WebviewWindowBuilder}", + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + }, + { + "name": "tokio", + "path": "tokio::{sync::{oneshot, Mutex}, time::{sleep, Duration}}", + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 81, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 4.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024375, + "prompt_hash": "5f9c5382a31c90a4968f7b418edc9099", + "token_usage": { + "input_tokens": 1190, + "output_tokens": 587, + "total_tokens": 1777 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/62619e7ccab878642efc666b41a43eb5.json b/.litho/cache/ai_code_insight/62619e7ccab878642efc666b41a43eb5.json new file mode 100644 index 0000000..8647b7a --- /dev/null +++ b/.litho/cache/ai_code_insight/62619e7ccab878642efc666b41a43eb5.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/+page.svelte", + "source_summary": "", + "code_purpose": "page", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Svelte框架下的路由页面组件,用于定义特定路由的UI和逻辑。但由于源代码为空,实际功能无法确定,可能为占位符或待实现页面。", + "responsibilities": [ + "作为应用中某个路由的展示页面入口", + "负责渲染该路径下的用户界面内容", + "可能承载数据加载与状态管理逻辑(当前未实现)" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024719, + "prompt_hash": "62619e7ccab878642efc666b41a43eb5", + "token_usage": { + "input_tokens": 407, + "output_tokens": 282, + "total_tokens": 689 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/63464ab4d38a6e724c67ffeea505b685.json b/.litho/cache/ai_code_insight/63464ab4d38a6e724c67ffeea505b685.json new file mode 100644 index 0000000..4616402 --- /dev/null +++ b/.litho/cache/ai_code_insight/63464ab4d38a6e724c67ffeea505b685.json @@ -0,0 +1,123 @@ +{ + "data": { + "code_dossier": { + "name": "path.rs", + "file_path": "crates/recorder/src/path.rs", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供应用数据目录和文件路径的管理功能,确保所需目录存在并返回正确路径。", + "functions": [ + "get_appdata_articles", + "get_appdata_file", + "get_appdata_file_in_dir", + "ensure_dir_in_appdata_prepared", + "ensure_app_data_prepared", + "ensure_dir_prepared" + ], + "interfaces": [] + }, + "detailed_description": "该组件负责处理与应用程序数据存储相关的路径操作。它定义了常量用于指定应用数据文件夹和数据库文件名,并提供了多个公共函数来获取不同场景下的文件路径。所有路径都基于系统本地数据目录(如Linux上的~/.local/share),并在访问前确保目标目录已正确创建。核心逻辑集中在递进式的路径准备机制:从确保根AppData目录存在,到支持子目录的按需创建,从而保证后续文件读写操作的可靠性。", + "responsibilities": [ + "管理应用程序的数据存储路径结构", + "确保应用所需的数据目录存在并可写", + "提供统一的路径生成接口供其他模块使用", + "封装底层文件系统操作细节" + ], + "interfaces": [ + { + "name": "get_appdata_articles", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "PathBuf", + "description": "获取Recorder数据库文件的完整路径" + }, + { + "name": "get_appdata_file", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "file_name", + "param_type": "P: AsRef", + "is_optional": false, + "description": null + } + ], + "return_type": "PathBuf", + "description": "获取App Data下指定文件的路径" + }, + { + "name": "get_appdata_file_in_dir", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "sub_dir_name", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "file_name", + "param_type": "P: AsRef", + "is_optional": false, + "description": null + } + ], + "return_type": "PathBuf", + "description": "获取App Data下指定文件夹中的文件路径" + }, + { + "name": "ensure_dir_prepared", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "dir_path", + "param_type": "PathBuf", + "is_optional": false, + "description": null + } + ], + "return_type": "PathBuf", + "description": "确保给定路径的目录存在,若不存在则创建" + } + ], + "dependencies": [ + { + "name": "std::fs", + "path": "std::fs", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "dirs", + "path": "dirs", + "is_external": true, + "line_number": 2, + "dependency_type": "external_crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 45, + "number_of_functions": 6, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805625, + "prompt_hash": "63464ab4d38a6e724c67ffeea505b685", + "token_usage": { + "input_tokens": 915, + "output_tokens": 905, + "total_tokens": 1820 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/63b76c51282dec5d5db2219968bd5c99.json b/.litho/cache/ai_code_insight/63b76c51282dec5d5db2219968bd5c99.json new file mode 100644 index 0000000..f1734e1 --- /dev/null +++ b/.litho/cache/ai_code_insight/63b76c51282dec5d5db2219968bd5c99.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/feed_api_rs/src/lib.rs", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.6, + "description": "定义了feed_api_rs库的模块结构,导出核心功能模块供外部使用。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是feed_api_rs库的根模块,通过pub mod声明导出了application_context、features和startup三个公共模块,同时包含一个私有的utils模块。它主要起到组织和封装内部模块的作用,为外部用户提供统一的模块访问入口。其职责在于构建清晰的模块化结构,便于代码维护和功能扩展。", + "responsibilities": [ + "组织和管理feed_api_rs库的模块结构", + "提供公共模块的导出接口", + "封装内部工具模块(utils)", + "作为库的入口点协调各子模块关系", + "维护模块间的可见性控制" + ], + "interfaces": [], + "dependencies": [ + { + "name": "utils", + "path": "./crates/feed_api_rs/src/utils.rs", + "is_external": false, + "line_number": null, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 4, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024577, + "prompt_hash": "63b76c51282dec5d5db2219968bd5c99", + "token_usage": { + "input_tokens": 650, + "output_tokens": 434, + "total_tokens": 1084 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/65a4ded8f7b861f8d55aecf58fe0005e.json b/.litho/cache/ai_code_insight/65a4ded8f7b861f8d55aecf58fe0005e.json new file mode 100644 index 0000000..59b79d0 --- /dev/null +++ b/.litho/cache/ai_code_insight/65a4ded8f7b861f8d55aecf58fe0005e.json @@ -0,0 +1,329 @@ +{ + "data": { + "code_dossier": { + "name": "types.ts", + "file_path": "app/src/routes/main/widgets/types.ts", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "定义前端UI组件所需的各种类型接口,包括属性传递和状态结构。", + "functions": [], + "interfaces": [ + "FeedsListProps", + "SearchBarProps", + "ArticleReaderProps", + "ArticlesGroup", + "ArticlesListProps", + "FooterProps", + "AISpriteProps", + "ArticleReadMode" + ] + }, + "detailed_description": "该组件是一个类型定义文件,专门用于声明前端UI组件之间的共享类型接口。它导入多个Svelte store的类型,并定义了如FeedsListProps、ArticlesListProps等组件属性接口,以及ArticlesGroup这样的数据分组结构。同时定义了一个联合类型ArticleReadMode来表示文章阅读模式。所有类型均通过export type导出,供其他组件引用,确保类型安全和一致性。", + "responsibilities": [ + "定义UI组件间通信的属性接口", + "统一管理前端组件依赖的状态store类型", + "提供数据结构类型定义(如ArticlesGroup)", + "定义可选值的联合类型(如阅读模式)", + "促进类型安全的组件间交互" + ], + "interfaces": [ + { + "name": "FeedsListProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "FeedsStoreType", + "is_optional": false, + "description": null + }, + { + "name": "selectedFeedId", + "param_type": "string | undefined", + "is_optional": true, + "description": null + }, + { + "name": "onFeedPressed", + "param_type": "(feedId: string) => void", + "is_optional": false, + "description": null + }, + { + "name": "onSelectToday", + "param_type": "() => void", + "is_optional": false, + "description": null + }, + { + "name": "onSelectWeekend", + "param_type": "() => void", + "is_optional": false, + "description": null + }, + { + "name": "isTodaySelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "isWeekendSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "onSelectFavorite", + "param_type": "() => void", + "is_optional": false, + "description": null + }, + { + "name": "isFavoriteSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "onSelectUnread", + "param_type": "() => void", + "is_optional": false, + "description": null + }, + { + "name": "isUnreadSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "SearchBarProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "SearchStoreType", + "is_optional": false, + "description": null + }, + { + "name": "articles_store", + "param_type": "ListStoreType", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticleReaderProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "articleId", + "param_type": "number", + "is_optional": false, + "description": null + }, + { + "name": "store", + "param_type": "ReaderStoreType", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticlesGroup", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "name", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "articles", + "param_type": "Article[]", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticlesListProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "ListStoreType", + "is_optional": false, + "description": null + }, + { + "name": "markAsRead", + "param_type": "(articleId: number) => Promise", + "is_optional": false, + "description": null + }, + { + "name": "isFilterActived", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "isFeedSpecified", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "selectedArticle", + "param_type": "Article | null", + "is_optional": false, + "description": null + }, + { + "name": "onArticlePressed", + "param_type": "(article: Article) => void", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "FooterProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "tasksStore", + "param_type": "TasksStoreType", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "AISpriteProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "AISpriteStore", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "ArticleReadMode", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": "'optimized' | 'melted' | 'original'", + "description": null + } + ], + "dependencies": [ + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 1, + "dependency_type": "type import", + "version": null + }, + { + "name": "SearchStoreType", + "path": "../stores/articles/search/index.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "type import", + "version": null + }, + { + "name": "ListStoreType", + "path": "../stores/articles/list/index.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "type import", + "version": null + }, + { + "name": "TasksStoreType", + "path": "../stores/tasks.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "type import", + "version": null + }, + { + "name": "FeedsStoreType", + "path": "../stores/feeds.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "type import", + "version": null + }, + { + "name": "ReaderStoreType", + "path": "../stores/reader.svelte", + "is_external": false, + "line_number": 6, + "dependency_type": "type import", + "version": null + }, + { + "name": "AISpriteStore", + "path": "../stores/sprite.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "type import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 66, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024229, + "prompt_hash": "65a4ded8f7b861f8d55aecf58fe0005e", + "token_usage": { + "input_tokens": 834, + "output_tokens": 1579, + "total_tokens": 2413 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/6654b7f0e0b6315d59bea218097bda8b.json b/.litho/cache/ai_code_insight/6654b7f0e0b6315d59bea218097bda8b.json new file mode 100644 index 0000000..a1eb74f --- /dev/null +++ b/.litho/cache/ai_code_insight/6654b7f0e0b6315d59bea218097bda8b.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "app.d.ts", + "file_path": "app/src/app.d.ts", + "code_purpose": "entry", + "importance_score": 0.6, + "description": "SvelteKit应用类型声明文件,用于扩展全局App命名空间以定义框架所需接口", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该文件是SvelteKit项目的全局类型声明文件,通过declare global语法扩展了App命名空间。它为SvelteKit框架提供类型定义入口,允许开发者自定义Error、Locals、PageData、PageState和Platform等接口。当前这些接口均被注释,表示尚未实现具体类型定义,但保留了未来扩展的可能性。此文件主要用于TypeScript类型系统集成,不影响运行时逻辑。", + "responsibilities": [ + "为SvelteKit框架提供全局类型声明扩展点", + "定义应用程序级别的类型接口契约", + "支持服务器端locals对象的类型安全传递", + "维护页面数据和状态的类型一致性", + "集成平台特定环境的类型定义" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 13, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805980, + "prompt_hash": "6654b7f0e0b6315d59bea218097bda8b", + "token_usage": { + "input_tokens": 466, + "output_tokens": 447, + "total_tokens": 913 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/66e11055ecfddc815b84ef74734c929e.json b/.litho/cache/ai_code_insight/66e11055ecfddc815b84ef74734c929e.json new file mode 100644 index 0000000..091ad62 --- /dev/null +++ b/.litho/cache/ai_code_insight/66e11055ecfddc815b84ef74734c929e.json @@ -0,0 +1,103 @@ +{ + "data": { + "code_dossier": { + "name": "application_context.rs", + "file_path": "crates/feed_api_rs/src/application_context.rs", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.6, + "description": "定义应用程序上下文结构及其宿主访问机制,用于在系统各组件间共享配置信息。", + "functions": [ + "new", + "get_context", + "copy_context" + ], + "interfaces": [ + "ContextHost" + ] + }, + "detailed_description": "该组件定义了 `ApplicationContext` 结构体,用于封装应用运行所需的核心配置(AppConfig 和 UserConfig)。通过 `ContextHost` trait 提供统一的上下文访问契约,允许系统中的其他组件以一致的方式获取和复制上下文实例。`ContextHostWrapper` 是该 trait 的具体实现,包装了一个 `ApplicationContext` 实例并提供安全的访问方法。整体设计支持上下文的不可变共享与克隆,适用于多模块协作场景。", + "responsibilities": [ + "封装应用程序的全局配置数据", + "提供对配置上下文的安全只读访问", + "支持上下文对象的复制与共享", + "定义上下文宿主的标准接口规范", + "促进依赖解耦和测试可替代性" + ], + "interfaces": [ + { + "name": "ContextHost", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "context", + "param_type": "ApplicationContext", + "is_optional": false, + "description": "初始化宿主时传入的应用上下文实例" + } + ], + "return_type": null, + "description": "定义上下文宿主的行为契约,确保所有宿主实现都能提供对 ApplicationContext 的访问能力。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "context", + "param_type": "ApplicationContext", + "is_optional": false, + "description": "要包装的应用上下文" + } + ], + "return_type": "Self", + "description": "构造一个新的 ContextHostWrapper 实例" + }, + { + "name": "get_context", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "&ApplicationContext", + "description": "获取对内部 ApplicationContext 的不可变引用" + }, + { + "name": "copy_context", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "ApplicationContext", + "description": "克隆并返回一份 ApplicationContext 的副本" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 35, + "number_of_functions": 3, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.1, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024585, + "prompt_hash": "66e11055ecfddc815b84ef74734c929e", + "token_usage": { + "input_tokens": 607, + "output_tokens": 847, + "total_tokens": 1454 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/67b0e101babd39897cdf5a26e51de157.json b/.litho/cache/ai_code_insight/67b0e101babd39897cdf5a26e51de157.json new file mode 100644 index 0000000..b82c083 --- /dev/null +++ b/.litho/cache/ai_code_insight/67b0e101babd39897cdf5a26e51de157.json @@ -0,0 +1,118 @@ +{ + "data": { + "code_dossier": { + "name": "tasks.svelte.ts", + "file_path": "app/src/routes/main/stores/tasks.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "任务状态管理Store,用于跟踪异步操作的加载状态", + "functions": [ + "createPending", + "create" + ], + "interfaces": [ + "StoreType", + "PendingItem" + ] + }, + "detailed_description": "该组件是一个Svelte状态管理模块,负责集中管理应用中所有异步任务的执行状态。它通过封装loading状态、维护待处理任务队列,并提供统一的状态反馈(如'处理中...'、'就绪'、'出现错误'等)来实现对异步操作生命周期的可视化控制。组件使用Svelte的$state和$derived响应式语法,自动计算整体任务状态和状态文本,并对外暴露添加、查询和移除任务的操作接口。", + "responsibilities": [ + "管理异步任务的生命周期状态", + "聚合多个并行任务的整体状态", + "提供任务状态的响应式更新机制", + "生成用户友好的状态显示文本", + "与loading状态组件协同工作" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义任务管理Store的公开接口,包含状态属性和操作方法" + }, + { + "name": "PendingItem", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "表示单个待处理任务的数据结构,包含描述、加载状态和关联的Promise" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个新的任务管理Store实例" + }, + { + "name": "createPending", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "description", + "param_type": "string", + "is_optional": false, + "description": "任务描述文本" + }, + { + "name": "promise", + "param_type": "Promise", + "is_optional": false, + "description": "关联的异步操作Promise" + } + ], + "return_type": "PendingItem", + "description": "创建一个新的待处理任务项" + } + ], + "dependencies": [ + { + "name": "LoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 1, + "dependency_type": "type-import", + "version": null + }, + { + "name": "createLoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "function-import", + "version": null + }, + { + "name": "Status", + "path": "./loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "enum-import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 7.0, + "lines_of_code": 85, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.35, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024192, + "prompt_hash": "67b0e101babd39897cdf5a26e51de157", + "token_usage": { + "input_tokens": 1004, + "output_tokens": 888, + "total_tokens": 1892 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/684e37e171a28e045821f6dfba331a14.json b/.litho/cache/ai_code_insight/684e37e171a28e045821f6dfba331a14.json new file mode 100644 index 0000000..6814754 --- /dev/null +++ b/.litho/cache/ai_code_insight/684e37e171a28e045821f6dfba331a14.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "env.rs", + "file_path": "app/src-tauri/src/env.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "用于判断当前程序是否以守护进程模式启动的工具函数。", + "functions": [ + "is_daemon" + ], + "interfaces": [ + "is_daemon" + ] + }, + "detailed_description": "该组件提供了一个名为 `is_daemon` 的布尔函数,用于检测应用程序是否以特定命令行参数(DAEMON_FEEDS_SCHEDULE_UPDATE)启动。它通过读取第一个命令行参数并与预定义常量进行比较来实现这一逻辑。此功能主要用于区分常规应用启动和后台守护进程调度任务的执行场景。", + "responsibilities": [ + "解析命令行参数以确定启动模式", + "提供简洁的API判断是否为守护进程模式", + "与系统环境交互获取运行时参数" + ], + "interfaces": [ + { + "name": "is_daemon", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "bool", + "description": "检查当前进程是否以 DAEMON_FEEDS_SCHEDULE_UPDATE 参数启动" + } + ], + "dependencies": [ + { + "name": "crate::daemon::args::DAEMON_FEEDS_SCHEDULE_UPDATE", + "path": "src/daemon/args.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "constant", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024667, + "prompt_hash": "684e37e171a28e045821f6dfba331a14", + "token_usage": { + "input_tokens": 459, + "output_tokens": 481, + "total_tokens": 940 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/68d760b0d05eb65fa4348484009855df.json b/.litho/cache/ai_code_insight/68d760b0d05eb65fa4348484009855df.json new file mode 100644 index 0000000..741bc6f --- /dev/null +++ b/.litho/cache/ai_code_insight/68d760b0d05eb65fa4348484009855df.json @@ -0,0 +1,59 @@ +{ + "data": { + "code_dossier": { + "name": "monitor.rs", + "file_path": "app/src-tauri/src/monitor.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": null, + "functions": [ + "start" + ], + "interfaces": [] + }, + "detailed_description": "该组件负责初始化Sentry错误监控服务。在应用启动时调用`start`函数,通过提供的DSN配置连接到Sentry服务器,并自动绑定当前代码的发布版本(使用宏`release_name!()`)。该功能用于捕获运行时异常、错误和性能问题,支持远程监控和调试。", + "responsibilities": [ + "初始化Sentry监控客户端", + "绑定应用发布版本信息以便追踪", + "为全局错误捕获提供运行时上下文" + ], + "interfaces": [ + { + "name": "start", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "nil", + "description": "启动Sentry监控服务,返回一个RAII守卫以维持会话生命周期" + } + ], + "dependencies": [ + { + "name": "sentry", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 9, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024666, + "prompt_hash": "68d760b0d05eb65fa4348484009855df", + "token_usage": { + "input_tokens": 488, + "output_tokens": 405, + "total_tokens": 893 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/696df1c6fca3fed85872b7040c31b6e9.json b/.litho/cache/ai_code_insight/696df1c6fca3fed85872b7040c31b6e9.json new file mode 100644 index 0000000..b62b536 --- /dev/null +++ b/.litho/cache/ai_code_insight/696df1c6fca3fed85872b7040c31b6e9.json @@ -0,0 +1,83 @@ +{ + "data": { + "code_dossier": { + "name": "+layout.svelte", + "file_path": "app/src/routes/+layout.svelte", + "code_purpose": "router", + "importance_score": 0.6, + "description": "SvelteKit路由布局组件,负责应用根级布局和主题初始化。", + "functions": [ + "onMount" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit应用的根布局组件(+layout.svelte),在页面渲染时执行一次。其主要功能是在组件挂载时初始化应用的主题系统:首先监听系统的深色模式偏好设置(prefers-color-scheme),当系统主题变化时通过setWebInnerOnly函数动态切换应用主题;其次调用applyTheme()立即应用当前主题。使用onMount生命周期钩子确保DOM加载完成后执行,并正确注册了事件监听器的清理逻辑,防止内存泄漏。", + "responsibilities": [ + "管理应用根级UI布局结构", + "初始化并应用用户界面主题", + "监听系统级深色模式偏好变化", + "确保主题相关资源的正确加载与卸载", + "提供子路由页面的插槽(slot)容器" + ], + "interfaces": [ + { + "name": "onMount", + "interface_type": "lifecycle", + "visibility": "private", + "parameters": [ + { + "name": "callback", + "param_type": "() => void | (() => void)", + "is_optional": false, + "description": "挂载后执行的回调函数" + } + ], + "return_type": "void", + "description": "Svelte生命周期钩子,在组件挂载到DOM后执行" + } + ], + "dependencies": [ + { + "name": "svelte", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "$lib/themes", + "path": "$lib/themes", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "app.css", + "path": "app/src/routes/../app.css", + "is_external": false, + "line_number": 1, + "dependency_type": "stylesheet", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 20, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758806040, + "prompt_hash": "696df1c6fca3fed85872b7040c31b6e9", + "token_usage": { + "input_tokens": 536, + "output_tokens": 653, + "total_tokens": 1189 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/6983fc30af9bc60b1b9af1ecd0e341f6.json b/.litho/cache/ai_code_insight/6983fc30af9bc60b1b9af1ecd0e341f6.json new file mode 100644 index 0000000..f0a072d --- /dev/null +++ b/.litho/cache/ai_code_insight/6983fc30af9bc60b1b9af1ecd0e341f6.json @@ -0,0 +1,180 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/settings/+page.svelte", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.8, + "description": "应用设置页面,管理主题、LLM配置、启动行为等全局配置项。", + "functions": [ + "switchTheme", + "selectLang", + "onAutoStartUpSwitched", + "onFrequencyUpdateSwitched", + "openGLMGuide", + "updateAppConfig", + "afterAppConfigUpdated", + "createSaveLLMFormAction", + "createLLMSwitcherAction", + "restoreLLMFormOllama", + "restoreLLMFormGLM", + "restoreLLMFormOpenAILike", + "restoreLLMFormPlatform" + ], + "interfaces": [ + "PressuredHandler", + "CheckSwitchedHandler", + "SelectionSelectedHandler" + ] + }, + "detailed_description": "该组件是应用程序的设置中心页面,主要负责展示和管理用户的全局配置。功能包括:1) 主题切换(亮色/暗色模式);2) 多种LLM提供商(Ollama、GLM、OpenAI兼容接口)的配置与激活;3) 应用行为设置如开机自启和后台更新频率;4) 显示应用及系统版本信息。组件通过Tauri插件获取系统环境信息,并利用Svelte的状态管理实现响应式UI更新。所有配置变更均通过`featuresApi`持久化到后端存储。", + "responsibilities": [ + "管理用户界面主题偏好设置", + "处理多种LLM服务提供商的配置输入与验证", + "协调应用级行为配置(如自动启动、更新策略)", + "展示应用元信息与系统环境详情", + "提供配置变更的保存与还原机制" + ], + "interfaces": [ + { + "name": "PressuredHandler", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "表示一个无参数的事件处理函数类型" + }, + { + "name": "CheckSwitchedHandler", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "复选框状态切换时的回调函数类型" + }, + { + "name": "SelectionSelectedHandler", + "interface_type": "type", + "visibility": "private", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "下拉选项被选择时的回调函数类型" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "@tauri-apps/api/app", + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": true, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "@tauri-apps/api/app", + "path": "@tauri-apps/api/app", + "is_external": true, + "line_number": 3, + "dependency_type": "plugin", + "version": null + }, + { + "name": "@tauri-apps/plugin-os", + "path": "@tauri-apps/plugin-os", + "is_external": true, + "line_number": 4, + "dependency_type": "plugin", + "version": null + }, + { + "name": "@tauri-apps/plugin-autostart", + "path": "@tauri-apps/plugin-autostart", + "is_external": true, + "line_number": 5, + "dependency_type": "plugin", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 6, + "dependency_type": "service", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 7, + "dependency_type": "utility", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 8, + "dependency_type": "ui", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 9, + "dependency_type": "model", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 10, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/themes", + "path": "$lib/themes", + "is_external": false, + "line_number": 11, + "dependency_type": "theme", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 33.0, + "lines_of_code": 653, + "number_of_functions": 14, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.65 + } + }, + "timestamp": 1759024505, + "prompt_hash": "6983fc30af9bc60b1b9af1ecd0e341f6", + "token_usage": { + "input_tokens": 6041, + "output_tokens": 1150, + "total_tokens": 7191 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/69e10635102689d195801f1a76d9360a.json b/.litho/cache/ai_code_insight/69e10635102689d195801f1a76d9360a.json new file mode 100644 index 0000000..d6a0d25 --- /dev/null +++ b/.litho/cache/ai_code_insight/69e10635102689d195801f1a76d9360a.json @@ -0,0 +1,144 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/scrap/src/search/mod.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "统一搜索提供者枚举,封装百度和必应搜索实现,支持基于关键词的网页内容抓取与聚合。", + "functions": [ + "search_by_words", + "fetch" + ], + "interfaces": [ + "IProvider", + "IFetcher" + ] + }, + "detailed_description": "该组件定义了一个名为ScrapProviderEnums的枚举类型,用于封装多种搜索引擎(当前为百度和必应)的具体实现。通过实现IProvider和IFetcher两个接口,该组件提供了统一的搜索和服务获取能力。其主要逻辑是根据枚举变体转发search_by_words调用到底层具体提供商,并在fetch方法中集成日志记录、关键词提取和结果聚合功能,从而实现对FeedTargetDescription描述的目标内容进行自动化抓取。", + "responsibilities": [ + "作为多搜索引擎的统一抽象入口", + "协调不同搜索提供商(如百度、必应)的行为一致性", + "执行基于关键词的内容抓取流程", + "集成日志记录以支持运行时监控", + "将原始数据源转换为标准化的文章列表输出" + ], + "interfaces": [ + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义搜索提供者的通用行为契约" + }, + { + "name": "search_by_words", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "待搜索的关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri应用句柄,用于跨平台操作" + } + ], + "return_type": "anyhow::Result>", + "description": "执行基于关键词的搜索并返回文章结果" + }, + { + "name": "fetch", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri应用句柄" + }, + { + "name": "_llm_section", + "param_type": "&LLMSection", + "is_optional": false, + "description": "LLM相关配置信息(当前未使用)" + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": "目标抓取源的描述信息" + } + ], + "return_type": "anyhow::Result>", + "description": "根据FeedTargetDescription执行完整抓取流程" + } + ], + "dependencies": [ + { + "name": "::types", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::search::types::IProvider", + "path": "crates/scrap/src/search/types.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 50, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805509, + "prompt_hash": "69e10635102689d195801f1a76d9360a", + "token_usage": { + "input_tokens": 765, + "output_tokens": 1031, + "total_tokens": 1796 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/6b397ec9a37a982794b1c3f095d54c0e.json b/.litho/cache/ai_code_insight/6b397ec9a37a982794b1c3f095d54c0e.json new file mode 100644 index 0000000..5fd5a59 --- /dev/null +++ b/.litho/cache/ai_code_insight/6b397ec9a37a982794b1c3f095d54c0e.json @@ -0,0 +1,53 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/llm/src/lib.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.6, + "description": "LLM功能的核心模块聚合器,提供统一的接口访问入口。", + "functions": [ + "pub mod llm_agent", + "mod connector", + "pub mod providers" + ], + "interfaces": [] + }, + "detailed_description": "该组件作为LLM(大语言模型)功能的顶层模块聚合器,主要职责是组织和导出子模块。它公开了`llm_agent`和`providers`模块供外部使用,同时私有引入`connector`模块用于内部HTTP客户端管理。整体结构遵循Rust的模块化设计原则,通过合理的可见性控制实现关注点分离。", + "responsibilities": [ + "聚合LLM相关功能模块", + "定义公共API边界", + "管理内部模块依赖关系", + "提供统一的功能导出入口" + ], + "interfaces": [], + "dependencies": [ + { + "name": "connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 3, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.8 + } + }, + "timestamp": 1759024566, + "prompt_hash": "6b397ec9a37a982794b1c3f095d54c0e", + "token_usage": { + "input_tokens": 485, + "output_tokens": 403, + "total_tokens": 888 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/6ccf5fd00ecfadf659131e813593fba4.json b/.litho/cache/ai_code_insight/6ccf5fd00ecfadf659131e813593fba4.json new file mode 100644 index 0000000..462191b --- /dev/null +++ b/.litho/cache/ai_code_insight/6ccf5fd00ecfadf659131e813593fba4.json @@ -0,0 +1,252 @@ +{ + "data": { + "code_dossier": { + "name": "bing.rs", + "file_path": "crates/scrap/src/search/bing.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现Bing搜索引擎的网页抓取与内容解析功能,支持通过关键词搜索并提取文章摘要和正文内容。", + "functions": [ + "Provider::new", + "Provider::prepare_target_sources", + "Provider::convert", + "IProvider::search_by_words" + ], + "interfaces": [ + "IProvider" + ] + }, + "detailed_description": "该组件实现了针对 Bing 搜索引擎的爬虫功能,主要职责是根据用户输入的关键词发起搜索请求,解析返回的 HTML 页面以提取搜索结果列表,并进一步抓取每个结果页面的正文内容。组件使用 reqwest 发起 HTTP 请求,scraper 进行 HTML 解析,结合自定义的选择器定位关键元素(如标题、链接、摘要等)。同时集成 LLMSection 实现内容智能处理,并通过 article_reader 模块异步读取目标网页全文。整个流程支持 Tauri 应用上下文调用或独立客户端模式。", + "responsibilities": [ + "封装 Bing 搜索接口并构造合规请求 URL", + "解析 Bing 搜索结果页的 HTML 结构,提取标题、链接和摘要信息", + "调用文章阅读器抓取目标网页的完整内容", + "将原始搜索结果转换为标准化的文章对象列表", + "提供统一的 IProvider 接口供上层模块调用" + ], + "interfaces": [ + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义通用搜索提供者的接口规范" + }, + { + "name": "Provider::new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "用于内容理解的 LLM 分区配置" + } + ], + "return_type": "anyhow::Result", + "description": "创建一个新的 Bing 搜索提供者实例" + }, + { + "name": "Provider::prepare_target_sources", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "&str", + "is_optional": false, + "description": "原始的 Bing 搜索结果 HTML 文本" + } + ], + "return_type": "anyhow::Result>", + "description": "从 HTML 中提取初步的文章元数据(标题、链接、摘要)" + }, + { + "name": "Provider::convert", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "String", + "is_optional": false, + "description": "Bing 搜索结果页面的 HTML 内容" + } + ], + "return_type": "anyhow::Result>", + "description": "将搜索结果转换为包含完整内容的文章对象列表" + }, + { + "name": "IProvider::search_by_words", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "待搜索的关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri 应用句柄,用于在应用环境中执行网络请求" + } + ], + "return_type": "anyhow::Result>", + "description": "执行关键词搜索并返回结构化文章列表" + }, + { + "name": "Provider::client", + "interface_type": "field", + "visibility": "private", + "parameters": [], + "return_type": "reqwest::Client", + "description": "HTTP 客户端实例,用于发送网络请求" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "html_parser", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "framework", + "version": null + }, + { + "name": "urlencoding", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "utility", + "version": null + }, + { + "name": "types::Article", + "path": "types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + }, + { + "name": "crate::connector::ClientOption", + "path": "crate::connector", + "is_external": false, + "line_number": 9, + "dependency_type": "config", + "version": null + }, + { + "name": "crate::search::selector_extensions::ElementSelector", + "path": "crate::search::selector_extensions", + "is_external": false, + "line_number": 10, + "dependency_type": "extension", + "version": null + }, + { + "name": "crate::search::types::IProvider", + "path": "crate::search::types", + "is_external": false, + "line_number": 11, + "dependency_type": "interface", + "version": null + }, + { + "name": "crate::search::utils::trim_head_read_days_ago", + "path": "crate::search::utils", + "is_external": false, + "line_number": 12, + "dependency_type": "utility", + "version": null + }, + { + "name": "crate::search::utils::trim_html_with_script_and_style", + "path": "crate::search::utils", + "is_external": false, + "line_number": 12, + "dependency_type": "utility", + "version": null + }, + { + "name": "crate::simulator::scrap_text_by_url", + "path": "crate::simulator", + "is_external": false, + "line_number": 13, + "dependency_type": "service", + "version": null + }, + { + "name": "crate::article_reader", + "path": "crate::", + "is_external": false, + "line_number": 14, + "dependency_type": "service", + "version": null + }, + { + "name": "crate::connector", + "path": "crate::", + "is_external": false, + "line_number": 15, + "dependency_type": "service", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 7.0, + "lines_of_code": 134, + "number_of_functions": 4, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 12.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024357, + "prompt_hash": "6ccf5fd00ecfadf659131e813593fba4", + "token_usage": { + "input_tokens": 1638, + "output_tokens": 1684, + "total_tokens": 3322 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/70c09ce4a2a65332561a35b3ab6409ab.json b/.litho/cache/ai_code_insight/70c09ce4a2a65332561a35b3ab6409ab.json new file mode 100644 index 0000000..f3af87e --- /dev/null +++ b/.litho/cache/ai_code_insight/70c09ce4a2a65332561a35b3ab6409ab.json @@ -0,0 +1,86 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/intelligent/src/article_processor/types.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "定义文章处理器的核心trait IArticleProcessor,用于构建责任链模式下的异步文章处理流程。", + "functions": [], + "interfaces": [ + "IArticleProcessor" + ] + }, + "detailed_description": "该组件定义了 `IArticleProcessor` trait,作为所有文章处理器的统一接口。通过此trait可以实现责任链模式,使得多个处理器能够按顺序对文章进行异步处理。`process` 方法接收一个不可变引用的 Article 和 LLMInstructOption 参数,并返回一个 Future,表示异步处理结果。该设计保证了输入数据不被修改,符合函数式处理原则,便于组合和测试。", + "responsibilities": [ + "定义文章处理的标准接口", + "支持异步处理流程", + "确保输入文章不可变性以保障数据安全", + "为责任链模式提供基础trait支撑" + ], + "interfaces": [ + { + "name": "IArticleProcessor", + "interface_type": "trait", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "文章处理器trait,所有文章处理器都应该impl这个trait以形成责任链调度。" + }, + { + "name": "process", + "interface_type": "method", + "visibility": "pub", + "parameters": [ + { + "name": "self", + "param_type": "&self", + "is_optional": false, + "description": "trait实例的不可变引用" + }, + { + "name": "input", + "param_type": "&Article", + "is_optional": false, + "description": "待处理的文章内容,不可变引用" + }, + { + "name": "opt", + "param_type": "LLMInstructOption", + "is_optional": false, + "description": "大模型指令选项配置" + } + ], + "return_type": "impl std::future::Future>", + "description": "处理文章,输入为[Article][types::Article],输出为`Article`的[future][std::future::Future]。函数本身不会修改输入的`Article`,且参数本身为不可变引用,在流水线中作为先前的副本。" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 12, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805881, + "prompt_hash": "70c09ce4a2a65332561a35b3ab6409ab", + "token_usage": { + "input_tokens": 608, + "output_tokens": 771, + "total_tokens": 1379 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/73344f222c4160af99c64c8e6f9ab7bd.json b/.litho/cache/ai_code_insight/73344f222c4160af99c64c8e6f9ab7bd.json new file mode 100644 index 0000000..8f21e29 --- /dev/null +++ b/.litho/cache/ai_code_insight/73344f222c4160af99c64c8e6f9ab7bd.json @@ -0,0 +1,55 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/scrap/src/lib.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "scrap模块的公共接口聚合文件,导出多个子模块以供外部使用。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是`scrap`功能模块的根模块,主要职责是组织和导出子模块。它本身不包含具体实现逻辑,而是通过`pub mod`关键字将`rss`、`search`、`simulator`、`types`等子模块公开给外部调用者。这些子模块分别负责RSS处理、网页内容搜索与解析、模拟行为以及共享类型定义。其设计符合Rust的模块化封装原则,起到了API门面(Facade)的作用,为上层模块提供统一的导入入口。", + "responsibilities": [ + "聚合并导出scrap功能相关的子模块", + "提供公共API接口以支持外部调用", + "维护模块间的逻辑边界与可见性控制" + ], + "interfaces": [], + "dependencies": [ + { + "name": "article_reader", + "path": "./crates/scrap/src/article_reader.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "connector", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805905, + "prompt_hash": "73344f222c4160af99c64c8e6f9ab7bd", + "token_usage": { + "input_tokens": 1773, + "output_tokens": 488, + "total_tokens": 2261 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/733b0de1b59a3de709f1ecbeebe6d161.json b/.litho/cache/ai_code_insight/733b0de1b59a3de709f1ecbeebe6d161.json new file mode 100644 index 0000000..4a7c210 --- /dev/null +++ b/.litho/cache/ai_code_insight/733b0de1b59a3de709f1ecbeebe6d161.json @@ -0,0 +1,88 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/intelligent/src/article_processor/mod.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust模块的根定义文件,用于组织和导出文章处理功能的相关子模块。它本身不包含具体实现逻辑,而是通过`pub mod`声明将多个功能模块(如LLM处理、类型定义、净化、优化、融合和助手功能)聚合为一个统一的命名空间,便于外部调用者以树状结构引用这些组件。", + "responsibilities": [ + "作为文章处理器的功能模块聚合点", + "提供统一的模块访问入口", + "维护子模块之间的组织结构关系" + ], + "interfaces": [], + "dependencies": [ + { + "name": "llm_processor", + "path": "crates/intelligent/src/article_processor/llm_processor.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "types", + "path": "crates/intelligent/src/article_processor/types.rs", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "purge", + "path": "crates/intelligent/src/article_processor/purge.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "optimizer", + "path": "crates/intelligent/src/article_processor/optimizer.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "melt", + "path": "crates/intelligent/src/article_processor/melt.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "assistant", + "path": "crates/intelligent/src/article_processor/assistant.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 6.0, + "cohesion_score": 0.8 + } + }, + "timestamp": 1759024610, + "prompt_hash": "733b0de1b59a3de709f1ecbeebe6d161", + "token_usage": { + "input_tokens": 449, + "output_tokens": 588, + "total_tokens": 1037 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/73d050d67c343cf40f2a74e819f39945.json b/.litho/cache/ai_code_insight/73d050d67c343cf40f2a74e819f39945.json new file mode 100644 index 0000000..71b8d0a --- /dev/null +++ b/.litho/cache/ai_code_insight/73d050d67c343cf40f2a74e819f39945.json @@ -0,0 +1,59 @@ +{ + "data": { + "code_dossier": { + "name": "ReaderBlankIndicator.svelte", + "file_path": "app/src/routes/main/widgets/ReaderBlankIndicator.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "用于在阅读器为空时显示提示信息的UI组件,提供多语言支持。", + "functions": [], + "interfaces": [ + "ReaderBlankIndicator" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,用于在阅读器内容为空时展示引导性提示信息。组件使用svelte-i18n进行国际化文本渲染,显示四条逐步递进的提示语,帮助用户理解当前状态并指导操作。UI布局采用居中垂直排列方式,视觉上聚焦且清晰。", + "responsibilities": [ + "在阅读器无内容时展示空白状态提示", + "提供多语言支持的提示文案展示", + "保持良好的用户体验和界面美观性", + "作为独立可复用的UI原子组件" + ], + "interfaces": [ + { + "name": "ReaderBlankIndicator", + "interface_type": "component", + "visibility": "public", + "parameters": [], + "return_type": "JSX.Element", + "description": "阅读器空白指示器组件,无输入参数,返回一个包含多语言提示信息的div元素" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 12, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805816, + "prompt_hash": "73d050d67c343cf40f2a74e819f39945", + "token_usage": { + "input_tokens": 521, + "output_tokens": 510, + "total_tokens": 1031 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/746257dfdfa6c6c10739c54c30e23a9f.json b/.litho/cache/ai_code_insight/746257dfdfa6c6c10739c54c30e23a9f.json new file mode 100644 index 0000000..37910c5 --- /dev/null +++ b/.litho/cache/ai_code_insight/746257dfdfa6c6c10739c54c30e23a9f.json @@ -0,0 +1,91 @@ +{ + "data": { + "code_dossier": { + "name": "Markdown.svelte", + "file_path": "app/src/lib/widgets/Markdown.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "一个用于渲染 Markdown 内容的 Svelte 组件,支持自定义样式和图像渲染器。", + "functions": [], + "interfaces": [ + "MarkdownProps" + ] + }, + "detailed_description": "该组件封装了 '@humanspeak/svelte-markdown' 库,接收一个包含 Markdown 源文本的 `value` 属性,并通过自定义 `renderers` 配置(如使用 `MarkdownImg` 处理图片)来增强渲染能力。它还通过全局 CSS 样式统一了标题、段落、列表、表格和代码块等元素的视觉呈现,确保与应用整体设计语言一致。", + "responsibilities": [ + "解析并渲染传入的 Markdown 字符串", + "提供可扩展的 HTML 元素渲染机制(通过 renderers)", + "统一 Markdown 内容的视觉样式以匹配产品设计规范", + "处理图片等内联元素的自定义渲染逻辑" + ], + "interfaces": [ + { + "name": "MarkdownProps", + "interface_type": "type", + "visibility": "private", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": "要渲染的 Markdown 源文本" + } + ], + "return_type": null, + "description": "定义传递给 Markdown 组件的属性结构" + } + ], + "dependencies": [ + { + "name": "@humanspeak/svelte-markdown", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "component", + "version": null + }, + { + "name": "./types", + "path": "app/src/lib/widgets/types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "svelte", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "framework", + "version": null + }, + { + "name": "./MarkdownImg.svelte", + "path": "app/src/lib/widgets/MarkdownImg.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "component", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 136, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.029411764705882353, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024486, + "prompt_hash": "746257dfdfa6c6c10739c54c30e23a9f", + "token_usage": { + "input_tokens": 1314, + "output_tokens": 637, + "total_tokens": 1951 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/746d48b27f27baf6c69b7a6718eb1a73.json b/.litho/cache/ai_code_insight/746d48b27f27baf6c69b7a6718eb1a73.json new file mode 100644 index 0000000..d1fd816 --- /dev/null +++ b/.litho/cache/ai_code_insight/746d48b27f27baf6c69b7a6718eb1a73.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "args.rs", + "file_path": "app/src-tauri/src/daemon/args.rs", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "定义守护进程的命令行参数常量,用于配置定时任务调度行为", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件定义了一个公共常量 DAEMON_FEEDS_SCHEDULE_UPDATE,表示用于触发守护进程中 feeds 定时更新任务的命令行参数。该常量作为配置项被其他模块引用,用于解析启动参数并决定是否启用定时更新功能。尽管当前仅包含一个常量,但其在系统启动流程中起到关键的配置作用。", + "responsibilities": [ + "定义守护进程相关的命令行参数常量", + "提供跨模块共享的配置标识符", + "支持守护进程功能的条件性启用控制", + "确保命令行接口的一致性和可维护性" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024671, + "prompt_hash": "746d48b27f27baf6c69b7a6718eb1a73", + "token_usage": { + "input_tokens": 423, + "output_tokens": 411, + "total_tokens": 834 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/74bab31315a8960d4ce77b43dd344178.json b/.litho/cache/ai_code_insight/74bab31315a8960d4ce77b43dd344178.json new file mode 100644 index 0000000..6a6b33b --- /dev/null +++ b/.litho/cache/ai_code_insight/74bab31315a8960d4ce77b43dd344178.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "build.rs", + "file_path": "app/src-tauri/build.rs", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Tauri应用的构建脚本,用于在编译时生成必要的绑定和配置。", + "functions": [ + "main" + ], + "interfaces": [] + }, + "detailed_description": "该组件是Rust项目中Tauri框架的构建脚本(build.rs),其主要作用是在编译期间执行tauri_build::build()函数,以生成前端与后端交互所需的绑定代码。它确保了Tauri命令、事件系统以及类型安全接口能够正确集成到最终的二进制文件中。尽管代码简洁,但它是连接Rust后端与前端的关键环节之一。", + "responsibilities": [ + "在编译期触发Tauri绑定代码生成", + "确保前后端类型安全通信的基础设施准备", + "参与构建流程以支持Tauri特定功能(如命令注册、权限检查等)" + ], + "interfaces": [], + "dependencies": [ + { + "name": "tauri_build", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "build-dependency", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 3, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024658, + "prompt_hash": "74bab31315a8960d4ce77b43dd344178", + "token_usage": { + "input_tokens": 412, + "output_tokens": 436, + "total_tokens": 848 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7769ebcdc6a484b55221c6cca454b36e.json b/.litho/cache/ai_code_insight/7769ebcdc6a484b55221c6cca454b36e.json new file mode 100644 index 0000000..c9b6863 --- /dev/null +++ b/.litho/cache/ai_code_insight/7769ebcdc6a484b55221c6cca454b36e.json @@ -0,0 +1,58 @@ +{ + "data": { + "code_dossier": { + "name": "state.rs", + "file_path": "crates/tauri-plugin-feed-api/src/state.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [ + "HybridRuntimeState" + ] + }, + "detailed_description": "该组件定义了一个名为HybridRuntimeState的结构体,用于在Tauri插件中封装后端功能API的实现。其主要作用是作为运行时状态容器,持有FeaturesAPIImpl实例,以便在应用生命周期内共享和访问核心业务逻辑。该结构体设计简洁,遵循Rust的模块化架构原则,为插件系统提供类型安全的状态管理。", + "responsibilities": [ + "封装后端功能API实现", + "作为Tauri插件的运行时状态容器", + "提供类型安全的状态共享机制" + ], + "interfaces": [ + { + "name": "HybridRuntimeState", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "用于在Tauri插件中存储和共享FeaturesAPIImpl实例的公共结构体" + } + ], + "dependencies": [ + { + "name": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "struct", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 5, + "number_of_functions": 0, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.2, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805930, + "prompt_hash": "7769ebcdc6a484b55221c6cca454b36e", + "token_usage": { + "input_tokens": 439, + "output_tokens": 443, + "total_tokens": 882 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/78520a548d6cdab7a2844f81cae51e22.json b/.litho/cache/ai_code_insight/78520a548d6cdab7a2844f81cae51e22.json new file mode 100644 index 0000000..6087280 --- /dev/null +++ b/.litho/cache/ai_code_insight/78520a548d6cdab7a2844f81cae51e22.json @@ -0,0 +1,89 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/themes/index.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "主题管理模块,用于获取、设置和应用UI主题(亮色/暗色),支持持久化存储与DOM同步。", + "functions": [ + "getTheme", + "setTheme", + "applyTheme", + "setWebInnerOnly" + ], + "interfaces": [ + "ThemePresets" + ] + }, + "detailed_description": "该组件实现了前端应用的主题管理系统,支持亮色和暗色两种预设模式。通过localStorage持久化用户选择的主题,并利用Tauri API在桌面端同步主题设置。组件提供四个核心函数:getTheme读取当前主题,setTheme更新主题并持久化,applyTheme应用当前存储的主题到应用环境,setWebInnerOnly则负责更新DOM以反映主题变化。类型ThemePresets定义了合法的主题值。所有功能通过统一接口导出,便于外部调用。", + "responsibilities": [ + "管理应用的主题状态(亮色/暗色)", + "通过localStorage实现主题偏好持久化", + "调用Tauri API同步原生应用主题", + "更新DOM类名以应用CSS主题样式", + "提供统一的主题操作接口供系统其他部分使用" + ], + "interfaces": [ + { + "name": "ThemePresets", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": "'light' | 'dark'", + "description": "定义支持的主题类型枚举,限制主题值仅为'light'或'dark'" + }, + { + "name": "getTheme", + "interface_type": "function", + "visibility": "exported", + "parameters": [], + "return_type": "ThemePresets", + "description": "从localStorage读取用户主题偏好,若无则返回默认'light'主题" + }, + { + "name": "setTheme", + "interface_type": "function", + "visibility": "exported", + "parameters": [ + { + "name": "theme", + "param_type": "ThemePresets", + "is_optional": false, + "description": "要设置的主题模式" + } + ], + "return_type": "void", + "description": "设置主题并同步到localStorage和Tauri原生环境" + } + ], + "dependencies": [ + { + "name": "@tauri-apps/api/app", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 27, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024472, + "prompt_hash": "78520a548d6cdab7a2844f81cae51e22", + "token_usage": { + "input_tokens": 596, + "output_tokens": 763, + "total_tokens": 1359 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/786b69d3c396d1a070f35a9e9a2963fb.json b/.litho/cache/ai_code_insight/786b69d3c396d1a070f35a9e9a2963fb.json new file mode 100644 index 0000000..5f9db73 --- /dev/null +++ b/.litho/cache/ai_code_insight/786b69d3c396d1a070f35a9e9a2963fb.json @@ -0,0 +1,38 @@ +{ + "data": { + "code_dossier": { + "name": "FeedsPanel.svelte", + "file_path": "app/src/routes/main/widgets/FeedsPanel.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件为空文件,未实现任何功能。作为前端UI组件,预期应展示信息流(feeds)内容,但当前无任何模板、脚本或样式定义。", + "responsibilities": [ + "占位组件:目前仅作为未来功能的占位符", + "结构预留:为信息流面板保留路由和组件结构位置", + "待实现功能:预计用于渲染和管理动态信息流内容" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805817, + "prompt_hash": "786b69d3c396d1a070f35a9e9a2963fb", + "token_usage": { + "input_tokens": 405, + "output_tokens": 280, + "total_tokens": 685 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/790984d1bbd9e6790c6f52e9614496fd.json b/.litho/cache/ai_code_insight/790984d1bbd9e6790c6f52e9614496fd.json new file mode 100644 index 0000000..2bdba76 --- /dev/null +++ b/.litho/cache/ai_code_insight/790984d1bbd9e6790c6f52e9614496fd.json @@ -0,0 +1,123 @@ +{ + "data": { + "code_dossier": { + "name": "types.ts", + "file_path": "app/src/lib/hybrid-apis/feed/types.ts", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.8, + "description": "定义了应用核心数据结构,包括LLM配置、信息流抓取、文章模型和对话消息等类型。", + "functions": [], + "interfaces": [ + "AppConfig", + "LLMProviderType", + "FeedsPackage", + "FeedTargetDescription", + "ArticleModel", + "FeedFetcherID", + "ConversationMessage", + "ConversationInput" + ] + }, + "detailed_description": "该组件是系统中的核心类型定义文件,主要用于声明应用程序中多个模块共享的数据结构。主要包括:1) LLMProviderType 和 LLMSection 定义了支持的大型语言模型提供者及其对应的配置参数;2) AppConfig 封装了整个应用的顶层配置结构;3) Feed 相关类型(FeedFetcherID, FeedTargetDescription, FeedsPackage)用于描述信息源抓取的目标与组织方式;4) ArticleModel 表示一篇文章的完整元数据和内容状态;5) ConversationMessage 和 ConversationInput 支持多模态对话交互的消息格式。所有类型均通过 export type 导出,供其他模块按需引用。", + "responsibilities": [ + "定义并导出应用程序的通用数据模型", + "统一LLM服务提供商的配置结构", + "规范信息流抓取任务的数据格式", + "提供文章内容处理的标准化表示", + "支持多模态对话系统的消息类型定义" + ], + "interfaces": [ + { + "name": "AppConfig", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "应用的顶层配置对象,包含LLM设置、爬虫选项和守护进程策略" + }, + { + "name": "LLMProviderType", + "interface_type": "union", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "支持的语言模型提供者枚举类型" + }, + { + "name": "LLMSection", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "LLM相关配置的完整结构,包含各provider的具体字段和激活类型" + }, + { + "name": "FeedFetcherID", + "interface_type": "union", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "信息源抓取器标识符,决定使用哪种抓取机制" + }, + { + "name": "FeedTargetDescription", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "单个信息源目标的描述,包括ID、名称、抓取器和原始数据" + }, + { + "name": "FeedsPackage", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "信息源包的容器结构,包含多个feed及其组织逻辑" + }, + { + "name": "ArticleModel", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "文章实体的完整模型,涵盖展示、存储和处理所需的所有字段" + }, + { + "name": "ConversationMessage", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "对话系统中的消息单元,支持多种角色和媒体类型" + }, + { + "name": "ConversationInput", + "interface_type": "object", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "用户输入消息的简化结构,仅包含媒体类型和负载" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 89, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024451, + "prompt_hash": "790984d1bbd9e6790c6f52e9614496fd", + "token_usage": { + "input_tokens": 828, + "output_tokens": 1161, + "total_tokens": 1989 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/79722b9ff757abc80130ff5312ac93da.json b/.litho/cache/ai_code_insight/79722b9ff757abc80130ff5312ac93da.json new file mode 100644 index 0000000..a027b03 --- /dev/null +++ b/.litho/cache/ai_code_insight/79722b9ff757abc80130ff5312ac93da.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "FeedsPanel.svelte", + "file_path": "app/src/routes/main/widgets/FeedsPanel.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件源代码为空,未实现任何功能。理论上应作为信息流展示面板的UI容器,但当前无实际逻辑或结构。", + "responsibilities": [ + "占位组件:暂时作为FeedsPanel的UI占位符", + "待实现职责:信息流数据展示", + "待实现职责:用户交互响应(如刷新、筛选)" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.0 + } + }, + "timestamp": 1759024538, + "prompt_hash": "79722b9ff757abc80130ff5312ac93da", + "token_usage": { + "input_tokens": 414, + "output_tokens": 253, + "total_tokens": 667 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/79fbfbb6c3d63c5b791ce454b00d698d.json b/.litho/cache/ai_code_insight/79fbfbb6c3d63c5b791ce454b00d698d.json new file mode 100644 index 0000000..582f1b5 --- /dev/null +++ b/.litho/cache/ai_code_insight/79fbfbb6c3d63c5b791ce454b00d698d.json @@ -0,0 +1,95 @@ +{ + "data": { + "code_dossier": { + "name": "ArticlesList.svelte", + "file_path": "app/src/routes/main/widgets/ArticlesList.svelte", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "Svelte组件,用于展示文章列表,支持分组显示、过滤、加载状态管理及用户交互。", + "functions": [ + "onloadFeedContents", + "render_articles_list" + ], + "interfaces": [ + "ArticlesListProps" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,负责渲染文章列表。它接收一个包含store和回调函数的props对象,通过store获取文章数据和加载状态,并根据当前状态显示相应的UI:加载中使用Progress组件,加载失败显示重试按钮,成功时则渲染文章列表。文章按组(如日期)展示,每篇文章显示标题和摘要,未读文章有视觉标识。用户点击文章会触发onArticlePressed回调。组件还处理滚动重置和自动标记已读逻辑。底部提供加载更多或重新加载内容的功能。", + "responsibilities": [ + "管理并展示文章列表的多种加载状态(加载中、完成、错误)", + "渲染分组的文章列表,支持过滤视图", + "处理用户交互(点击文章、加载更多、重试加载)", + "在文章被选中时自动标记为已读", + "控制列表容器的滚动位置以响应数据更新" + ], + "interfaces": [ + { + "name": "ArticlesListProps", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义传递给ArticlesList组件的所有属性类型,包括store、选中文章、回调函数等。" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "Status", + "path": "../stores/loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "store", + "version": null + }, + { + "name": "ArticlesListProps", + "path": "./types", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "ArticlesGroup", + "path": "./types", + "is_external": false, + "line_number": 4, + "dependency_type": "type", + "version": null + }, + { + "name": "Progress", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 5, + "dependency_type": "ui_component", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 14.0, + "lines_of_code": 130, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758801043, + "prompt_hash": "79fbfbb6c3d63c5b791ce454b00d698d", + "token_usage": { + "input_tokens": 1501, + "output_tokens": 807, + "total_tokens": 2308 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7a7bbd0b11c0e19b574ec3469947e912.json b/.litho/cache/ai_code_insight/7a7bbd0b11c0e19b574ec3469947e912.json new file mode 100644 index 0000000..0646728 --- /dev/null +++ b/.litho/cache/ai_code_insight/7a7bbd0b11c0e19b574ec3469947e912.json @@ -0,0 +1,133 @@ +{ + "data": { + "code_dossier": { + "name": "ArticlesList.svelte", + "file_path": "app/src/routes/main/widgets/ArticlesList.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "Svelte组件,用于展示文章列表,支持分组显示、过滤、加载状态管理及用户交互。", + "functions": [ + "onloadFeedContents", + "render_articles_list" + ], + "interfaces": [ + "ArticlesListProps" + ] + }, + "detailed_description": "该组件是一个前端UI组件,负责渲染文章列表。它接收来自父组件的props,包括store、选中文章、回调函数等,并根据加载状态(初始化加载、连续加载、错误)动态展示不同的UI元素。组件使用Svelte的$effect运行副作用逻辑,如滚动重置和自动标记已读。通过snippet实现可复用的列表渲染逻辑,支持按分组(ArticlesGroup)展示文章,并提供加载更多、重试等功能按钮。样式方面,定义了全局动画以增强加载指示器的视觉效果。", + "responsibilities": [ + "管理并渲染文章列表的UI展示", + "处理不同加载状态下的视图切换(加载中、完成、错误)", + "响应用户交互(点击文章、加载更多、重试)", + "自动将选中的未读文章标记为已读", + "在数据更新时重置滚动位置" + ], + "interfaces": [ + { + "name": "ArticlesListProps", + "interface_type": "type", + "visibility": "export", + "parameters": [ + { + "name": "store", + "param_type": "any", + "is_optional": false, + "description": "包含状态和方法的数据存储对象" + }, + { + "name": "selectedArticle", + "param_type": "any", + "is_optional": true, + "description": "当前选中的文章项" + }, + { + "name": "onArticlePressed", + "param_type": "() => void", + "is_optional": false, + "description": "文章项被点击时的回调函数" + }, + { + "name": "isFilterActived", + "param_type": "boolean", + "is_optional": false, + "description": "是否启用了过滤功能" + }, + { + "name": "markAsRead", + "param_type": "(id: string) => Promise", + "is_optional": false, + "description": "将指定ID的文章标记为已读的方法" + }, + { + "name": "isFeedSpecified", + "param_type": "boolean", + "is_optional": false, + "description": "是否指定了具体的feed源" + } + ], + "return_type": null, + "description": "组件接收的属性类型定义" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "Status", + "path": "../stores/loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "ArticlesListProps", + "path": "./types", + "is_external": false, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "ArticlesGroup", + "path": "./types", + "is_external": false, + "line_number": 4, + "dependency_type": "import", + "version": null + }, + { + "name": "Progress", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 5, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 14.0, + "lines_of_code": 130, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 5.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024194, + "prompt_hash": "7a7bbd0b11c0e19b574ec3469947e912", + "token_usage": { + "input_tokens": 1509, + "output_tokens": 984, + "total_tokens": 2493 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7a8eeb4ad5e00605874269d4428161e8.json b/.litho/cache/ai_code_insight/7a8eeb4ad5e00605874269d4428161e8.json new file mode 100644 index 0000000..ff76be7 --- /dev/null +++ b/.litho/cache/ai_code_insight/7a8eeb4ad5e00605874269d4428161e8.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "monitor.rs", + "file_path": "app/src-tauri/src/monitor.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "监控组件初始化,集成Sentry进行错误追踪和性能监控", + "functions": [ + "start" + ], + "interfaces": [ + "start" + ] + }, + "detailed_description": "该组件负责初始化应用的监控能力,通过Sentry SDK建立错误报告和性能监控机制。其核心功能是在应用启动时调用sentry::init,传入指定的DSN和配置选项(包括自动识别版本号),从而启用全局异常捕获和事件上报。此函数通常由主程序在启动阶段调用一次。", + "responsibilities": [ + "初始化Sentry监控服务", + "配置错误追踪的发布版本标识", + "建立全局异常捕获机制", + "提供应用健康状态监控入口" + ], + "interfaces": [ + { + "name": "start", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "启动监控服务,初始化Sentry客户端" + } + ], + "dependencies": [ + { + "name": "sentry", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 9, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805955, + "prompt_hash": "7a8eeb4ad5e00605874269d4428161e8", + "token_usage": { + "input_tokens": 480, + "output_tokens": 444, + "total_tokens": 924 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7b5e8c15cf4078c8e4902404f0930d2f.json b/.litho/cache/ai_code_insight/7b5e8c15cf4078c8e4902404f0930d2f.json new file mode 100644 index 0000000..388ab40 --- /dev/null +++ b/.litho/cache/ai_code_insight/7b5e8c15cf4078c8e4902404f0930d2f.json @@ -0,0 +1,75 @@ +{ + "data": { + "code_dossier": { + "name": "hooks.client.ts", + "file_path": "app/src/hooks.client.ts", + "code_purpose": "middleware", + "importance_score": 0.6, + "description": "Sentry错误监控和会话重放初始化配置,用于客户端异常捕获与上报", + "functions": [ + "handleError" + ], + "interfaces": [] + }, + "detailed_description": "该组件为SvelteKit应用的客户端错误处理钩子,主要职责是初始化Sentry SDK并配置错误追踪、性能监控和会话重放功能。通过调用Sentry.init()方法,设置DSN、采样率等核心参数,并集成replayIntegration以实现用户行为回放。最终导出由handleErrorWithSentry包装的全局错误处理器,用于捕获和上报运行时异常。", + "responsibilities": [ + "初始化Sentry SDK并配置监控参数", + "设置错误和会话重放的采样策略", + "集成Sentry的replay功能以支持用户行为追踪", + "提供全局错误处理函数供框架使用", + "管理客户端端到端的异常监控链路" + ], + "interfaces": [ + { + "name": "handleError", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "input", + "param_type": "{ error: unknown; event: import('@sentry/sveltekit').Event; hint: import('@sentry/sveltekit').EventHint; }", + "is_optional": false, + "description": "SvelteKit错误处理上下文对象" + } + ], + "return_type": "void", + "description": "Sentry封装的错误处理函数,负责将异常上报至Sentry服务" + } + ], + "dependencies": [ + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 21, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.095, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805982, + "prompt_hash": "7b5e8c15cf4078c8e4902404f0930d2f", + "token_usage": { + "input_tokens": 601, + "output_tokens": 615, + "total_tokens": 1216 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7c3967eaf9f17960fef351271795f6f2.json b/.litho/cache/ai_code_insight/7c3967eaf9f17960fef351271795f6f2.json new file mode 100644 index 0000000..94780f2 --- /dev/null +++ b/.litho/cache/ai_code_insight/7c3967eaf9f17960fef351271795f6f2.json @@ -0,0 +1,120 @@ +{ + "data": { + "code_dossier": { + "name": "init_app_config.rs", + "file_path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "code_purpose": "entry", + "importance_score": 0.9, + "description": "负责应用配置的初始化、加载和持久化,支持 TOML 格式的读写。", + "functions": [ + "call", + "sync_to", + "default_app_config" + ], + "interfaces": [ + "call", + "sync_to" + ] + }, + "detailed_description": "该组件是应用程序启动流程中的关键部分,主要职责为初始化并管理应用配置(AppConfig)。它通过异步方式尝试从预定义路径加载 `app_config.toml` 配置文件:若文件存在,则解析其内容并反序列化为 AppConfig 结构;若文件不存在或读取失败,则生成默认配置并通过 sync_to 函数将其写入磁盘以创建初始配置。配置的序列化与反序列化使用 toml 库完成,确保格式一致性。整个过程封装在 InitTask 中,便于集成到系统的初始化任务调度体系中。", + "responsibilities": [ + "初始化应用配置对象", + "从文件系统加载或创建默认配置", + "将配置持久化保存至 TOML 文件", + "提供默认配置的构建逻辑", + "集成到异步初始化任务框架" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result>", + "description": "执行配置初始化任务,返回一个包含 AppConfig 的初始化任务对象" + }, + { + "name": "sync_to", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "app_config", + "param_type": "&AppConfig", + "is_optional": false, + "description": "待持久化的应用配置引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "将给定的应用配置同步写入到 app_config.toml 文件中" + }, + { + "name": "default_app_config", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "AppConfig", + "description": "生成并返回一个具有合理默认值的应用配置实例" + } + ], + "dependencies": [ + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "async_runtime", + "version": null + }, + { + "name": "recorder::path::get_appdata_file", + "path": "recorder::path", + "is_external": false, + "line_number": 6, + "dependency_type": "utility", + "version": null + }, + { + "name": "types::AppConfig", + "path": "types", + "is_external": false, + "line_number": 8, + "dependency_type": "model", + "version": null + }, + { + "name": "super::task::InitTask", + "path": "crates/feed_api_rs/src/startup/task", + "is_external": false, + "line_number": 10, + "dependency_type": "framework", + "version": null + }, + { + "name": "toml", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "serialization", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 76, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801083, + "prompt_hash": "7c3967eaf9f17960fef351271795f6f2", + "token_usage": { + "input_tokens": 1035, + "output_tokens": 920, + "total_tokens": 1955 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7c57c3051847bcdeafe165709195313e.json b/.litho/cache/ai_code_insight/7c57c3051847bcdeafe165709195313e.json new file mode 100644 index 0000000..20ccdbf --- /dev/null +++ b/.litho/cache/ai_code_insight/7c57c3051847bcdeafe165709195313e.json @@ -0,0 +1,146 @@ +{ + "data": { + "code_dossier": { + "name": "ArticleReader.svelte", + "file_path": "app/src/routes/main/widgets/ArticleReader.svelte", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "文章阅读器组件,支持多种阅读模式和交互功能", + "functions": [ + "copyLink", + "openOriginalPage", + "refreshByEnhancedScraper", + "switchStar" + ], + "interfaces": [ + "ArticleReaderProps", + "ArticleReadMode" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,用于展示和交互文章内容。它提供三种阅读模式:优化内容、熔炼内容和原始页面。组件通过Tab切换不同视图,并集成了收藏、复制链接、打开原文、重新抓取等交互功能。数据通过Tauri API从后端获取,并响应式更新。使用$effect自动加载文章数据,支持状态管理与用户反馈(toaster)。", + "responsibilities": [ + "管理文章阅读的多模式切换(优化/熔炼/原始)", + "处理文章数据的加载与刷新逻辑", + "提供用户交互功能:收藏、复制链接、打开原文、重新抓取", + "集成第三方组件进行内容渲染(ArticleRenderWidget, EmbedWebView)", + "实现UI反馈机制(toaster提示)" + ], + "interfaces": [ + { + "name": "ArticleReaderProps", + "interface_type": "type", + "visibility": "export", + "parameters": [], + "return_type": null, + "description": "组件的输入属性类型,包含articleId和store" + }, + { + "name": "ArticleReadMode", + "interface_type": "type", + "visibility": "export", + "parameters": [], + "return_type": null, + "description": "枚举阅读模式:optimized, melted, original" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 3, + "dependency_type": "ui", + "version": null + }, + { + "name": "lucide-svelte", + "path": "lucide-svelte", + "is_external": true, + "line_number": 4, + "dependency_type": "icon", + "version": null + }, + { + "name": "ArticleRenderWidget", + "path": "$lib/widgets/ArticleRenderWidget.svelte", + "is_external": false, + "line_number": 10, + "dependency_type": "component", + "version": null + }, + { + "name": "EmbedWebView", + "path": "$lib/widgets/EmbedWebView.svelte", + "is_external": false, + "line_number": 11, + "dependency_type": "component", + "version": null + }, + { + "name": "ArticleReaderProps", + "path": "./types", + "is_external": false, + "line_number": 12, + "dependency_type": "type", + "version": null + }, + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 13, + "dependency_type": "model", + "version": null + }, + { + "name": "@tauri-apps/plugin-clipboard-manager", + "path": "@tauri-apps/plugin-clipboard-manager", + "is_external": true, + "line_number": 14, + "dependency_type": "plugin", + "version": null + }, + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 16, + "dependency_type": "api", + "version": null + }, + { + "name": "disableContextMenu", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 17, + "dependency_type": "util", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 9.0, + "lines_of_code": 156, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.64, + "cohesion_score": 0.82 + } + }, + "timestamp": 1758801061, + "prompt_hash": "7c57c3051847bcdeafe165709195313e", + "token_usage": { + "input_tokens": 1606, + "output_tokens": 935, + "total_tokens": 2541 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7df3a7c345f93a2a645ccb03f339e3b2.json b/.litho/cache/ai_code_insight/7df3a7c345f93a2a645ccb03f339e3b2.json new file mode 100644 index 0000000..63ae949 --- /dev/null +++ b/.litho/cache/ai_code_insight/7df3a7c345f93a2a645ccb03f339e3b2.json @@ -0,0 +1,161 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/scrap/src/rss/mod.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "RSS 内容抓取器实现,用于从 RSS 源提取文章信息并调用内容读取服务获取正文。", + "functions": [ + "fetch" + ], + "interfaces": [ + "IFetcher" + ] + }, + "detailed_description": "该组件实现了 IFetcher trait,专门用于处理 RSS 源的抓取逻辑。它接收一个 FeedTargetDescription,从中提取 URL,使用 reqwest 发起 HTTP 请求获取 RSS XML 数据,并通过 rss crate 解析 Channel 结构。随后遍历其中的 item 条目,提取标题、链接和摘要信息,并调用 article_reader 模块异步读取每篇文章的完整正文内容。最终将这些信息组装成 Article 对象列表返回。整个过程在失败时会进行适当的错误处理,例如缺失 URL 或解析失败。", + "responsibilities": [ + "解析 RSS feed 并提取基础文章元数据(标题、链接、摘要)", + "协调对远程文章页面的内容抓取与正文提取", + "实现 IFetcher 接口以支持统一的数据获取策略", + "处理 RSS 解析过程中的错误情况并提供有意义的错误反馈" + ], + "interfaces": [ + { + "name": "IFetcher", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义通用抓取器接口,RSSFetcher 提供其具体实现。" + }, + { + "name": "fetch", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "_app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri 应用句柄,当前未实际使用" + }, + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定用于内容处理的 LLM 配置区域" + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": "包含待抓取源数据(如 URL)的目标描述" + } + ], + "return_type": "anyhow::Result>", + "description": "执行 RSS 抓取主流程,返回文章列表或错误" + } + ], + "dependencies": [ + { + "name": "crate::types::IFetcher", + "path": "crates/scrap/src/types/mod.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "trait", + "version": null + }, + { + "name": "rss::Channel", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::AppHandle", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::Runtime", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "trait", + "version": null + }, + { + "name": "types::Article", + "path": "crates/scrap/src/types/mod.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::FeedTargetDescription", + "path": "crates/scrap/src/types/mod.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "crates/scrap/src/types/mod.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::article_reader", + "path": "crates/scrap/src/article_reader.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "reqwest", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "library", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 54, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.67, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024357, + "prompt_hash": "7df3a7c345f93a2a645ccb03f339e3b2", + "token_usage": { + "input_tokens": 2222, + "output_tokens": 1095, + "total_tokens": 3317 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7e0e8fef0131b7a0c87c87dfd1fe24a1.json b/.litho/cache/ai_code_insight/7e0e8fef0131b7a0c87c87dfd1fe24a1.json new file mode 100644 index 0000000..2eddfeb --- /dev/null +++ b/.litho/cache/ai_code_insight/7e0e8fef0131b7a0c87c87dfd1fe24a1.json @@ -0,0 +1,104 @@ +{ + "data": { + "code_dossier": { + "name": "init_user_profile.rs", + "file_path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "负责用户配置文件的初始化、读取和同步,支持 TOML 格式的持久化存储。", + "functions": [ + "call", + "sync_to", + "default_user_profile" + ], + "interfaces": [ + "call", + "sync_to" + ] + }, + "detailed_description": "该组件用于在应用启动时初始化用户配置。它尝试从指定路径加载 user_config.toml 文件,若文件不存在或读取失败,则生成默认用户配置并将其持久化到磁盘。核心功能包括异步读取配置、序列化/反序列化 TOML 数据以及写入最新配置。`call` 函数返回一个初始化任务,集成至系统启动流程;`sync_to` 提供将内存中的 UserConfig 对象写回磁盘的能力;`default_user_profile` 定义了新用户的默认订阅设置。", + "responsibilities": [ + "管理用户配置的生命周期(加载、创建默认、持久化)", + "处理用户配置的序列化与反序列化(TOML 格式)", + "提供默认用户画像以支持首次启动体验", + "与文件系统交互实现配置的持久化存储", + "集成到应用启动流程中作为初始化任务" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result>", + "description": "启动用户配置初始化任务,返回可执行的异步任务" + }, + { + "name": "sync_to", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "user_config", + "param_type": "&UserConfig", + "is_optional": false, + "description": "待持久化的用户配置引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "将给定的用户配置同步保存至磁盘文件" + }, + { + "name": "default_user_profile", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "UserConfig", + "description": "生成并返回默认的用户配置实例" + } + ], + "dependencies": [ + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "async_runtime", + "version": null + }, + { + "name": "recorder::path::get_appdata_file", + "path": "recorder::path", + "is_external": false, + "line_number": 6, + "dependency_type": "utility", + "version": null + }, + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 56, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758801163, + "prompt_hash": "7e0e8fef0131b7a0c87c87dfd1fe24a1", + "token_usage": { + "input_tokens": 866, + "output_tokens": 859, + "total_tokens": 1725 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7e8a973c8b2a4d26fdecf2634da67d25.json b/.litho/cache/ai_code_insight/7e8a973c8b2a4d26fdecf2634da67d25.json new file mode 100644 index 0000000..09be4d3 --- /dev/null +++ b/.litho/cache/ai_code_insight/7e8a973c8b2a4d26fdecf2634da67d25.json @@ -0,0 +1,72 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "app/src-tauri/src/daemon/mod.rs", + "code_purpose": "other", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust模块的组织文件,用于将daemon功能域下的多个子模块(args、feeds_update、launcher、locks)进行聚合和封装。它本身不包含具体实现逻辑,而是通过pub(crate)关键字将内部模块暴露给同crate的其他组件使用,形成一个内聚的守护进程功能模块集合。", + "responsibilities": [ + "组织和管理daemon领域的子模块", + "控制子模块的可见性范围(仅限当前crate)", + "提供daemon功能的模块化结构基础", + "维护守护进程相关功能的命名空间一致性" + ], + "interfaces": [], + "dependencies": [ + { + "name": "args", + "path": "app/src-tauri/src/daemon/args.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "feeds_update", + "path": "app/src-tauri/src/daemon/feeds_update.rs", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "launcher", + "path": "app/src-tauri/src/daemon/launcher.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "locks", + "path": "app/src-tauri/src/daemon/locks.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 4, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.8, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805971, + "prompt_hash": "7e8a973c8b2a4d26fdecf2634da67d25", + "token_usage": { + "input_tokens": 423, + "output_tokens": 488, + "total_tokens": 911 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7ea084b580daec28f2d54c2d4d6b8221.json b/.litho/cache/ai_code_insight/7ea084b580daec28f2d54c2d4d6b8221.json new file mode 100644 index 0000000..bbdc266 --- /dev/null +++ b/.litho/cache/ai_code_insight/7ea084b580daec28f2d54c2d4d6b8221.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/articles/search/index.svelte.ts", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "文章搜索状态管理Store,用于维护过滤文本和激活状态", + "functions": [ + "create" + ], + "interfaces": [ + "StoreType" + ] + }, + "detailed_description": "该组件定义了一个Svelte状态存储器(Store),用于管理文章列表的搜索与过滤功能。其核心是通过$state创建响应式filterText字段,并利用$derived派生出isFilterActived布尔值,表示当前是否处于激活过滤状态。提供getter/setter接口以封装内部状态,确保外部只能通过受控方式访问或修改状态。", + "responsibilities": [ + "管理文章搜索的过滤关键词状态", + "提供响应式的过滤文本存储和更新机制", + "计算并暴露过滤功能是否已激活的状态标志", + "封装内部状态逻辑,对外提供清晰的只读/可写属性接口", + "作为可复用的状态模块供UI组件订阅和绑定" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义文章搜索Store的结构类型,包含filterText和isFilterActived两个属性" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "StoreType", + "description": "工厂函数,用于创建并返回一个新的文章搜索状态Store实例" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 24, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805842, + "prompt_hash": "7ea084b580daec28f2d54c2d4d6b8221", + "token_usage": { + "input_tokens": 510, + "output_tokens": 592, + "total_tokens": 1102 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/7ef25265a87dc8901007c0def6dd9376.json b/.litho/cache/ai_code_insight/7ef25265a87dc8901007c0def6dd9376.json new file mode 100644 index 0000000..a18964b --- /dev/null +++ b/.litho/cache/ai_code_insight/7ef25265a87dc8901007c0def6dd9376.json @@ -0,0 +1,42 @@ +{ + "data": { + "code_dossier": { + "name": "date.ts", + "file_path": "app/src/lib/utils/date.ts", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供日期格式化工具函数,将当前日期转换为YYYY-MM-DD字符串格式", + "functions": [ + "currentDateText" + ], + "interfaces": [] + }, + "detailed_description": "该组件包含一个名为currentDateText的函数,用于获取当前系统日期并将其格式化为'YYYY-MM-DD'的标准字符串格式。函数通过JavaScript内置Date对象获取年、月、日,并对月份和日期进行零填充处理以确保两位数显示,最后返回组合后的日期字符串。该功能常用于日志记录、文件命名、数据标识等需要标准化日期表示的场景。", + "responsibilities": [ + "获取当前系统日期时间", + "将日期格式化为标准的YYYY-MM-DD字符串格式", + "确保月份和日期的两位数显示(零填充)", + "提供可复用的日期格式化工具函数" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024688, + "prompt_hash": "7ef25265a87dc8901007c0def6dd9376", + "token_usage": { + "input_tokens": 495, + "output_tokens": 434, + "total_tokens": 929 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/80b695228e7ab95081cf5571a6dc2f9a.json b/.litho/cache/ai_code_insight/80b695228e7ab95081cf5571a6dc2f9a.json new file mode 100644 index 0000000..2cfb904 --- /dev/null +++ b/.litho/cache/ai_code_insight/80b695228e7ab95081cf5571a6dc2f9a.json @@ -0,0 +1,159 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "app/src-tauri/src/lib.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "Tauri 应用的主入口模块,负责初始化应用插件、系统托盘、守护进程调度及窗口管理。", + "functions": [ + "run" + ], + "interfaces": [ + "run" + ] + }, + "detailed_description": "该组件是 Tauri 桌面应用的核心启动器,通过 `run` 函数构建并运行应用实例。它集成多个 Tauri 插件(如自动启动、剪贴板、Shell 等),设置单实例机制防止重复启动,并监听窗口关闭事件以在 macOS 上隐藏而非退出主窗口。支持桌面端系统托盘创建,提供‘显示主窗口’、‘网络信息’、‘关于’和‘退出’菜单项。通过 `env::is_daemon` 判断是否为守护进程模式,在非守护模式下显示主窗口,并启动定时更新订阅源的任务(`launch_feeds_schedule_update`)。整体作为智能 Agent 协调多个子模块完成应用生命周期管理。", + "responsibilities": [ + "初始化并运行 Tauri 应用实例", + "管理应用插件注册与配置", + "处理主窗口的显示/隐藏逻辑(尤其 macOS 平台)", + "创建系统托盘并响应用户交互", + "启动后台任务调度(如订阅源更新)" + ], + "interfaces": [ + { + "name": "run", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "应用的主入口函数,构建 Tauri 应用并启动事件循环。" + } + ], + "dependencies": [ + { + "name": "constrant", + "path": "./app/src-tauri/src/constrant.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "daemon", + "path": "./app/src-tauri/src/daemon", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "env", + "path": "./app/src-tauri/src/env.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "monitor", + "path": "./app/src-tauri/src/monitor.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "tray", + "path": "./app/src-tauri/src/tray.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 7, + "dependency_type": "crate", + "version": null + }, + { + "name": "tauri_plugin_single_instance", + "path": null, + "is_external": true, + "line_number": 15, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_dialog", + "path": null, + "is_external": true, + "line_number": 18, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_os", + "path": null, + "is_external": true, + "line_number": 19, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_shell", + "path": null, + "is_external": true, + "line_number": 20, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_feed_api", + "path": null, + "is_external": true, + "line_number": 21, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_clipboard_manager", + "path": null, + "is_external": true, + "line_number": 22, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_autostart", + "path": null, + "is_external": true, + "line_number": 23, + "dependency_type": "plugin", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 68, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 13.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024422, + "prompt_hash": "80b695228e7ab95081cf5571a6dc2f9a", + "token_usage": { + "input_tokens": 2422, + "output_tokens": 1027, + "total_tokens": 3449 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/80f61996e2d06022b495b4ba4b64b062.json b/.litho/cache/ai_code_insight/80f61996e2d06022b495b4ba4b64b062.json new file mode 100644 index 0000000..136fb9d --- /dev/null +++ b/.litho/cache/ai_code_insight/80f61996e2d06022b495b4ba4b64b062.json @@ -0,0 +1,106 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/ollama/src/lib.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "Ollama 程序状态与版本信息查询组件,支持跨平台检测和远程健康检查", + "functions": [ + "install", + "launch", + "request_running", + "request_version", + "query_platform", + "query_platform_by_remote", + "query_platform_by_process", + "parse_version", + "parse_is_running_from_version", + "create_shell_command" + ], + "interfaces": [ + "ProgramStatus", + "Information", + "APIVersionResponse" + ] + }, + "detailed_description": "该组件负责管理 Ollama AI 模型运行时的状态检测、安装启动及版本查询。通过本地进程调用和远程 HTTP 接口两种方式判断 Ollama 是否已安装并运行,并获取其版本信息。支持 Windows、macOS 和 Linux 跨平台路径配置,使用条件编译处理不同操作系统的 shell 命令差异。核心逻辑包括:1) 通过执行 `ollama -v` 检查本地安装状态;2) 向 API 端点发送请求验证服务是否运行;3) 解析响应内容提取版本号;4) 综合判断返回结构化信息。", + "responsibilities": [ + "检测 Ollama 在当前系统中的安装与运行状态", + "通过本地命令行和远程 API 双重机制获取程序信息", + "跨平台兼容性处理(Windows/macOS/Linux)", + "解析命令输出和 API 响应数据", + "提供统一的信息查询接口供上层模块调用" + ], + "interfaces": [ + { + "name": "ProgramStatus", + "interface_type": "enum", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "表示 Ollama 程序的三种状态:未安装、已安装但未运行、正在运行" + }, + { + "name": "Information", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "封装版本号、状态和额外信息的响应数据结构" + }, + { + "name": "APIVersionResponse", + "interface_type": "struct", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "用于反序列化远程 API 返回的版本信息" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "serialization", + "version": null + }, + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "runtime", + "version": null + }, + { + "name": "types::llm_endpoint::LLMEndPoint", + "path": "crates/types/src/llm_endpoint.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 8.0, + "lines_of_code": 140, + "number_of_functions": 10, + "number_of_classes": 3, + "depth_of_inheritance": 0, + "coupling_factor": 0.3, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024418, + "prompt_hash": "80f61996e2d06022b495b4ba4b64b062", + "token_usage": { + "input_tokens": 1470, + "output_tokens": 864, + "total_tokens": 2334 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/83682f524cb0e93138a59ce664e9aa41.json b/.litho/cache/ai_code_insight/83682f524cb0e93138a59ce664e9aa41.json new file mode 100644 index 0000000..c50c3c8 --- /dev/null +++ b/.litho/cache/ai_code_insight/83682f524cb0e93138a59ce664e9aa41.json @@ -0,0 +1,296 @@ +{ + "data": { + "code_dossier": { + "name": "impl_default.rs", + "file_path": "crates/feed_api_rs/src/features/impl_default.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现了Feed功能的核心业务逻辑,包括订阅管理、内容抓取、文章处理流水线和用户交互等功能。", + "functions": [ + "new", + "sync_user_profile", + "process_article_pipelines", + "create_futures_for_update_feeds", + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件是Feed系统的核心实现,负责处理所有与订阅内容相关的业务逻辑。它实现了FeaturesAPI接口,提供了完整的CRUD操作和高级功能。主要功能包括:管理用户订阅包和订阅源的增删改查;从不同来源(RSS/搜索引擎)抓取文章内容;通过Purge/Optimizer/Melt三个LLM处理器对文章进行清洗、优化和融合处理;将处理后的文章存储到数据库;提供多种方式读取和查询文章内容(按时间、收藏状态等);支持与文章内容进行AI对话;以及Ollama模型的管理功能。组件采用异步架构,支持并发处理多篇文章,通过Arc>实现全局状态共享。", + "responsibilities": [ + "管理用户订阅配置的持久化与同步", + "协调文章抓取、处理和存储的完整流水线", + "提供多样化的文章内容查询和过滤接口", + "集成LLM处理器对文章内容进行智能处理", + "管理Ollama等外部AI服务的连接状态" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了Feed系统所有功能的接口契约" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "std", + "version": null + }, + { + "name": "chrono", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tokio::sync::RwLock", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "intelligent::article_processor::assistant::Assistant", + "path": "crates/intelligent/src/article_processor/assistant.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::llm_processor::ArticleLLMProcessor", + "path": "crates/intelligent/src/article_processor/llm_processor.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crates/intelligent/src/article_processor/llm_processor.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::melt::Melt", + "path": "crates/intelligent/src/article_processor/melt.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::optimizer::Optimizer", + "path": "crates/intelligent/src/article_processor/optimizer.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::purge::Purge", + "path": "crates/intelligent/src/article_processor/purge.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::types::IArticleProcessor", + "path": "crates/intelligent/src/article_processor/types.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "ollama", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "recorder::article_recorder_service::ArticleRecorderService", + "path": "crates/recorder/src/article_recorder_service.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "recorder::entity::article_record::Model", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::rss::RSSFetcher", + "path": "crates/scrap/src/rss.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::utils::trim_html_with_script_and_style", + "path": "crates/scrap/src/search/utils.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::baidu", + "path": "crates/scrap/src/search/baidu.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::bing", + "path": "crates/scrap/src/search/bing.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::ScrapProviderEnums", + "path": "crates/scrap/src/search/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "types", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::startup::init_app_config::sync_to", + "path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::application_context::ApplicationContext", + "path": "crates/feed_api_rs/src/application_context.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::startup::init_user_profile", + "path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::utils::do_parallel_with_limit", + "path": "crates/feed_api_rs/src/utils.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "super::api::FeaturesAPI", + "path": "crates/feed_api_rs/src/features/api.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 25.0, + "lines_of_code": 544, + "number_of_functions": 26, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 22.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758801165, + "prompt_hash": "83682f524cb0e93138a59ce664e9aa41", + "token_usage": { + "input_tokens": 7625, + "output_tokens": 1931, + "total_tokens": 9556 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/83d05e12b628c2d7cd1d86f3007e94cb.json b/.litho/cache/ai_code_insight/83d05e12b628c2d7cd1d86f3007e94cb.json new file mode 100644 index 0000000..967bef1 --- /dev/null +++ b/.litho/cache/ai_code_insight/83d05e12b628c2d7cd1d86f3007e94cb.json @@ -0,0 +1,76 @@ +{ + "data": { + "code_dossier": { + "name": "purge.rs", + "file_path": "crates/intelligent/src/article_processor/purge.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "实现文章内容净化处理的LLM处理器,用于清除文章中的冗余或不适当内容。", + "functions": [], + "interfaces": [ + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件实现了IPresetArticleLLMProcessor trait,专门用于创建一个文章内容净化处理器。它通过加载预定义的系统提示和用户提示命令,配置LLM上下文参数(8192 token),并初始化ArticleLLMProcessor实例。其主要功能是为文章处理流程提供一个专门用于内容净化的AI处理通道,确保输出内容符合质量标准。", + "responsibilities": [ + "实现文章内容净化的LLM处理逻辑", + "配置净化任务所需的系统提示和用户指令", + "设置适当的LLM上下文长度(8192 tokens)以处理长文本", + "作为预设处理器工厂创建ArticleLLMProcessor实例", + "遵循IPresetArticleLLMProcessor接口规范" + ], + "interfaces": [ + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result", + "description": "预设文章LLM处理器接口,定义了创建处理器实例的标准方法" + } + ], + "dependencies": [ + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor}", + "path": "crate::article_processor::llm_processor", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805881, + "prompt_hash": "83d05e12b628c2d7cd1d86f3007e94cb", + "token_usage": { + "input_tokens": 593, + "output_tokens": 661, + "total_tokens": 1254 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/849d3a6b45640b65396afd58695bf847.json b/.litho/cache/ai_code_insight/849d3a6b45640b65396afd58695bf847.json new file mode 100644 index 0000000..b519a47 --- /dev/null +++ b/.litho/cache/ai_code_insight/849d3a6b45640b65396afd58695bf847.json @@ -0,0 +1,84 @@ +{ + "data": { + "code_dossier": { + "name": "connector.rs", + "file_path": "crates/scrap/src/connector.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供HTTP客户端构建工具,用于创建带有默认请求头和配置的reqwest Client实例。", + "functions": [ + "new_builder", + "new" + ], + "interfaces": [ + "ClientOption" + ] + }, + "detailed_description": "该组件封装了HTTP客户端(reqwest::Client)的初始化逻辑,通过提供统一的默认请求头(如User-Agent、Accept、Encoding等)和基础配置(超时、Cookie存储、压缩支持),简化了网络请求客户端的创建过程。它接收一个包含主机地址和可选用户代理的配置结构体ClientOption,并据此构建出预设行为的ClientBuilder或直接生成Client实例。此设计有助于在爬虫或数据抓取场景中模拟真实浏览器行为,提高请求成功率。", + "responsibilities": [ + "封装HTTP客户端的创建逻辑", + "设置标准化的请求头以模拟浏览器行为", + "管理客户端基础配置(超时、压缩、Cookie等)", + "提供灵活但安全的客户端构建接口" + ], + "interfaces": [ + { + "name": "ClientOption", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "user_agent", + "param_type": "Option", + "is_optional": true, + "description": "自定义User-Agent字符串,若未提供则使用默认值" + }, + { + "name": "host", + "param_type": "String", + "is_optional": false, + "description": "目标请求主机名,用于设置Host请求头" + } + ], + "return_type": null, + "description": "客户端配置选项,用于指导ClientBuilder的构建过程" + } + ], + "dependencies": [ + { + "name": "reqwest", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "library", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 43, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.0465, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024378, + "prompt_hash": "849d3a6b45640b65396afd58695bf847", + "token_usage": { + "input_tokens": 907, + "output_tokens": 684, + "total_tokens": 1591 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/84cd79d365ba42093e6ee9a55a8ba055.json b/.litho/cache/ai_code_insight/84cd79d365ba42093e6ee9a55a8ba055.json new file mode 100644 index 0000000..63c3f12 --- /dev/null +++ b/.litho/cache/ai_code_insight/84cd79d365ba42093e6ee9a55a8ba055.json @@ -0,0 +1,289 @@ +{ + "data": { + "code_dossier": { + "name": "impl_default.rs", + "file_path": "crates/feed_api_rs/src/features/impl_default.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现Feeds功能的核心业务逻辑,包括订阅管理、内容抓取、文章处理管道和用户交互。", + "functions": [ + "new", + "sync_user_profile", + "process_article_pipelines", + "create_futures_for_update_feeds", + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件是Feed系统的核心业务实现。它通过`FeaturesAPIImpl`结构体实现了`FeaturesAPI`接口,提供了对订阅包(FeedsPackage)和单个订阅源(Feed)的全生命周期管理(增删改查)。其核心功能在于内容更新管道:当调用`update_feed_contents`时,会根据配置选择`scrap`或`rss`作为抓取器获取原始文章列表。对于每篇新文章,会启动一个异步处理流程,依次通过Purge、Optimizer、Melt三个LLM处理器进行内容净化、优化和融合,并将最终结果存入数据库。此外,该组件还提供读取已存档内容(支持多种过滤条件如今日、周末、收藏夹)、与文章助手对话、搜索等功能,并封装了对Ollama服务的启停控制。", + "responsibilities": [ + "管理用户订阅包和订阅源的元数据配置", + "协调并执行从外部源抓取和处理文章内容的完整管道", + "提供对已存档文章的查询、标记和搜索等用户交互功能", + "作为应用配置和用户配置的中央访问点", + "集成和管理外部AI服务(Ollama)的生命周期" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了所有前端或系统其他部分需要调用的Feed相关功能的接口。" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "std", + "version": null + }, + { + "name": "chrono", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tokio::sync::RwLock", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "intelligent::article_processor::assistant::Assistant", + "path": "crates/intelligent/src/article_processor/assistant/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::llm_processor::ArticleLLMProcessor", + "path": "crates/intelligent/src/article_processor/llm_processor/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crates/intelligent/src/article_processor/llm_processor/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::melt::Melt", + "path": "crates/intelligent/src/article_processor/melt/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::optimizer::Optimizer", + "path": "crates/intelligent/src/article_processor/optimizer/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::purge::Purge", + "path": "crates/intelligent/src/article_processor/purge/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "intelligent::article_processor::types::IArticleProcessor", + "path": "crates/intelligent/src/article_processor/types.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "ollama", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "recorder::article_recorder_service::ArticleRecorderService", + "path": "crates/recorder/src/article_recorder_service/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "recorder::entity::article_record::Model", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::rss::RSSFetcher", + "path": "crates/scrap/src/rss/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::baidu", + "path": "crates/scrap/src/search/baidu.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::bing", + "path": "crates/scrap/src/search/bing.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::search::ScrapProviderEnums", + "path": "crates/scrap/src/search/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "scrap::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "types", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::startup::init_app_config::sync_to", + "path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::application_context::ApplicationContext", + "path": "crates/feed_api_rs/src/application_context.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::startup::init_user_profile", + "path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::utils::do_parallel_with_limit", + "path": "crates/feed_api_rs/src/utils/mod.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "super::api::FeaturesAPI", + "path": "crates/feed_api_rs/src/features/api.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 25.0, + "lines_of_code": 544, + "number_of_functions": 22, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.73, + "cohesion_score": 0.65 + } + }, + "timestamp": 1759024300, + "prompt_hash": "84cd79d365ba42093e6ee9a55a8ba055", + "token_usage": { + "input_tokens": 7633, + "output_tokens": 1944, + "total_tokens": 9577 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/860f2aef0ec434e6bf925a94c7a7aa79.json b/.litho/cache/ai_code_insight/860f2aef0ec434e6bf925a94c7a7aa79.json new file mode 100644 index 0000000..b11a923 --- /dev/null +++ b/.litho/cache/ai_code_insight/860f2aef0ec434e6bf925a94c7a7aa79.json @@ -0,0 +1,49 @@ +{ + "data": { + "code_dossier": { + "name": "toast.ts", + "file_path": "app/src/routes/main/stores/toast.ts", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "定义了两个全局通知toaster实例,用于在应用不同位置显示提示信息", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件使用Skeleton框架的createToaster函数创建了两个预配置的toaster实例:globalToaster位于屏幕右下角,偏移30px;spriteToaster位于屏幕左下角,偏移128px。这两个实例可在应用任何地方导入使用,实现一致性的通知展示体验。", + "responsibilities": [ + "提供全局通知服务实例", + "预配置toaster显示位置和偏移量", + "封装第三方通知库的初始化逻辑", + "确保通知样式和行为的一致性" + ], + "interfaces": [], + "dependencies": [ + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 10, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024513, + "prompt_hash": "860f2aef0ec434e6bf925a94c7a7aa79", + "token_usage": { + "input_tokens": 471, + "output_tokens": 386, + "total_tokens": 857 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8774bcabedc89de528bdab1b0eb158c2.json b/.litho/cache/ai_code_insight/8774bcabedc89de528bdab1b0eb158c2.json new file mode 100644 index 0000000..53c666b --- /dev/null +++ b/.litho/cache/ai_code_insight/8774bcabedc89de528bdab1b0eb158c2.json @@ -0,0 +1,109 @@ +{ + "data": { + "code_dossier": { + "name": "feeds_update.rs", + "file_path": "app/src-tauri/src/daemon/feeds_update.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "负责定时拉取并更新订阅源内容的后台守护任务,基于配置频率执行周期性更新。", + "functions": [ + "launch_feeds_schedule_update", + "schedule_loop" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了一个后台定时任务代理(Agent),用于周期性地更新应用程序中的订阅源内容。通过读取应用配置中的更新频率(高频1小时或低频3小时),启动一个异步循环,每隔设定时间触发一次批量更新操作。每次执行时遍历所有已注册的feed package及其包含的feed项,并调用FeaturesAPI进行内容更新。使用文件锁机制防止多个实例同时运行,确保更新过程的唯一性和安全性。错误信息通过日志记录,成功与失败均有相应日志输出,便于监控和调试。", + "responsibilities": [ + "管理订阅源内容的周期性自动更新任务", + "防止并发执行:通过文件锁确保同一时间仅有一个更新进程运行", + "根据应用配置动态调整更新频率(1小时或3小时)", + "协调调用FeaturesAPI完成各个feed的内容拉取与刷新", + "提供结构化日志输出以支持运行时监控和故障排查" + ], + "interfaces": [], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "is_external": false, + "line_number": null, + "dependency_type": "std", + "version": null + }, + { + "name": "feed_api_rs::features::api::FeaturesAPI", + "path": "feed_api_rs::features::api::FeaturesAPI", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "fslock::LockFile", + "path": "fslock::LockFile", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tauri", + "path": "tauri", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tauri_plugin_feed_api::state::HybridRuntimeState", + "path": "tauri_plugin_feed_api::state::HybridRuntimeState", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "tokio::time", + "path": "tokio::time", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "crate::daemon::locks", + "path": "crate::daemon::locks", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 69, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.875, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024433, + "prompt_hash": "8774bcabedc89de528bdab1b0eb158c2", + "token_usage": { + "input_tokens": 1026, + "output_tokens": 894, + "total_tokens": 1920 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/87aade9efd624b66cc966003e2391c82.json b/.litho/cache/ai_code_insight/87aade9efd624b66cc966003e2391c82.json new file mode 100644 index 0000000..5ca2d9b --- /dev/null +++ b/.litho/cache/ai_code_insight/87aade9efd624b66cc966003e2391c82.json @@ -0,0 +1,159 @@ +{ + "data": { + "code_dossier": { + "name": "article_record.rs", + "file_path": "crates/recorder/src/entity/article_record.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义文章记录的数据模型,包含源链接、标题、内容版本、阅读状态等字段,用于ORM映射和数据持久化。", + "functions": [], + "interfaces": [ + "Model", + "Relation", + "ActiveModelBehavior" + ] + }, + "detailed_description": "该组件是SeaORM框架下的实体模型,代表数据库表t_article_record的结构。它封装了一篇文章的核心元数据与内容信息,包括原始和优化后的内容、导读、发布日期、创建时间、阅读/收藏状态以及分组ID。通过serde和sea-orm的派生宏实现了序列化、反序列化及ORM行为支持,适用于后端数据存储与API传输场景。", + "responsibilities": [ + "定义文章记录的数据结构和ORM映射", + "支持JSON等格式的序列化与反序列化", + "维护文章内容的不同版本(原始、净化、优化、熔合)", + "记录文章的元信息如发布时间、创建时间、阅读状态", + "提供对数据库操作所需的基本模型行为实现" + ], + "interfaces": [ + { + "name": "Model", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "id", + "param_type": "i32", + "is_optional": false, + "description": "主键ID" + }, + { + "name": "source_link", + "param_type": "String", + "is_optional": false, + "description": "原文链接" + }, + { + "name": "title", + "param_type": "String", + "is_optional": false, + "description": "文章标题" + }, + { + "name": "purged_content", + "param_type": "String", + "is_optional": false, + "description": "清理后的原始正文" + }, + { + "name": "head_read", + "param_type": "String", + "is_optional": false, + "description": "导读内容" + }, + { + "name": "optimized_content", + "param_type": "String", + "is_optional": false, + "description": "优化后的正文" + }, + { + "name": "melted_content", + "param_type": "String", + "is_optional": false, + "description": "融合处理后的正文" + }, + { + "name": "published_at", + "param_type": "chrono::NaiveDate", + "is_optional": false, + "description": "新闻发布的日期" + }, + { + "name": "created_at", + "param_type": "chrono::NaiveDate", + "is_optional": false, + "description": "记录创建时间" + }, + { + "name": "has_read", + "param_type": "bool", + "is_optional": false, + "description": "是否已阅读" + }, + { + "name": "is_favorite", + "param_type": "bool", + "is_optional": false, + "description": "是否收藏" + }, + { + "name": "group_id", + "param_type": "String", + "is_optional": false, + "description": "所属分组ID" + } + ], + "return_type": null, + "description": "文章记录的实体模型,对应数据库表t_article_record" + }, + { + "name": "Relation", + "interface_type": "enum", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "用于定义与其他实体的关系,当前为空枚举,表示无关联关系" + }, + { + "name": "ActiveModelBehavior", + "interface_type": "trait impl", + "visibility": "impl", + "parameters": [], + "return_type": null, + "description": "为ActiveModel提供默认行为实现,当前为空实现" + } + ], + "dependencies": [ + { + "name": "sea_orm", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": true, + "line_number": 1, + "dependency_type": "orm", + "version": null + }, + { + "name": "serde", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 28, + "number_of_functions": 0, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805924, + "prompt_hash": "87aade9efd624b66cc966003e2391c82", + "token_usage": { + "input_tokens": 656, + "output_tokens": 1095, + "total_tokens": 1751 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/87d989544413a8099358bde45864e14f.json b/.litho/cache/ai_code_insight/87d989544413a8099358bde45864e14f.json new file mode 100644 index 0000000..0236755 --- /dev/null +++ b/.litho/cache/ai_code_insight/87d989544413a8099358bde45864e14f.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "en.json", + "file_path": "app/src/lib/i18n/locales/en.json", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "英文语言包配置文件,包含应用所有用户界面的国际化文本内容。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个JSON格式的国际化语言配置文件,用于存储Saga Reader应用的英文用户界面文本。它按照功能模块(如common、main、reader、settings等)组织键值对,覆盖了产品名称、菜单项、对话框按钮、表单提示、状态消息等UI元素的显示文本。支持动态占位符(如{name}、{length}、{e}),允许在运行时注入变量值。该文件是i18n系统的核心资源之一,与前端框架结合实现多语言切换。", + "responsibilities": [ + "提供应用界面的英文文本资源", + "支持多语言国际化(i18n)功能", + "管理UI元素的静态文案和动态提示信息", + "通过结构化键路径组织语言资源便于维护" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 183, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024700, + "prompt_hash": "87d989544413a8099358bde45864e14f", + "token_usage": { + "input_tokens": 2325, + "output_tokens": 455, + "total_tokens": 2780 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/88b1de4cfa45a27fbd0f96d11fb12a14.json b/.litho/cache/ai_code_insight/88b1de4cfa45a27fbd0f96d11fb12a14.json new file mode 100644 index 0000000..9488608 --- /dev/null +++ b/.litho/cache/ai_code_insight/88b1de4cfa45a27fbd0f96d11fb12a14.json @@ -0,0 +1,129 @@ +{ + "data": { + "code_dossier": { + "name": "launcher.rs", + "file_path": "app/src-tauri/src/daemon/launcher.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "负责守护进程的启动逻辑,包含带错误忽略的启动和标准启动两种模式。", + "functions": [ + "launch_ignore_error", + "launch" + ], + "interfaces": [ + "launch_ignore_error", + "launch" + ] + }, + "detailed_description": "该组件实现了守护进程(daemon)的启动功能,主要通过调用当前可执行文件并传递参数来启动后台服务。它使用文件锁机制防止重复启动,确保同一时间只有一个实例运行。launch函数是核心逻辑,先获取锁路径,尝试加锁,若已锁定则认为守护进程已在运行;否则释放锁并启动新进程。launch_ignore_error是对launch的安全封装,捕获所有错误并记录日志而不中断调用者。", + "responsibilities": [ + "管理守护进程的启动流程", + "通过文件锁防止守护进程重复启动", + "提供静默失败的安全启动接口", + "记录守护进程生命周期的关键事件日志" + ], + "interfaces": [ + { + "name": "launch", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "host_arg", + "param_type": "&str", + "is_optional": false, + "description": "传递给守护进程的主机参数" + }, + { + "name": "locker_monitor_name", + "param_type": "&str", + "is_optional": false, + "description": "用于生成锁文件路径的标识名" + } + ], + "return_type": "anyhow::Result<()>", + "description": "标准启动方法,成功返回Ok,失败返回错误" + }, + { + "name": "launch_ignore_error", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "host_arg", + "param_type": "&str", + "is_optional": false, + "description": "传递给守护进程的主机参数" + }, + { + "name": "locker_monitor_name", + "param_type": "&str", + "is_optional": false, + "description": "用于生成锁文件路径的标识名" + } + ], + "return_type": "()", + "description": "安全启动方法,内部处理所有错误并记录日志" + } + ], + "dependencies": [ + { + "name": "std::env", + "path": "std::env", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "std::process::Command", + "path": "std::process::Command", + "is_external": false, + "line_number": 2, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "fslock::LockFile", + "path": "fslock", + "is_external": true, + "line_number": 4, + "dependency_type": "external_crate", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": 5, + "dependency_type": "external_crate", + "version": null + }, + { + "name": "crate::daemon::locks::get_lock_path", + "path": "crate::daemon::locks", + "is_external": false, + "line_number": 7, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 41, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.56, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805679, + "prompt_hash": "88b1de4cfa45a27fbd0f96d11fb12a14", + "token_usage": { + "input_tokens": 795, + "output_tokens": 930, + "total_tokens": 1725 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/88c86ac5915868064de89650a69f65b2.json b/.litho/cache/ai_code_insight/88c86ac5915868064de89650a69f65b2.json new file mode 100644 index 0000000..f1f4141 --- /dev/null +++ b/.litho/cache/ai_code_insight/88c86ac5915868064de89650a69f65b2.json @@ -0,0 +1,152 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/types/src/lib.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.8, + "description": "定义了系统核心数据模型,包括文章、配置、用户订阅和对话消息等结构体。", + "functions": [ + "rename_feed", + "change_feed_data", + "remove_feed", + "find_feeds_package", + "find_feeds_package_mut", + "find_feed", + "add_feeds_packages", + "remove_feeds_package", + "rename_feeds_package", + "search_feeds_package_inner" + ], + "interfaces": [ + "Article", + "LLMInstructOption", + "AppConfigLogSection", + "DiagnosticSection", + "OutputType", + "ScrapProviderType", + "LLMProviderType", + "LLMProvider", + "PlatformLLMProvider", + "GLMLLMProvider", + "OpenAILLMProvider", + "OllamaLLMProvider", + "LLMSection", + "DaemonSection", + "ScrapSection", + "AppConfig", + "UserConfig", + "FeedsPackage", + "FeedTargetDescription", + "ConversationMessageRoleType", + "ConversationMessagePayloadType", + "ConversationMessage" + ] + }, + "detailed_description": "该组件是系统的核心数据模型层,定义了多个用于配置管理、内容处理和用户交互的数据结构。主要包括:1) 配置相关模型(AppConfig, UserConfig)用于管理应用和用户的配置信息;2) LLM相关模型(LLMProviderType, LLMSection等)用于支持多种大语言模型提供商的配置和切换;3) 订阅管理模型(FeedsPackage, FeedTargetDescription)用于管理用户订阅包和订阅项;4) 对话消息模型(ConversationMessage)用于表示聊天会话中的消息。组件通过Serde实现序列化/反序列化,支持JSON等格式的持久化和传输。", + "responsibilities": [ + "定义系统核心数据结构和模型", + "提供配置管理和序列化支持", + "支持多LLM提供商的类型安全枚举", + "实现用户订阅包的增删改查操作", + "确保数据结构的可扩展性和类型安全性" + ], + "interfaces": [ + { + "name": "UserConfig", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "用户配置主结构体,包含订阅包列表" + }, + { + "name": "rename_feed", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": "订阅包ID" + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": "订阅项ID" + }, + { + "name": "new_name", + "param_type": "&str", + "is_optional": false, + "description": "新名称" + } + ], + "return_type": "bool", + "description": "重命名指定的订阅项" + }, + { + "name": "LLMProviderType", + "interface_type": "enum", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "支持的LLM提供商枚举" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "serialization", + "version": null + }, + { + "name": "strum", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "enum_utils", + "version": null + }, + { + "name": "std::cmp::Ordering", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "crate::llm_endpoint::LLMEndPoint", + "path": "crates/types/src/llm_endpoint.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 18.0, + "lines_of_code": 378, + "number_of_functions": 10, + "number_of_classes": 24, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024245, + "prompt_hash": "88c86ac5915868064de89650a69f65b2", + "token_usage": { + "input_tokens": 3322, + "output_tokens": 1027, + "total_tokens": 4349 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/89ff389b285cb8f201720a6bbde0927a.json b/.litho/cache/ai_code_insight/89ff389b285cb8f201720a6bbde0927a.json new file mode 100644 index 0000000..551cc95 --- /dev/null +++ b/.litho/cache/ai_code_insight/89ff389b285cb8f201720a6bbde0927a.json @@ -0,0 +1,93 @@ +{ + "data": { + "code_dossier": { + "name": "init_llm.rs", + "file_path": "crates/feed_api_rs/src/startup/init_llm.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "初始化LLM提供者服务,根据配置启动或检查Ollama等本地大模型运行时状态。", + "functions": [ + "call" + ], + "interfaces": [ + "call" + ] + }, + "detailed_description": "该组件负责在系统启动阶段对配置的LLM(大型语言模型)提供者进行初始化。主要逻辑为:若配置使用Ollama作为提供者,则通过query_platform检查其运行状态;若已安装但未运行,则尝试调用launch()启动服务;若无法连接,则记录错误并标记为未安装。对于其他LLM提供者类型,执行空初始化任务。此过程以异步方式执行,并集成到系统的初始化任务框架中。", + "responsibilities": [ + "根据LLMSection配置判断激活的LLM提供者类型", + "针对Ollama提供者执行平台可用性检测与自启恢复", + "集成到统一的异步初始化任务系统中", + "处理Ollama服务状态查询中的网络或服务异常", + "为非Ollama提供者执行空初始化占位操作" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "&LLMSection", + "is_optional": false, + "description": "包含LLM配置信息的引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "执行LLM提供者的初始化流程" + } + ], + "dependencies": [ + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "logging", + "version": null + }, + { + "name": "ollama", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "service_client", + "version": null + }, + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 3, + "dependency_type": "model", + "version": null + }, + { + "name": "InitTask", + "path": "super::task::{InitTask, TaskInitializer}", + "is_external": false, + "line_number": 5, + "dependency_type": "framework", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 38, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.75, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801177, + "prompt_hash": "89ff389b285cb8f201720a6bbde0927a", + "token_usage": { + "input_tokens": 832, + "output_tokens": 713, + "total_tokens": 1545 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8a80f984693064e97840353555933f94.json b/.litho/cache/ai_code_insight/8a80f984693064e97840353555933f94.json new file mode 100644 index 0000000..093883c --- /dev/null +++ b/.litho/cache/ai_code_insight/8a80f984693064e97840353555933f94.json @@ -0,0 +1,146 @@ +{ + "data": { + "code_dossier": { + "name": "llm_platform.rs", + "file_path": "crates/llm/src/providers/llm_platform.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "实现基于平台的LLM服务调用代理,封装请求参数并完成与远程模型的交互。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了PlatformAgentService结构体,用于封装对特定LLM平台的调用逻辑。它通过reqwest客户端发送JSON格式的请求到目标平台,并接收文本响应。当前硬编码了空URL(需配置),使用RequestParameters序列化提示内容。其主要作用是作为AI能力提供者的适配层,对接外部大模型服务。", + "responsibilities": [ + "初始化HTTP客户端与配置信息", + "构造标准化的请求参数对象", + "执行远程LLM补全请求并处理响应", + "实现CompletionService接口以统一调用契约", + "管理与外部LLM平台的通信细节" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义LLM补全服务的标准接口" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&PlatformLLMProvider", + "is_optional": false, + "description": "平台配置信息引用" + }, + { + "name": "_system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词(当前未使用)" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "AI目标选项(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "创建PlatformAgentService实例" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "prompt", + "param_type": "String", + "is_optional": false, + "description": "用户输入提示" + } + ], + "return_type": "anyhow::Result", + "description": "异步执行文本补全请求" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "serde::Serialize", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::PlatformLLMProvider", + "path": "types", + "is_external": false, + "line_number": 4, + "dependency_type": "model", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "utility", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "interface", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 45, + "number_of_functions": 2, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 5.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024246, + "prompt_hash": "8a80f984693064e97840353555933f94", + "token_usage": { + "input_tokens": 765, + "output_tokens": 916, + "total_tokens": 1681 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8b418c3361926337283c2a123284c5f2.json b/.litho/cache/ai_code_insight/8b418c3361926337283c2a123284c5f2.json new file mode 100644 index 0000000..26f3919 --- /dev/null +++ b/.litho/cache/ai_code_insight/8b418c3361926337283c2a123284c5f2.json @@ -0,0 +1,182 @@ +{ + "data": { + "code_dossier": { + "name": "llm_processor.rs", + "file_path": "crates/intelligent/src/article_processor/llm_processor.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "基于LLM的文章处理器,利用生成式AI模型对文章内容进行处理和转换。", + "functions": [ + "new", + "process" + ], + "interfaces": [ + "IArticleProcessor", + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件是一个基于大型语言模型(LLM)的文章处理器,负责将输入的文章内容通过预设的系统提示和用户指令发送给LLM代理进行处理,并返回经过LLM生成或修改后的内容。它支持多语言处理,能够根据配置的语言选项自动适配输出语种。组件通过CompletionAgent与底层LLM服务交互,封装了prompt构造、语言处理逻辑以及结果注入等流程。", + "responsibilities": [ + "作为LLM代理的前端接口,协调文章内容与AI模型之间的交互", + "构建符合要求的Prompt指令,包括原文、用户命令和语言规范", + "处理多语言需求,根据系统或指定语言设置输出语种", + "实现文章内容的异步生成式处理,保持输入结构不变仅替换内容", + "提供可扩展的构造接口以支持不同场景下的实例化" + ], + "interfaces": [ + { + "name": "IArticleProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result
", + "description": "文章处理器统一接口,定义process方法用于处理文章。" + }, + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "预设LLM处理器创建trait,用于框架层面统一创建ArticleLLMProcessor实例。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": null + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "user_prompt_command", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "构造一个新的ArticleLLMProcessor实例,接受LLM配置、系统提示、用户命令和AI目标选项。" + }, + { + "name": "process", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "input", + "param_type": "&Article", + "is_optional": false, + "description": null + }, + { + "name": "opt", + "param_type": "LLMInstructOption", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result
", + "description": "异步处理输入文章,调用LLM完成内容生成并返回新文章。" + } + ], + "dependencies": [ + { + "name": "llm::llm_agent::CompletionAgent", + "path": "llm::llm_agent::CompletionAgent", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types::AITargetOption", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "types::Article", + "path": "types::Article", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "types::LLMInstructOption", + "path": "types::LLMInstructOption", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types::LLMSection", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::article_processor::types::IArticleProcessor", + "path": "crate::article_processor::types::IArticleProcessor", + "is_external": false, + "line_number": 5, + "dependency_type": "trait", + "version": null + }, + { + "name": "sys_locale::get_locale", + "path": "sys_locale::get_locale", + "is_external": true, + "line_number": 6, + "dependency_type": "function", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 61, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024333, + "prompt_hash": "8b418c3361926337283c2a123284c5f2", + "token_usage": { + "input_tokens": 1021, + "output_tokens": 1278, + "total_tokens": 2299 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8b50e08f39972e471eeff731e83dc8f8.json b/.litho/cache/ai_code_insight/8b50e08f39972e471eeff731e83dc8f8.json new file mode 100644 index 0000000..5568f93 --- /dev/null +++ b/.litho/cache/ai_code_insight/8b50e08f39972e471eeff731e83dc8f8.json @@ -0,0 +1,51 @@ +{ + "data": { + "code_dossier": { + "name": "loading.ts", + "file_path": "app/src/lib/types/loading.ts", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义加载状态的枚举类型,用于表示异步操作的不同阶段", + "functions": [], + "interfaces": [ + "LoadingStatus" + ] + }, + "detailed_description": "该组件定义了一个名为LoadingStatus的枚举类型,包含三个状态值:Loading(加载中)、Completed(已完成)和Error(出错)。该枚举主要用于表示异步操作(如数据获取、文件上传等)的生命周期状态,为前端UI状态管理和错误处理提供标准化的状态标识。", + "responsibilities": [ + "定义异步操作的标准状态枚举", + "提供类型安全的状态值引用", + "支持UI根据加载状态进行条件渲染", + "作为领域模型在不同组件间传递状态信息" + ], + "interfaces": [ + { + "name": "LoadingStatus", + "interface_type": "enum", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "表示异步操作的三种可能状态:加载中、已完成、出错" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 7, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024682, + "prompt_hash": "8b50e08f39972e471eeff731e83dc8f8", + "token_usage": { + "input_tokens": 431, + "output_tokens": 444, + "total_tokens": 875 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8c3a3790eb2a9d2a2fe2f790fc5c2b79.json b/.litho/cache/ai_code_insight/8c3a3790eb2a9d2a2fe2f790fc5c2b79.json new file mode 100644 index 0000000..4b02e3a --- /dev/null +++ b/.litho/cache/ai_code_insight/8c3a3790eb2a9d2a2fe2f790fc5c2b79.json @@ -0,0 +1,159 @@ +{ + "data": { + "code_dossier": { + "name": "AISpritePanel.svelte", + "file_path": "app/src/routes/main/widgets/AISpritePanel.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "AI助手交互面板,提供聊天界面和用户输入功能", + "functions": [ + "scrollChatBottom", + "addMessage", + "onPromptKeydown", + "toDateText" + ], + "interfaces": [ + "store: AISpriteProps" + ] + }, + "detailed_description": "该组件实现了一个悬浮式AI助手聊天面板,包含消息历史展示、实时输入、加载状态反馈等功能。通过绑定store属性管理对话状态,支持键盘快捷发送(回车键),并集成国际化文本显示。UI采用Svelte框架构建,使用Skeleton UI库的Avatar、ProgressRing等组件,并通过Markdown渲染器展示AI回复内容。面板可展开/收起,具备流畅滚动动画和响应式布局。", + "responsibilities": [ + "管理AI助手面板的显示与隐藏状态", + "渲染对话历史记录,区分用户与AI消息", + "处理用户输入并触发消息发送逻辑", + "提供加载状态视觉反馈", + "实现聊天区域自动滚动到底部" + ], + "interfaces": [ + { + "name": "store", + "interface_type": "prop", + "visibility": "public", + "parameters": [ + { + "name": "store", + "param_type": "AISpriteProps", + "is_optional": false, + "description": "包含对话历史、加载状态和操作方法的状态管理对象" + } + ], + "return_type": null, + "description": "接收外部传入的AI对话状态和控制方法" + }, + { + "name": "scrollChatBottom", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "behavior", + "param_type": "'auto' | 'instant' | 'smooth'", + "is_optional": true, + "description": "滚动动画行为" + } + ], + "return_type": "void", + "description": "将聊天容器滚动到底部" + }, + { + "name": "addMessage", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "Promise", + "description": "处理用户消息发送逻辑,包含防重复提交和错误提示" + }, + { + "name": "onPromptKeydown", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "event", + "param_type": "KeyboardEvent", + "is_optional": false, + "description": "键盘事件对象" + } + ], + "return_type": "void", + "description": "监听回车键触发消息发送" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "AISpriteProps", + "path": "../widgets/types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "ui_library", + "version": null + }, + { + "name": "lucide-svelte", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "icon_library", + "version": null + }, + { + "name": "$lib/widgets/Markdown.svelte", + "path": "$lib/widgets/Markdown.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "component", + "version": null + }, + { + "name": "toaster", + "path": "../stores/toast", + "is_external": false, + "line_number": 6, + "dependency_type": "store", + "version": null + }, + { + "name": "svelte", + "path": null, + "is_external": true, + "line_number": 8, + "dependency_type": "framework", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 9.0, + "lines_of_code": 186, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024204, + "prompt_hash": "8c3a3790eb2a9d2a2fe2f790fc5c2b79", + "token_usage": { + "input_tokens": 1765, + "output_tokens": 1028, + "total_tokens": 2793 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8e292d9c80991a9f4ec647fd3faacef2.json b/.litho/cache/ai_code_insight/8e292d9c80991a9f4ec647fd3faacef2.json new file mode 100644 index 0000000..90022be --- /dev/null +++ b/.litho/cache/ai_code_insight/8e292d9c80991a9f4ec647fd3faacef2.json @@ -0,0 +1,178 @@ +{ + "data": { + "code_dossier": { + "name": "llm_ollama.rs", + "file_path": "crates/llm/src/providers/llm_ollama.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现基于 Ollama LLM 的文本补全功能,封装请求参数并调用远程 API 完成生成任务", + "functions": [ + "OllamaCompletionService::new", + "OllamaCompletionService::completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了针对 Ollama 大语言模型的补全服务。通过封装请求体(RequestParameter)和解析响应(CompletionReply),利用 reqwest 发送 POST 请求至指定 endpoint 执行 completion 调用。系统提示词、模型配置和 AI 目标选项均在初始化时注入,确保可配置性与复用性。主要服务于需要与本地或私有部署的 Ollama 模型交互的功能模块。", + "responsibilities": [ + "初始化 Ollama 补全服务所需的客户端与配置参数", + "构造符合 Ollama API 规范的请求数据结构", + "调用远程 /api/generate 接口完成文本生成任务", + "解析返回结果并提取生成文本", + "管理 HTTP 客户端生命周期及超时设置(间接依赖 connector)" + ], + "interfaces": [ + { + "name": "OllamaCompletionService::new", + "interface_type": "constructor", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "OllamaLLMProvider", + "is_optional": false, + "description": "包含 endpoint 等配置信息" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统级提示语" + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "AI 推理目标相关选项" + } + ], + "return_type": "anyhow::Result", + "description": "创建一个新的 Ollama 补全服务实例" + }, + { + "name": "OllamaCompletionService::completion", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行一次补全请求并返回生成结果" + }, + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "统一的补全服务接口契约" + }, + { + "name": "RequestParameter", + "interface_type": "struct", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "用于序列化为 JSON 的请求体结构" + }, + { + "name": "CompletionReply", + "interface_type": "struct", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "用于反序列化响应体的结果结构" + }, + { + "name": "OllamaCompletionService", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "Ollama 补全服务主结构体" + }, + { + "name": "impl CompletionService for OllamaCompletionService", + "interface_type": "implementation", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "为 Ollama 实现通用补全接口" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::llm_endpoint::LLMEndPoint", + "path": "types/llm_endpoint.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "model", + "version": null + }, + { + "name": "types::OllamaLLMProvider", + "path": "types/mod.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "config", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "utility", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 8, + "dependency_type": "model", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 65, + "number_of_functions": 2, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.38, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024253, + "prompt_hash": "8e292d9c80991a9f4ec647fd3faacef2", + "token_usage": { + "input_tokens": 947, + "output_tokens": 1221, + "total_tokens": 2168 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8f2b7f9a396fa7d8f831124619001714.json b/.litho/cache/ai_code_insight/8f2b7f9a396fa7d8f831124619001714.json new file mode 100644 index 0000000..301e2cc --- /dev/null +++ b/.litho/cache/ai_code_insight/8f2b7f9a396fa7d8f831124619001714.json @@ -0,0 +1,59 @@ +{ + "data": { + "code_dossier": { + "name": "connector.rs", + "file_path": "crates/llm/src/connector.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "创建并配置用于HTTP请求的reqwest客户端,支持超时和压缩。", + "functions": [ + "new" + ], + "interfaces": [] + }, + "detailed_description": "该组件负责构建一个预配置的reqwest HTTP客户端实例,用于后续的网络请求操作。当前配置包括60秒的全局超时、启用Gzip和Deflate压缩算法以优化传输效率。此客户端通常被LLM相关模块用于调用远程API服务。", + "responsibilities": [ + "初始化HTTP客户端实例", + "设置合理的请求超时策略", + "启用响应内容压缩支持", + "提供可复用的客户端构造方法" + ], + "interfaces": [], + "dependencies": [ + { + "name": "std::time::Duration", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "third_party", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024573, + "prompt_hash": "8f2b7f9a396fa7d8f831124619001714", + "token_usage": { + "input_tokens": 475, + "output_tokens": 400, + "total_tokens": 875 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/8ff5bf46b5d12046d8fdc8053bc2c451.json b/.litho/cache/ai_code_insight/8ff5bf46b5d12046d8fdc8053bc2c451.json new file mode 100644 index 0000000..64d57b3 --- /dev/null +++ b/.litho/cache/ai_code_insight/8ff5bf46b5d12046d8fdc8053bc2c451.json @@ -0,0 +1,133 @@ +{ + "data": { + "code_dossier": { + "name": "lite-edit.ts", + "file_path": "app/src/lib/windows/lite-edit.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "该组件负责管理与订阅组和订阅相关的窗口打开逻辑,封装了 Tauri 窗口操作的异步交互流程。", + "functions": [ + "openFeedPackageCreateWindow", + "openFeedPackageEditWindow", + "openFeedCreateWindow", + "openFeedEditWindow", + "open" + ], + "interfaces": [ + "UnlistenFn", + "FeedsPackage", + "FeedTargetDescription", + "WindowOptions" + ] + }, + "detailed_description": "该文件实现了一组用于打开模态窗口的函数,主要用于创建或编辑‘订阅组’(FeedsPackage) 和 ‘订阅’(Feed)。每个公开函数都返回一个 Promise,封装了通过回调接收用户输入结果的异步过程。核心逻辑集中在 `open` 函数中,它利用 Tauri 的 `openWithCallback` 方法打开指定 URL 的新窗口,并在窗口关闭时执行回调,自动清理事件监听器。所有上层函数(如 openFeedPackageCreateWindow)基于此通用机制构造特定参数的 URL 并解析返回数据。整个模块作为 UI 控制层,桥接前端页面与底层窗口系统。", + "responsibilities": [ + "提供统一的窗口打开与回调处理机制", + "封装订阅组和订阅的创建/编辑窗口打开逻辑", + "管理窗口生命周期中的事件监听器自动释放", + "构造带参数的导航URL以传递模式和上下文数据", + "将底层回调接口转换为Promise风格的异步API" + ], + "interfaces": [ + { + "name": "open", + "interface_type": "function", + "visibility": "exported", + "parameters": [ + { + "name": "label", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "title", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "url", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "onFinish", + "param_type": "(submited: boolean, data: string) => void", + "is_optional": false, + "description": null + }, + { + "name": "windowOpt", + "param_type": "WindowOptions", + "is_optional": true, + "description": null + } + ], + "return_type": "Promise", + "description": "通用函数:打开指定标签、标题、URL的窗口,并注册关闭回调。支持传入选项覆盖默认窗口配置。" + }, + { + "name": "openFeedPackageCreateWindow", + "interface_type": "function", + "visibility": "exported", + "parameters": [], + "return_type": "Promise", + "description": "打开‘新增订阅组’窗口,用户提交后返回 FeedsPackage 数据对象。" + } + ], + "dependencies": [ + { + "name": "@tauri-apps/api/event", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "type", + "version": null + }, + { + "name": "./utils", + "path": "app/src/lib/windows/utils", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "app/src/lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "@tauri-apps/api/window", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 103, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024474, + "prompt_hash": "8ff5bf46b5d12046d8fdc8053bc2c451", + "token_usage": { + "input_tokens": 1084, + "output_tokens": 1035, + "total_tokens": 2119 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/900b73675a2a8d1afd2c5c9d53c46131.json b/.litho/cache/ai_code_insight/900b73675a2a8d1afd2c5c9d53c46131.json new file mode 100644 index 0000000..795965b --- /dev/null +++ b/.litho/cache/ai_code_insight/900b73675a2a8d1afd2c5c9d53c46131.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "constrant.rs", + "file_path": "app/src-tauri/src/constrant.rs", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "定义了应用程序中多个窗口的标签、URL和标题常量,用于Tauri应用的窗口管理和前端路由配置。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件通过定义一系列公共常量,为Tauri桌面应用中的多个窗口(如主窗口、外部端点信息窗口、关于窗口)提供统一的标识符(label)、访问路径(URL)和显示标题(title)。这些常量被用于窗口创建、路由匹配和UI展示等场景,确保跨模块引用的一致性和可维护性。代码采用清晰的命名约定,按功能分组组织常量,提升了可读性。", + "responsibilities": [ + "定义并导出主窗口的标识、路径与标题常量", + "管理外部端点信息窗口的导航与显示配置", + "维护‘关于’窗口的相关元信息", + "为前端路由与窗口控制系统提供统一配置源" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 11, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024665, + "prompt_hash": "900b73675a2a8d1afd2c5c9d53c46131", + "token_usage": { + "input_tokens": 545, + "output_tokens": 469, + "total_tokens": 1014 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/909b5cb43cabaa97af93cea50a9d8474.json b/.litho/cache/ai_code_insight/909b5cb43cabaa97af93cea50a9d8474.json new file mode 100644 index 0000000..9bc945c --- /dev/null +++ b/.litho/cache/ai_code_insight/909b5cb43cabaa97af93cea50a9d8474.json @@ -0,0 +1,89 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/llm/src/providers/mod.rs", + "source_summary": "", + "code_purpose": "router", + "importance_score": 0.6, + "description": "该模块作为LLM提供者功能的内部路由与组织单元,集中声明了多个子模块,用于管理不同LLM服务(如Mistral、Ollama、GLM、OpenAI兼容等)的实现。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该文件是Rust项目中`llm` crate下`providers`目录的模块定义文件(mod.rs),其主要作用是将多个具体的LLM提供商实现模块进行聚合和可见性控制。通过`pub(crate) mod`语法,它将`llm_mistral`、`llm_ollama`、`llm_platform`、`llm_glm`、`llm_openaibase_like`等私有于crate内的子模块引入当前命名空间,同时将`types`模块设为公共以供外部使用。此文件本身不包含具体业务逻辑或函数实现,而是承担模块组织和封装职责,形成清晰的代码结构层次。", + "responsibilities": [ + "聚合所有LLM提供商的子模块,形成统一的模块入口", + "控制各子模块在crate内的可见性(通过pub(crate))", + "暴露公共类型接口(types模块)以便其他模块复用", + "维护LLM providers层级的命名空间结构" + ], + "interfaces": [], + "dependencies": [ + { + "name": "llm_mistral", + "path": "crates/llm/src/providers/llm_mistral/mod.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_ollama", + "path": "crates/llm/src/providers/llm_ollama/mod.rs", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_platform", + "path": "crates/llm/src/providers/llm_platform/mod.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "types", + "path": "crates/llm/src/providers/types/mod.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_glm", + "path": "crates/llm/src/providers/llm_glm/mod.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "llm_openaibase_like", + "path": "crates/llm/src/providers/llm_openaibase_like/mod.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 6.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024570, + "prompt_hash": "909b5cb43cabaa97af93cea50a9d8474", + "token_usage": { + "input_tokens": 446, + "output_tokens": 756, + "total_tokens": 1202 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/909d78037190872fb1bae3181c9be40d.json b/.litho/cache/ai_code_insight/909d78037190872fb1bae3181c9be40d.json new file mode 100644 index 0000000..35aa9dc --- /dev/null +++ b/.litho/cache/ai_code_insight/909d78037190872fb1bae3181c9be40d.json @@ -0,0 +1,49 @@ +{ + "data": { + "code_dossier": { + "name": "id.ts", + "file_path": "app/src/lib/utils/id.ts", + "code_purpose": "util", + "importance_score": 0.6, + "description": "生成基于时间戳的字符串ID", + "functions": [ + "genStringId" + ], + "interfaces": [] + }, + "detailed_description": "该组件提供了一个简单的函数 genStringId,用于生成基于当前时间戳的字符串ID。通过调用 Date.now() 获取毫秒级时间戳,并将其转换为字符串返回。适用于需要简单唯一标识符的场景,但不保证全局唯一性或高并发下的顺序性。", + "responsibilities": [ + "生成基于时间戳的字符串形式的唯一ID", + "提供轻量级的ID生成能力供其他模块使用", + "确保ID生成过程简单高效" + ], + "interfaces": [ + { + "name": "genStringId", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "string", + "description": "生成一个基于当前时间戳的字符串ID" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 5, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805997, + "prompt_hash": "909d78037190872fb1bae3181c9be40d", + "token_usage": { + "input_tokens": 421, + "output_tokens": 385, + "total_tokens": 806 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9174e34c1b67e246a67144e35bb94e48.json b/.litho/cache/ai_code_insight/9174e34c1b67e246a67144e35bb94e48.json new file mode 100644 index 0000000..08c2b84 --- /dev/null +++ b/.litho/cache/ai_code_insight/9174e34c1b67e246a67144e35bb94e48.json @@ -0,0 +1,120 @@ +{ + "data": { + "code_dossier": { + "name": "hooks.server.ts", + "file_path": "app/src/hooks.server.ts", + "code_purpose": "middleware", + "importance_score": 0.6, + "description": "SvelteKit服务端钩子文件,用于初始化Sentry监控并处理全局请求拦截逻辑。", + "functions": [ + "handle", + "handleError" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit应用的服务端钩子(server hook),主要负责初始化Sentry错误追踪系统,并在每个请求处理过程中设置用户的语言偏好。通过`sequence`中间件链,首先集成Sentry的请求处理,然后从HTTP请求头中提取`accept-language`字段,将其设置为当前会话的语言环境。最后,使用Sentry包装的错误处理器来捕获和上报未处理的异常。整个流程确保了应用具备全面的错误监控能力和基础的国际化支持。", + "responsibilities": [ + "初始化Sentry性能与错误监控SDK", + "作为请求中间件链的一部分处理传入请求", + "解析并设置用户语言偏好以支持国际化", + "集成全局错误处理机制以捕获未捕获异常" + ], + "interfaces": [ + { + "name": "handle", + "interface_type": "Handle", + "visibility": "export", + "parameters": [ + { + "name": "event", + "param_type": "RequestEvent", + "is_optional": false, + "description": "SvelteKit请求事件对象" + }, + { + "name": "resolve", + "param_type": "(event: RequestEvent) => Response", + "is_optional": false, + "description": "解析请求并返回响应的函数" + } + ], + "return_type": "Response", + "description": "处理请求中间件链" + }, + { + "name": "handleError", + "interface_type": "HandleServerError", + "visibility": "export", + "parameters": [ + { + "name": "input", + "param_type": "{ error: unknown; event: RequestEvent }", + "is_optional": false, + "description": "包含错误和请求事件的对象" + } + ], + "return_type": "App.Error", + "description": "统一错误处理并上报至Sentry" + } + ], + "dependencies": [ + { + "name": "@sveltejs/kit", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "framework", + "version": null + }, + { + "name": "@sveltejs/kit/hooks", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "utility", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "monitoring", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "monitoring", + "version": null + }, + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "i18n", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 25, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.8, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758806029, + "prompt_hash": "9174e34c1b67e246a67144e35bb94e48", + "token_usage": { + "input_tokens": 637, + "output_tokens": 849, + "total_tokens": 1486 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/926f094d2428a4cbfd5933b4669aca5f.json b/.litho/cache/ai_code_insight/926f094d2428a4cbfd5933b4669aca5f.json new file mode 100644 index 0000000..f09055a --- /dev/null +++ b/.litho/cache/ai_code_insight/926f094d2428a4cbfd5933b4669aca5f.json @@ -0,0 +1,228 @@ +{ + "data": { + "code_dossier": { + "name": "baidu.rs", + "file_path": "crates/scrap/src/search/baidu.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "百度搜索引擎结果抓取与内容提取组件,支持关键词搜索、时间范围过滤和文章正文抽取", + "functions": [ + "new", + "prepare_target_sources", + "convert", + "search_by_words", + "adjust_date_str" + ], + "interfaces": [ + "IProvider" + ] + }, + "detailed_description": "该组件实现了针对百度搜索结果页的爬虫功能,通过CSS选择器解析HTML结构提取文章标题、链接、发布时间等元信息,并进一步调用文章阅读器获取正文内容。支持按关键词搜索和最近7天的时间范围筛选,使用reqwest进行HTTP请求,scraper进行HTML解析,chrono处理日期转换。", + "responsibilities": [ + "解析百度搜索结果页面的HTML结构并提取文章元数据", + "将相对模糊的发布日期(如'3天前')转换为标准日期格式", + "通过外部文章阅读器获取目标网页的正文内容", + "实现IProvider接口提供统一的搜索服务契约", + "管理HTTP客户端配置和请求参数构造" + ], + "interfaces": [ + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "搜索服务提供者接口,定义了通用的搜索方法契约" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "语言模型分段配置" + } + ], + "return_type": "anyhow::Result", + "description": "创建百度搜索提供者实例" + }, + { + "name": "search_by_words", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "搜索关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri应用上下文句柄" + } + ], + "return_type": "anyhow::Result>", + "description": "执行关键词搜索并返回文章列表" + }, + { + "name": "prepare_target_sources", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "&str", + "is_optional": false, + "description": "原始HTML文本" + } + ], + "return_type": "anyhow::Result>", + "description": "从HTML中提取文章元数据" + }, + { + "name": "convert", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "html_text", + "param_type": "String", + "is_optional": false, + "description": "HTML文本" + } + ], + "return_type": "anyhow::Result>", + "description": "转换搜索结果并获取文章内容" + }, + { + "name": "adjust_date_str", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "lossy_date_str", + "param_type": "String", + "is_optional": false, + "description": "原始日期字符串" + } + ], + "return_type": "String", + "description": "标准化日期字符串格式" + } + ], + "dependencies": [ + { + "name": "chrono", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "external", + "version": null + }, + { + "name": "reqwest", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "external", + "version": null + }, + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "external", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "external", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 6, + "dependency_type": "external", + "version": null + }, + { + "name": "types", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "internal", + "version": null + }, + { + "name": "crate::connector", + "path": null, + "is_external": false, + "line_number": 9, + "dependency_type": "internal", + "version": null + }, + { + "name": "crate::search::types", + "path": null, + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + }, + { + "name": "crate::search::utils", + "path": null, + "is_external": false, + "line_number": 11, + "dependency_type": "internal", + "version": null + }, + { + "name": "crate::simulator::scrap_text_by_url", + "path": null, + "is_external": false, + "line_number": 12, + "dependency_type": "internal", + "version": null + }, + { + "name": "crate::article_reader", + "path": null, + "is_external": false, + "line_number": 13, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 12.0, + "lines_of_code": 181, + "number_of_functions": 5, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.61, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024367, + "prompt_hash": "926f094d2428a4cbfd5933b4669aca5f", + "token_usage": { + "input_tokens": 2238, + "output_tokens": 1336, + "total_tokens": 3574 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9276c0d8316c8c6f81690e015657645f.json b/.litho/cache/ai_code_insight/9276c0d8316c8c6f81690e015657645f.json new file mode 100644 index 0000000..af417a1 --- /dev/null +++ b/.litho/cache/ai_code_insight/9276c0d8316c8c6f81690e015657645f.json @@ -0,0 +1,184 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/feed_api_rs/src/startup/mod.rs", + "code_purpose": "other", + "importance_score": 0.8, + "description": "应用启动初始化模块,负责协调Tiger0和Tiger1阶段的组件初始化,包括配置、日志、用户档案和LLM服务。", + "functions": [ + "tiger0_1", + "tiger2", + "launch" + ], + "interfaces": [ + "Startup", + "ContextHost" + ] + }, + "detailed_description": "该组件是应用的启动协调器,实现两阶段初始化策略:Tiger0为必须同步初始化的核心配置与日志,Tiger1为可并行初始化的用户配置与依赖服务(如LLM)。通过tokio::join!并发执行init_user_profile和init_llm以提升启动性能。实现了ContextHost trait以管理ApplicationContext生命周期,并提供了launch入口方法。Tiger2阶段被预留用于延迟初始化。", + "responsibilities": [ + "协调应用启动时序,执行Tiger0/Tiger1阶段初始化", + "并发初始化用户配置与LLM依赖服务", + "管理ApplicationContext的创建与传递", + "提供统一的启动入口点(launch)", + "处理启动过程中的错误并记录日志" + ], + "interfaces": [ + { + "name": "Startup", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "应用启动上下文容器,持有ApplicationContext实例。" + }, + { + "name": "ContextHost", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义上下文宿主行为的标准接口,被Startup实现。" + }, + { + "name": "launch", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result", + "description": "异步启动方法,构建并返回初始化完成的Startup实例。" + }, + { + "name": "tiger0_1", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result", + "description": "执行Tiger0(同步)和Tiger1(并发)阶段的初始化逻辑,返回构建的ApplicationContext。" + }, + { + "name": "tiger2", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "_context", + "param_type": "ApplicationContext", + "is_optional": false, + "description": "传入的上下文对象,当前未使用" + } + ], + "return_type": "anyhow::Result", + "description": "预留的Tiger2延迟初始化函数,当前为todo状态。" + } + ], + "dependencies": [ + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "logging", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "error_handling", + "version": null + }, + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 27, + "dependency_type": "runtime", + "version": null + }, + { + "name": "types", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": null, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "init_app_config", + "path": "crates/feed_api_rs/src/startup/init_app_config", + "is_external": false, + "line_number": null, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "init_logger", + "path": "crates/feed_api_rs/src/startup/init_logger", + "is_external": false, + "line_number": null, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "init_llm", + "path": "crates/feed_api_rs/src/startup/init_llm", + "is_external": false, + "line_number": null, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "init_user_profile", + "path": "crates/feed_api_rs/src/startup/init_user_profile", + "is_external": false, + "line_number": null, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "task", + "path": "crates/feed_api_rs/src/startup/task", + "is_external": false, + "line_number": null, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "ApplicationContext", + "path": "crates/feed_api_rs/src/application_context/ApplicationContext", + "is_external": false, + "line_number": 3, + "dependency_type": "data_model", + "version": null + }, + { + "name": "ContextHost", + "path": "crates/feed_api_rs/src/application_context/ContextHost", + "is_external": false, + "line_number": 3, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 72, + "number_of_functions": 3, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.65, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805357, + "prompt_hash": "9276c0d8316c8c6f81690e015657645f", + "token_usage": { + "input_tokens": 1263, + "output_tokens": 1242, + "total_tokens": 2505 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/929c919b226f8b99be92fee0aa9a04f2.json b/.litho/cache/ai_code_insight/929c919b226f8b99be92fee0aa9a04f2.json new file mode 100644 index 0000000..ffe92c7 --- /dev/null +++ b/.litho/cache/ai_code_insight/929c919b226f8b99be92fee0aa9a04f2.json @@ -0,0 +1,73 @@ +{ + "data": { + "code_dossier": { + "name": "vite.config.ts", + "file_path": "app/vite.config.ts", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Vite 构建工具的配置文件,用于 SvelteKit 应用的开发和构建设置", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是 Vite 的配置文件,主要用于配置 SvelteKit 项目的构建和开发服务器行为。它定义了插件加载顺序(Tailwind CSS、Sentry 错误追踪、SvelteKit 集成),并针对 Tauri 桌面应用开发环境进行了定制化设置,包括固定端口、HMR 配置以及对 src-tauri 目录的监听忽略。同时排除了 fsevents 的依赖优化以避免原生模块问题。", + "responsibilities": [ + "配置 Vite 构建工具的核心行为", + "集成前端框架和第三方插件(Tailwind、Sentry、SvelteKit)", + "为 Tauri 桌面应用开发提供专用服务器设置", + "管理开发服务器的热更新和端口绑定策略", + "优化依赖处理以兼容原生环境" + ], + "interfaces": [], + "dependencies": [ + { + "name": "vite", + "path": "vite", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "@tailwindcss/vite", + "path": "@tailwindcss/vite", + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": "@sentry/sveltekit", + "is_external": true, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "@sveltejs/kit/vite", + "path": "@sveltejs/kit/vite", + "is_external": true, + "line_number": 4, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 47, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.085, + "cohesion_score": 0.92 + } + }, + "timestamp": 1758805840, + "prompt_hash": "929c919b226f8b99be92fee0aa9a04f2", + "token_usage": { + "input_tokens": 707, + "output_tokens": 563, + "total_tokens": 1270 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/940af1e923133707481c6b68a66b7748.json b/.litho/cache/ai_code_insight/940af1e923133707481c6b68a66b7748.json new file mode 100644 index 0000000..d7d9a54 --- /dev/null +++ b/.litho/cache/ai_code_insight/940af1e923133707481c6b68a66b7748.json @@ -0,0 +1,51 @@ +{ + "data": { + "code_dossier": { + "name": "settings.ts", + "file_path": "app/src/lib/windows/settings.ts", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "负责管理设置窗口的打开行为,封装了窗口配置参数并调用单例模式展示窗口。", + "functions": [ + "open" + ], + "interfaces": [] + }, + "detailed_description": "该组件定义了一个异步函数 open,用于打开名为 'settings' 的应用设置窗口。通过导入并调用 showWindowSingleton 工具函数,传入窗口标识、URL 路径及一系列窗口属性(如标题、尺寸、居中显示、不可调整大小和不可最大化),实现统一且受控的窗口展示逻辑。此模块作为配置与行为的桥梁,将窗口的视觉和交互特性集中声明。", + "responsibilities": [ + "封装设置窗口的打开逻辑", + "定义设置窗口的UI配置参数(尺寸、标题、可调整性等)", + "利用单例模式确保设置窗口唯一实例", + "协调窗口系统与具体业务需求之间的交互" + ], + "interfaces": [], + "dependencies": [ + { + "name": "showWindowSingleton", + "path": "./utils", + "is_external": false, + "line_number": 1, + "dependency_type": "function", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 14, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024698, + "prompt_hash": "940af1e923133707481c6b68a66b7748", + "token_usage": { + "input_tokens": 477, + "output_tokens": 488, + "total_tokens": 965 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/952149d754cc18b71a69052679087887.json b/.litho/cache/ai_code_insight/952149d754cc18b71a69052679087887.json new file mode 100644 index 0000000..e309ca3 --- /dev/null +++ b/.litho/cache/ai_code_insight/952149d754cc18b71a69052679087887.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "capabilities.json", + "file_path": "app/src-tauri/gen/schemas/capabilities.json", + "code_purpose": "config", + "importance_score": 0.6, + "description": "定义应用中不同能力(Capability)的配置,包括权限、窗口访问控制和平台限制。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个JSON配置文件,用于定义Tauri桌面应用中的能力系统(Capabilities)。每个能力包含标识符、描述、本地/远程属性、关联窗口、支持的平台以及授予的权限列表。核心功能是通过声明式方式管理应用的功能权限,实现细粒度的安全控制。例如,'default'能力为默认主窗口提供基础UI和系统交互权限,而'scrap-host-capability'则专用于Scrap WebHost模块,限制其仅在特定窗口运行并赋予最小必要权限。", + "responsibilities": [ + "定义和组织应用的能力与权限映射", + "实现基于能力的安全模型以隔离功能模块", + "控制各能力可访问的应用窗口范围", + "指定能力适用的平台限制(如仅桌面)", + "为远程内容(如Web视图)提供安全的权限配置" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805947, + "prompt_hash": "952149d754cc18b71a69052679087887", + "token_usage": { + "input_tokens": 755, + "output_tokens": 514, + "total_tokens": 1269 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9656ab0f2459c9bb839eb71bda5afab3.json b/.litho/cache/ai_code_insight/9656ab0f2459c9bb839eb71bda5afab3.json new file mode 100644 index 0000000..160c905 --- /dev/null +++ b/.litho/cache/ai_code_insight/9656ab0f2459c9bb839eb71bda5afab3.json @@ -0,0 +1,97 @@ +{ + "data": { + "code_dossier": { + "name": "utils.rs", + "file_path": "crates/feed_api_rs/src/utils.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供异步任务并行执行的限流控制工具函数,确保在指定并发数限制下安全地执行多个Future。", + "functions": [ + "do_parallel_with_limit" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了`do_parallel_with_limit`异步函数,用于在最大并发数限制下并行执行一组Future任务。通过使用Tokio的Semaphore(信号量)机制,每个任务在执行前需获取一个许可,从而实现对并发数量的精确控制。当max_concurrent为0时,默认设为1以防止无效配置。此功能适用于需要避免资源过载的高并发场景,如批量网络请求处理。", + "responsibilities": [ + "管理异步任务的并发执行数量", + "防止系统资源因过多并发任务而耗尽", + "封装复杂的并发控制逻辑,提供简洁易用的API", + "支持调试模式下的执行状态输出" + ], + "interfaces": [ + { + "name": "do_parallel_with_limit", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "futures", + "param_type": "Vec", + "is_optional": false, + "description": "待执行的异步任务列表" + }, + { + "name": "max_concurrent", + "param_type": "usize", + "is_optional": false, + "description": "最大允许的并发任务数,0将被自动修正为1" + } + ], + "return_type": "Vec", + "description": "返回所有任务完成后的结果向量" + } + ], + "dependencies": [ + { + "name": "std::future::Future", + "path": "std::future::Future", + "is_external": false, + "line_number": 1, + "dependency_type": "trait", + "version": null + }, + { + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "is_external": false, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "futures::future::join_all", + "path": "futures::future::join_all", + "is_external": true, + "line_number": 3, + "dependency_type": "function", + "version": null + }, + { + "name": "tokio::sync::Semaphore", + "path": "tokio::sync::Semaphore", + "is_external": true, + "line_number": 4, + "dependency_type": "struct", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 29, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 4.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024599, + "prompt_hash": "9656ab0f2459c9bb839eb71bda5afab3", + "token_usage": { + "input_tokens": 627, + "output_tokens": 736, + "total_tokens": 1363 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/96d870b1a6b442d8bb70d367b08083e0.json b/.litho/cache/ai_code_insight/96d870b1a6b442d8bb70d367b08083e0.json new file mode 100644 index 0000000..eb6a004 --- /dev/null +++ b/.litho/cache/ai_code_insight/96d870b1a6b442d8bb70d367b08083e0.json @@ -0,0 +1,107 @@ +{ + "data": { + "code_dossier": { + "name": "tray.rs", + "file_path": "app/src-tauri/src/tray.rs", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "系统托盘图标管理组件,负责创建和管理桌面应用的托盘菜单及窗口控制逻辑。", + "functions": [ + "create_tray", + "open_main_window", + "bring_to_front" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了Tauri桌面应用的系统托盘功能。主要功能包括:创建带有自定义菜单项的托盘图标(显示主窗口、网络信息、关于、退出程序),处理菜单点击事件以打开或聚焦不同类型的窗口(主窗口、外部端点信息窗口、关于窗口),并通过双击托盘图标快速打开主窗口。组件使用了条件编译来适配macOS平台的菜单点击行为差异。所有窗口配置(标签、标题、URL等)通过常量模块注入,增强了可维护性。", + "responsibilities": [ + "创建并初始化系统托盘图标及其上下文菜单", + "响应托盘菜单项的点击事件以控制应用程序窗口", + "管理多个Webview窗口的打开与聚焦行为", + "实现跨平台兼容的托盘交互逻辑(特别是macOS左键点击菜单支持)", + "封装窗口焦点恢复的通用操作" + ], + "interfaces": [ + { + "name": "create_tray", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "app", + "param_type": "tauri::AppHandle", + "is_optional": false, + "description": "Tauri应用句柄引用" + } + ], + "return_type": "tauri::Result<()>", + "description": "创建系统托盘并注册事件处理器" + }, + { + "name": "open_main_window", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "app", + "param_type": "tauri::AppHandle", + "is_optional": false, + "description": "Tauri应用句柄引用" + } + ], + "return_type": null, + "description": "打开或聚焦主窗口" + }, + { + "name": "bring_to_front", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "window", + "param_type": "WebviewWindow", + "is_optional": false, + "description": "要前置的Webview窗口实例" + } + ], + "return_type": null, + "description": "将指定窗口恢复到前台显示" + } + ], + "dependencies": [ + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + }, + { + "name": "crate::constrant", + "path": "app/src-tauri/src/constrant.rs", + "is_external": false, + "line_number": 9, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 8.0, + "lines_of_code": 119, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805667, + "prompt_hash": "96d870b1a6b442d8bb70d367b08083e0", + "token_usage": { + "input_tokens": 1524, + "output_tokens": 869, + "total_tokens": 2393 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9a0c0aea81cc72cc13d6b8d1b3f1cce5.json b/.litho/cache/ai_code_insight/9a0c0aea81cc72cc13d6b8d1b3f1cce5.json new file mode 100644 index 0000000..fc75c3d --- /dev/null +++ b/.litho/cache/ai_code_insight/9a0c0aea81cc72cc13d6b8d1b3f1cce5.json @@ -0,0 +1,70 @@ +{ + "data": { + "code_dossier": { + "name": "dom.ts", + "file_path": "app/src/lib/utils/dom.ts", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供DOM操作相关的工具函数,用于禁用右键菜单和监听元素可见性变化。", + "functions": [ + "disableContextMenu", + "observeVisiblity" + ], + "interfaces": [ + "ObserveVisiblityOption" + ] + }, + "detailed_description": "该组件包含两个核心工具函数:`disableContextMenu`用于在浏览器环境中禁用指定节点的上下文菜单(右键菜单),但允许输入框等表单元素保留默认行为;`observeVisiblity`利用IntersectionObserver API监听页面元素的可见状态变化,并通过回调通知。这两个函数均返回Svelte风格的销毁对象,便于在组件生命周期中清理事件监听或观察器。", + "responsibilities": [ + "禁用非输入元素的右键上下文菜单", + "监听DOM元素的可视状态变化", + "提供可销毁的DOM行为绑定机制", + "适配Svelte运行时环境(通过$env判断)" + ], + "interfaces": [ + { + "name": "ObserveVisiblityOption", + "interface_type": "type", + "visibility": "exported", + "parameters": [ + { + "name": "callback", + "param_type": "(v: boolean) => void", + "is_optional": false, + "description": "当元素可见性发生变化时调用的回调函数,参数为boolean表示是否可见" + } + ], + "return_type": null, + "description": "定义observeVisiblity函数所需的配置选项结构" + } + ], + "dependencies": [ + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 46, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024690, + "prompt_hash": "9a0c0aea81cc72cc13d6b8d1b3f1cce5", + "token_usage": { + "input_tokens": 642, + "output_tokens": 597, + "total_tokens": 1239 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9a8a579a07ccbdfaca7eeda797409138.json b/.litho/cache/ai_code_insight/9a8a579a07ccbdfaca7eeda797409138.json new file mode 100644 index 0000000..a4e073f --- /dev/null +++ b/.litho/cache/ai_code_insight/9a8a579a07ccbdfaca7eeda797409138.json @@ -0,0 +1,187 @@ +{ + "data": { + "code_dossier": { + "name": "article_recorder_service.rs", + "file_path": "crates/recorder/src/article_recorder_service.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "文章记录服务,负责对文章记录进行增删改查、状态管理及搜索等业务操作。", + "functions": [ + "initialize", + "update_content", + "insert", + "exists_by_source", + "query_backward", + "query_favorite", + "query_unread", + "query_backward_in_duration", + "count", + "mark_as_read", + "set_favorite", + "query_by_id", + "dispose", + "search_contents_by_keyword" + ], + "interfaces": [ + "ArticleRecorderService" + ] + }, + "detailed_description": "该组件是文章记录的核心服务层实现,封装了对文章记录(Model)的各类数据访问逻辑。它通过依赖 Operator 操作底层数据库,实现了初始化、插入、更新、查询(按分组、收藏、未读、时间范围等)、标记已读、设置收藏、关键词搜索等功能。其主要职责集中在文章记录的生命周期管理与状态变更控制,是连接上层业务逻辑与底层数据存储的关键中介。", + "responsibilities": [ + "管理文章记录的持久化操作(增删改查)", + "维护文章记录的状态(已读/未读、收藏)", + "提供多维度的文章查询接口(按时间、收藏、未读、关键词等)", + "确保数据一致性(如插入时去重逻辑)" + ], + "interfaces": [ + { + "name": "ArticleRecorderService", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "文章记录服务的主要结构体,包含Operator用于执行数据库操作。" + }, + { + "name": "initialize", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result<()>", + "description": "初始化服务及其依赖的Operator。" + }, + { + "name": "update_content", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "record", + "param_type": "Model", + "is_optional": false, + "description": "需要更新的文章记录" + }, + { + "name": "purged_content", + "param_type": "String", + "is_optional": false, + "description": "清洗后的内容" + }, + { + "name": "optimized_content", + "param_type": "String", + "is_optional": false, + "description": "优化后的内容" + }, + { + "name": "melted_content", + "param_type": "String", + "is_optional": false, + "description": "融合后的内容" + } + ], + "return_type": "anyhow::Result", + "description": "更新指定记录的三种内容字段。" + }, + { + "name": "insert", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "records", + "param_type": "Vec", + "is_optional": false, + "description": "待插入的文章记录列表" + } + ], + "return_type": "anyhow::Result", + "description": "批量插入文章记录,自动处理重复链接:删除已读的重复项,跳过未读的重复项。" + } + ], + "dependencies": [ + { + "name": "chrono::NaiveDate", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::ColumnTrait", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::Condition", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::IntoActiveModel", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::ActiveValue::Set", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "sea_orm::prelude::Expr", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::entity::article_record", + "path": "./crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::operator::Operator", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 9.0, + "lines_of_code": 157, + "number_of_functions": 18, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.4667, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024392, + "prompt_hash": "9a8a579a07ccbdfaca7eeda797409138", + "token_usage": { + "input_tokens": 2194, + "output_tokens": 1228, + "total_tokens": 3422 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9afcc0a2aad7ba144d9071852e12dac1.json b/.litho/cache/ai_code_insight/9afcc0a2aad7ba144d9071852e12dac1.json new file mode 100644 index 0000000..00d7d44 --- /dev/null +++ b/.litho/cache/ai_code_insight/9afcc0a2aad7ba144d9071852e12dac1.json @@ -0,0 +1,74 @@ +{ + "data": { + "code_dossier": { + "name": "vite.config.ts", + "file_path": "app/vite.config.ts", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Vite构建工具的配置文件,用于SvelteKit应用的开发和构建设置", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是Vite构建系统的配置文件,专为SvelteKit框架设计。它定义了开发服务器行为、插件集成(Tailwind CSS、Sentry错误监控、SvelteKit支持)、热更新机制以及针对Tauri桌面应用环境的特殊配置。通过异步方式导出配置对象,支持条件性地根据TAURI_DEV_HOST环境变量调整HMR连接协议和主机地址。同时排除了fsevents依赖的预优化,避免在非macOS系统上出现问题。", + "responsibilities": [ + "配置Vite开发服务器端口及HMR热重载行为", + "集成Tailwind CSS、Sentry和SvelteKit等核心构建插件", + "适配Tauri桌面应用的开发环境需求", + "优化依赖处理以提升构建性能", + "管理环境变量驱动的条件性配置逻辑" + ], + "interfaces": [], + "dependencies": [ + { + "name": "vite", + "path": "vite", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "@tailwindcss/vite", + "path": "@tailwindcss/vite", + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": "@sentry/sveltekit", + "is_external": true, + "line_number": 3, + "dependency_type": "@sentry/sveltekit", + "version": null + }, + { + "name": "@sveltejs/kit/vite", + "path": "@sveltejs/kit/vite", + "is_external": true, + "line_number": 4, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 47, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.72 + } + }, + "timestamp": 1759024555, + "prompt_hash": "9afcc0a2aad7ba144d9071852e12dac1", + "token_usage": { + "input_tokens": 715, + "output_tokens": 591, + "total_tokens": 1306 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9b2b0d80cfc15c7bc59ad686a9e90723.json b/.litho/cache/ai_code_insight/9b2b0d80cfc15c7bc59ad686a9e90723.json new file mode 100644 index 0000000..492d907 --- /dev/null +++ b/.litho/cache/ai_code_insight/9b2b0d80cfc15c7bc59ad686a9e90723.json @@ -0,0 +1,73 @@ +{ + "data": { + "code_dossier": { + "name": "context.ts", + "file_path": "app/src/routes/main/stores/context.ts", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.8, + "description": "定义了应用上下文的状态结构,用于在Svelte组件之间共享当前选中的Feed和文章信息。", + "functions": [], + "interfaces": [ + "IContext" + ] + }, + "detailed_description": "该组件定义了一个名为 IContext 的接口,用于描述应用程序的全局状态上下文。它包含两个字段:currentFeedId(表示当前激活的订阅源ID,可选)和 currentArticle(表示当前查看的文章内容,可为 null)。此类型主要用于 Svelte 的 context API 中,以便在嵌套组件树中安全地传递状态,避免通过 props 层层透传。该文件仅提供类型定义,不包含运行时逻辑,属于纯类型声明模块。", + "responsibilities": [ + "定义应用级上下文的数据结构", + "提供跨组件通信的类型安全支持", + "管理当前 Feed 和文章的引用状态", + "支持 Svelte Context API 的类型推导" + ], + "interfaces": [ + { + "name": "IContext", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "currentFeedId", + "param_type": "string | undefined", + "is_optional": false, + "description": "当前选中的 Feed 的唯一标识符,可能未设置" + }, + { + "name": "currentArticle", + "param_type": "Article | null", + "is_optional": false, + "description": "当前显示的文章对象,若无则为 null" + } + ], + "return_type": null, + "description": "描述主界面中组件共享的状态上下文结构" + } + ], + "dependencies": [ + { + "name": "$lib/types/article", + "path": "app/src/lib/types/article", + "is_external": false, + "line_number": 1, + "dependency_type": "type import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 8, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024531, + "prompt_hash": "9b2b0d80cfc15c7bc59ad686a9e90723", + "token_usage": { + "input_tokens": 452, + "output_tokens": 643, + "total_tokens": 1095 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9cab669aef6cb0d35df819fd0dfd920b.json b/.litho/cache/ai_code_insight/9cab669aef6cb0d35df819fd0dfd920b.json new file mode 100644 index 0000000..52f49be --- /dev/null +++ b/.litho/cache/ai_code_insight/9cab669aef6cb0d35df819fd0dfd920b.json @@ -0,0 +1,51 @@ +{ + "data": { + "code_dossier": { + "name": "settings.ts", + "file_path": "app/src/lib/i18n/settings.ts", + "code_purpose": "config", + "importance_score": 0.6, + "description": "国际化配置模块,负责管理应用的区域设置(locale),提供默认和备用语言配置,并根据运行环境获取当前浏览器的语言设置。", + "functions": [ + "getLocale", + "setLocale" + ], + "interfaces": [] + }, + "detailed_description": "该组件是i18n系统的基础配置模块,定义了默认语言(zh)和备用语言(en)常量。其核心功能是通过`getLocale`函数检测执行环境(浏览器或服务端)并返回相应的语言标识:在浏览器中读取`window.navigator.language`,在服务端则返回默认中文。`setLocale`函数目前为空实现,预留用于动态切换语言的功能扩展。整体设计简洁,专注于语言环境的初始化逻辑。", + "responsibilities": [ + "定义国际化系统的默认和备用语言", + "根据执行环境安全地获取当前用户语言偏好", + "提供语言设置的基础接口供上层模块调用", + "隔离浏览器API与服务端环境的差异" + ], + "interfaces": [], + "dependencies": [ + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": false, + "line_number": 1, + "dependency_type": "module-import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 12, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758806009, + "prompt_hash": "9cab669aef6cb0d35df819fd0dfd920b", + "token_usage": { + "input_tokens": 466, + "output_tokens": 527, + "total_tokens": 993 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/9f00aa53bb19aeddcfc6da8590973776.json b/.litho/cache/ai_code_insight/9f00aa53bb19aeddcfc6da8590973776.json new file mode 100644 index 0000000..e8e065e --- /dev/null +++ b/.litho/cache/ai_code_insight/9f00aa53bb19aeddcfc6da8590973776.json @@ -0,0 +1,108 @@ +{ + "data": { + "code_dossier": { + "name": "feeds_update.rs", + "file_path": "app/src-tauri/src/daemon/feeds_update.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "负责定时拉取并更新订阅源内容的后台守护进程组件,通过锁机制防止重复执行。", + "functions": [ + "launch_feeds_schedule_update", + "schedule_loop" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了一个后台定时任务代理(Agent),用于周期性地更新应用程序中的订阅源内容。它首先尝试获取一个文件锁以确保同一时间只有一个更新实例在运行,避免资源竞争和重复操作。一旦获得锁,便会启动一个异步循环,根据应用配置中设定的频率(每1小时或3小时)触发更新流程。在每次更新时,遍历所有已注册的订阅包及其下的订阅项,并调用 FeaturesAPI 来更新每个订阅的内容。更新过程中会传递 AppHandle 实例以便必要时通知前端或其他模块。成功或失败均会记录日志,便于监控与调试。", + "responsibilities": [ + "管理订阅内容的周期性自动更新任务调度", + "通过文件锁机制防止多个更新实例并发执行", + "调用 FeaturesAPI 执行具体的订阅内容拉取与更新逻辑", + "根据应用配置动态调整更新频率", + "记录关键操作日志以支持运行时监控与问题排查" + ], + "interfaces": [], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "is_external": false, + "line_number": null, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "feed_api_rs::features::api::FeaturesAPI", + "path": "feed_api_rs::features::api::FeaturesAPI", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "fslock::LockFile", + "path": "fslock::LockFile", + "is_external": true, + "line_number": null, + "dependency_type": "library", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": null, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": "tauri", + "is_external": true, + "line_number": null, + "dependency_type": "framework", + "version": null + }, + { + "name": "tauri_plugin_feed_api::state::HybridRuntimeState", + "path": "tauri_plugin_feed_api::state::HybridRuntimeState", + "is_external": true, + "line_number": null, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tokio::time", + "path": "tokio::time", + "is_external": true, + "line_number": null, + "dependency_type": "runtime", + "version": null + }, + { + "name": "crate::daemon::locks", + "path": "crate::daemon::locks", + "is_external": false, + "line_number": null, + "dependency_type": "local_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 69, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.875, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758805684, + "prompt_hash": "9f00aa53bb19aeddcfc6da8590973776", + "token_usage": { + "input_tokens": 1018, + "output_tokens": 912, + "total_tokens": 1930 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a23fc67512b17b1feac5985b9692a7f2.json b/.litho/cache/ai_code_insight/a23fc67512b17b1feac5985b9692a7f2.json new file mode 100644 index 0000000..d57be38 --- /dev/null +++ b/.litho/cache/ai_code_insight/a23fc67512b17b1feac5985b9692a7f2.json @@ -0,0 +1,182 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/settings/+page.svelte", + "code_purpose": "config", + "importance_score": 0.8, + "description": "应用程序设置页面,提供主题、LLM提供商配置、应用行为等全局配置功能", + "functions": [ + "switchTheme", + "selectLang", + "onAutoStartUpSwitched", + "onFrequencyUpdateSwitched", + "openGLMGuide", + "afterAppConfigUpdated", + "createSaveLLMFormAction", + "createLLMSwitcherAction", + "saveLLMFormOllama", + "restoreLLMFormOllama", + "saveLLMFormGLM", + "restoreLLMFormGLM", + "saveLLMFormOpenAILike", + "restoreLLMFormOpenAILike", + "saveLLMFormPlatform", + "restoreLLMFormPlatform" + ], + "interfaces": [ + "PressedHandler", + "CheckSwitchedHandler", + "SelectionSelectedHandler" + ] + }, + "detailed_description": "该组件是应用程序的设置中心页面,负责管理多种全局配置。它通过Tauri API获取系统信息,并与hybrid-apis进行交互来持久化存储配置。组件实现了主题切换、多LLM提供商配置(Ollama、GLM、OpenAI兼容、平台内置)、语言偏好设置以及应用行为控制(自动启动、后台更新频率)等功能。UI采用Svelte的snippet机制组织可复用的界面元素,如开关选项、选择器和保存面板。", + "responsibilities": [ + "管理应用程序的全局配置状态", + "提供用户友好的界面以配置不同的LLM服务提供商", + "处理主题切换和语言偏好设置", + "展示系统和应用版本信息", + "协调前端表单状态与后端持久化配置的同步" + ], + "interfaces": [ + { + "name": "PressedHandler", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "按钮按下事件处理器类型定义" + }, + { + "name": "CheckSwitchedHandler", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "复选框切换事件处理器类型定义" + }, + { + "name": "SelectionSelectedHandler", + "interface_type": "type", + "visibility": "private", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "选择项变更事件处理器类型定义" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$app/environment", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "@tauri-apps/api/app", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "native-api", + "version": null + }, + { + "name": "@tauri-apps/plugin-os", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "native-plugin", + "version": null + }, + { + "name": "@tauri-apps/plugin-autostart", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "native-plugin", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 6, + "dependency_type": "internal-api", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 7, + "dependency_type": "utility", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 8, + "dependency_type": "ui-component", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 9, + "dependency_type": "internal-type", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 10, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/themes", + "path": "$lib/themes", + "is_external": false, + "line_number": 11, + "dependency_type": "theme", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 33.0, + "lines_of_code": 653, + "number_of_functions": 18, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.45, + "cohesion_score": 0.65 + } + }, + "timestamp": 1758805779, + "prompt_hash": "a23fc67512b17b1feac5985b9692a7f2", + "token_usage": { + "input_tokens": 6032, + "output_tokens": 1126, + "total_tokens": 7158 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a400b5d729bb04c7cd24a67f7eb77cee.json b/.litho/cache/ai_code_insight/a400b5d729bb04c7cd24a67f7eb77cee.json new file mode 100644 index 0000000..df166ac --- /dev/null +++ b/.litho/cache/ai_code_insight/a400b5d729bb04c7cd24a67f7eb77cee.json @@ -0,0 +1,121 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/feed_api_rs/src/startup/mod.rs", + "source_summary": "", + "code_purpose": "other", + "importance_score": 0.8, + "description": "应用启动模块,负责初始化核心组件并构建应用上下文。实现分阶段(Tiger0/1/2)的启动流程控制。", + "functions": [ + "tiger0_1", + "tiger2", + "launch" + ], + "interfaces": [ + "Startup", + "ContextHost" + ] + }, + "detailed_description": "该组件是应用程序的启动中枢,采用分阶段策略进行初始化:Tiger0_1同步初始化关键配置和日志系统,随后并行初始化用户配置与LLM服务依赖。通过`tokio::join!`实现并发加载以提升启动效率,并具备错误聚合处理机制。支持延迟初始化(Tiger2预留接口),体现阶段性启动设计思想。实现了`ContextHost` trait以统一管理`ApplicationContext`的生命周期。", + "responsibilities": [ + "协调应用启动时的核心组件初始化顺序", + "实现Tiger0/Tiger1阶段的同步与并发初始化逻辑", + "构建并返回完整的应用上下文(ApplicationContext)", + "提供结构化的启动日志与错误报告机制", + "实现ContextHost接口以支持上下文传递" + ], + "interfaces": [ + { + "name": "Startup", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "应用启动器主结构体,持有应用上下文实例" + }, + { + "name": "ContextHost", + "interface_type": "trait", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "上下文宿主接口,定义了上下文获取与克隆的标准方法" + }, + { + "name": "launch", + "interface_type": "function", + "visibility": "pub", + "parameters": [], + "return_type": "anyhow::Result", + "description": "异步启动入口点,执行初始化并返回启动器实例" + }, + { + "name": "tiger0_1", + "interface_type": "function", + "visibility": "pub", + "parameters": [], + "return_type": "anyhow::Result", + "description": "执行Tiger0/Tiger1阶段的初始化工作,包括配置、日志、用户数据和LLM服务" + }, + { + "name": "tiger2", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "_context", + "param_type": "ApplicationContext", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "预留的延迟初始化接口,用于Tiger2阶段的异步任务" + } + ], + "dependencies": [ + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "logging", + "version": null + }, + { + "name": "crate::application_context", + "path": "crates/feed_api_rs/src/application_context", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "types", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 9, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 72, + "number_of_functions": 3, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.45, + "cohesion_score": 0.88 + } + }, + "timestamp": 1759024312, + "prompt_hash": "a400b5d729bb04c7cd24a67f7eb77cee", + "token_usage": { + "input_tokens": 1272, + "output_tokens": 963, + "total_tokens": 2235 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a5c496dda132677abe0eb636ac9cfe0d.json b/.litho/cache/ai_code_insight/a5c496dda132677abe0eb636ac9cfe0d.json new file mode 100644 index 0000000..589b581 --- /dev/null +++ b/.litho/cache/ai_code_insight/a5c496dda132677abe0eb636ac9cfe0d.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/index.ts", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个空的入口文件,当前仅包含一条注释,说明其用途是存放通过 `$lib` 别名导入的文件。它本身不导出任何功能或模块,也没有实现具体逻辑。", + "responsibilities": [ + "作为项目中 `@lib` 别名指向的入口目录索引", + "组织和集中管理共享库代码的导出(未来潜在职责)", + "提供可扩展的模块导入机制供其他部分引用" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024451, + "prompt_hash": "a5c496dda132677abe0eb636ac9cfe0d", + "token_usage": { + "input_tokens": 426, + "output_tokens": 295, + "total_tokens": 721 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a637c5b39416f4ebdd06177531cab86a.json b/.litho/cache/ai_code_insight/a637c5b39416f4ebdd06177531cab86a.json new file mode 100644 index 0000000..f847c9f --- /dev/null +++ b/.litho/cache/ai_code_insight/a637c5b39416f4ebdd06177531cab86a.json @@ -0,0 +1,313 @@ +{ + "data": { + "code_dossier": { + "name": "commands.rs", + "file_path": "crates/tauri-plugin-feed-api/src/commands.rs", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "Tauri 命令模块,提供与 RSS Feed 管理、文章内容抓取、AI 助手交互等核心功能的前端接口。封装了对 FeaturesAPI 的调用,并处理错误转换。", + "functions": [ + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "scrap_text_by_url", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "interfaces": [] + }, + "detailed_description": "该组件是 Tauri 框架下的后端命令控制器,负责暴露一系列异步命令供前端调用。其主要功能围绕 FeedsPackage(订阅包)和 Feed(订阅源)的增删改查(CRUD),以及文章内容的读取、标记已读、收藏、搜索等操作。同时,它集成了 AI 能力,支持通过 Ollama 启动本地大模型服务,并实现基于文章内容的智能问答(chat_with_article_assistant)。此外,组件还包含一个网页内容抓取机制(scrap_text_by_url),通过创建隐藏的 WebView 窗口加载目标 URL 并提取 HTML 内容,为后续的 AI 处理提供数据源。所有命令都通过 `convert_result` 函数将 `anyhow::Result` 统一转换为 `Result`,实现了错误处理的标准化。", + "responsibilities": [ + "提供RSS订阅管理的核心CRUD接口", + "协调前端请求与后端FeaturesAPI的交互", + "实现网页内容抓取以支持AI摘要和问答", + "集成并控制Ollama本地AI服务", + "统一处理后端服务调用的错误" + ], + "interfaces": [ + { + "name": "add_feeds_package", + "interface_type": "command", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "feeds_package", + "param_type": "FeedsPackage", + "is_optional": false, + "description": null + } + ], + "return_type": "Result<(), ()>", + "description": "添加一个新的订阅包" + }, + { + "name": "remove_feeds_package", + "interface_type": "command", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "Result<(), ()>", + "description": "根据ID移除一个订阅包" + }, + { + "name": "get_feeds_packages", + "interface_type": "command", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + } + ], + "return_type": "Result, ()>", + "description": "获取所有订阅包的列表" + }, + { + "name": "update_feed_contents", + "interface_type": "command", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "app_handle", + "param_type": "AppHandle", + "is_optional": false, + "description": null + }, + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "Result<(), ()>", + "description": "更新指定订阅源的内容" + }, + { + "name": "scrap_text_by_url", + "interface_type": "command", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "app_handle", + "param_type": "AppHandle", + "is_optional": false, + "description": null + }, + { + "name": "url", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "Result", + "description": "通过创建隐藏WebView抓取指定URL的完整HTML文本" + }, + { + "name": "chat_with_article_assistant", + "interface_type": "command", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "app_handle", + "param_type": "AppHandle", + "is_optional": false, + "description": null + }, + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "article_id", + "param_type": "i32", + "is_optional": false, + "description": null + }, + { + "name": "user_prompt", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "history", + "param_type": "Vec", + "is_optional": false, + "description": null + } + ], + "return_type": "Result", + "description": "与指定文章的AI助手进行对话" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "std", + "version": null + }, + { + "name": "spdlog::error", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "framework", + "version": null + }, + { + "name": "feed_api_rs::features::api::FeaturesAPI", + "path": "crates/feed-api-rs/src/features/api.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "internal_service", + "version": null + }, + { + "name": "ollama::ProgramStatus", + "path": null, + "is_external": true, + "line_number": 8, + "dependency_type": "ai_service", + "version": null + }, + { + "name": "recorder::entity::article_record::Model", + "path": null, + "is_external": true, + "line_number": 9, + "dependency_type": "data_model", + "version": null + }, + { + "name": "types::AppConfig", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "data_model", + "version": null + }, + { + "name": "types::ConversationMessage", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "data_model", + "version": null + }, + { + "name": "types::FeedTargetDescription", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "data_model", + "version": null + }, + { + "name": "types::FeedsPackage", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "data_model", + "version": null + }, + { + "name": "crate::scrap_host", + "path": "./crates/tauri-plugin-feed-api/src/scrap_host.rs", + "is_external": false, + "line_number": 13, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "crate::state::HybridRuntimeState", + "path": "./crates/tauri-plugin-feed-api/src/state.rs", + "is_external": false, + "line_number": 14, + "dependency_type": "internal_state", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 299, + "number_of_functions": 25, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.65, + "cohesion_score": 0.82 + } + }, + "timestamp": 1758805673, + "prompt_hash": "a637c5b39416f4ebdd06177531cab86a", + "token_usage": { + "input_tokens": 3178, + "output_tokens": 1857, + "total_tokens": 5035 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a6608f266c742be633a355cdfd2d3db7.json b/.litho/cache/ai_code_insight/a6608f266c742be633a355cdfd2d3db7.json new file mode 100644 index 0000000..c23e631 --- /dev/null +++ b/.litho/cache/ai_code_insight/a6608f266c742be633a355cdfd2d3db7.json @@ -0,0 +1,102 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/about/+page.svelte", + "code_purpose": "page", + "importance_score": 0.8, + "description": "关于页面组件,展示应用名称、版本信息及引擎版本,并提供访问官网按钮。使用Svelte状态管理与国际化支持。", + "functions": [ + "onVisitHome" + ], + "interfaces": [ + "disableContextMenu" + ] + }, + "detailed_description": "该组件为Tauri应用中的'关于'页面,负责展示应用的基本信息(如名称、版本)和底层运行时版本(Tauri引擎版本)。通过异步调用Tauri API获取本地应用元数据,并在浏览器环境中初始化显示。界面包含Logo展示、文本信息区和外部链接按钮。使用$state进行响应式状态管理,支持右键菜单禁用功能以提升桌面端用户体验。", + "responsibilities": [ + "展示应用元信息(名称、版本)", + "获取并渲染Tauri运行时版本", + "提供跳转至官方网站的功能入口", + "禁用右键上下文菜单以优化桌面端体验", + "支持多语言文本渲染" + ], + "interfaces": [ + { + "name": "disableContextMenu", + "interface_type": "action", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "Svelte动作,用于禁用DOM元素的默认右键菜单行为" + }, + { + "name": "onVisitHome", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "void", + "description": "处理点击事件,通过featuresApi打开外部主页链接" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "@tauri-apps/api/app", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "api", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 4, + "dependency_type": "service", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": false, + "line_number": 5, + "dependency_type": "env", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 6, + "dependency_type": "util", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 37, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.57, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805779, + "prompt_hash": "a6608f266c742be633a355cdfd2d3db7", + "token_usage": { + "input_tokens": 734, + "output_tokens": 748, + "total_tokens": 1482 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a6cb6ba582e164d7a7fc2c1f99150bb5.json b/.litho/cache/ai_code_insight/a6cb6ba582e164d7a7fc2c1f99150bb5.json new file mode 100644 index 0000000..904a49a --- /dev/null +++ b/.litho/cache/ai_code_insight/a6cb6ba582e164d7a7fc2c1f99150bb5.json @@ -0,0 +1,223 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/main/+page.svelte", + "code_purpose": "page", + "importance_score": 1.0, + "description": "主页面组件,集成多个UI模块并协调全局状态管理。", + "functions": [], + "interfaces": [ + "onFeedPressed", + "onSelectToday", + "onSelectWeekend", + "onSelectFavorite", + "onSelectUnread", + "markAsRead", + "onArticlePressed" + ] + }, + "detailed_description": "该组件是应用的主路由页面,负责整合多个功能模块(如FeedsList、ArticlesList、ArticleReader等)并通过Svelte stores进行状态管理。它通过createStore初始化主状态,并将子状态传递给各个子组件。组件使用条件渲染显示文章阅读器或空白指示器,并集成了AI精灵面板和全局通知系统。布局采用Flexbox实现响应式三栏结构。", + "responsibilities": [ + "作为应用主界面的容器组件,组织和协调多个UI组件", + "管理全局状态store的创建与分发", + "处理主界面的布局结构和响应式设计", + "集成通知系统(Toaster)和AI功能面板", + "协调不同功能模块间的状态同步" + ], + "interfaces": [ + { + "name": "onFeedPressed", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "feedId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "void", + "description": "处理用户点击订阅源的事件" + }, + { + "name": "onSelectToday", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "处理选择今日文章筛选的事件" + }, + { + "name": "onSelectWeekend", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "处理选择周末文章筛选的事件" + }, + { + "name": "onSelectFavorite", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "处理选择收藏文章筛选的事件" + }, + { + "name": "onSelectUnread", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "处理选择未读文章筛选的事件" + }, + { + "name": "markAsRead", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "articleId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "void", + "description": "标记文章为已读" + }, + { + "name": "onArticlePressed", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "article", + "param_type": "Article", + "is_optional": false, + "description": null + } + ], + "return_type": "void", + "description": "处理文章被点击的事件" + } + ], + "dependencies": [ + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 1, + "dependency_type": "utility", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "is_external": true, + "line_number": 2, + "dependency_type": "ui-library", + "version": null + }, + { + "name": "FeedsList", + "path": "./widgets/FeedsList.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "component", + "version": null + }, + { + "name": "ArticlesList", + "path": "./widgets/ArticlesList.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "component", + "version": null + }, + { + "name": "SearchBar", + "path": "./widgets/SearchBar.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "component", + "version": null + }, + { + "name": "ArticleReader", + "path": "./widgets/ArticleReader.svelte", + "is_external": false, + "line_number": 6, + "dependency_type": "component", + "version": null + }, + { + "name": "Footer", + "path": "./widgets/Footer.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "component", + "version": null + }, + { + "name": "ReaderBlankIndicator", + "path": "./widgets/ReaderBlankIndicator.svelte", + "is_external": false, + "line_number": 8, + "dependency_type": "component", + "version": null + }, + { + "name": "createStore", + "path": "./stores/index.svelte", + "is_external": false, + "line_number": 9, + "dependency_type": "store", + "version": null + }, + { + "name": "AISpritePanel", + "path": "./widgets/AISpritePanel.svelte", + "is_external": false, + "line_number": 10, + "dependency_type": "component", + "version": null + }, + { + "name": "globalToaster", + "path": "./stores/toast", + "is_external": false, + "line_number": 11, + "dependency_type": "store", + "version": null + }, + { + "name": "spriteToaster", + "path": "./stores/toast", + "is_external": false, + "line_number": 11, + "dependency_type": "store", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 75, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.65, + "cohesion_score": 0.8 + } + }, + "timestamp": 1758800999, + "prompt_hash": "a6cb6ba582e164d7a7fc2c1f99150bb5", + "token_usage": { + "input_tokens": 1094, + "output_tokens": 1295, + "total_tokens": 2389 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a72745de0a68a2a2e8f7ed4854312ce7.json b/.litho/cache/ai_code_insight/a72745de0a68a2a2e8f7ed4854312ce7.json new file mode 100644 index 0000000..fbd66a1 --- /dev/null +++ b/.litho/cache/ai_code_insight/a72745de0a68a2a2e8f7ed4854312ce7.json @@ -0,0 +1,88 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/intelligent/src/article_processor/mod.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "文章处理模块的根模块,组织和导出子模块", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是文章处理器模块的根模块,主要作为命名空间组织者,将文章处理功能分解为多个子模块进行管理。它通过mod关键字声明并公开了六个子模块:llm_processor(LLM处理)、types(类型定义)、purge(清理)、optimizer(优化)、melt(数据融合)和assistant(辅助功能)。该模块本身不包含具体实现逻辑,而是采用Rust的模块系统来构建清晰的功能分层架构。", + "responsibilities": [ + "作为文章处理功能的模块入口点和命名空间组织者", + "协调和整合文章处理的各个子功能模块", + "提供统一的模块访问接口供外部组件调用", + "维护文章处理模块的整体架构结构" + ], + "interfaces": [], + "dependencies": [ + { + "name": "llm_processor", + "path": "crates/intelligent/src/article_processor/llm_processor.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "types", + "path": "crates/intelligent/src/article_processor/types.rs", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + }, + { + "name": "purge", + "path": "crates/intelligent/src/article_processor/purge.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "optimizer", + "path": "crates/intelligent/src/article_processor/optimizer.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "melt", + "path": "crates/intelligent/src/article_processor/melt.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "assistant", + "path": "crates/intelligent/src/article_processor/assistant.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 6, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805889, + "prompt_hash": "a72745de0a68a2a2e8f7ed4854312ce7", + "token_usage": { + "input_tokens": 441, + "output_tokens": 687, + "total_tokens": 1128 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a733d5bbea0966fe77e752a458aed424.json b/.litho/cache/ai_code_insight/a733d5bbea0966fe77e752a458aed424.json new file mode 100644 index 0000000..ef4f16a --- /dev/null +++ b/.litho/cache/ai_code_insight/a733d5bbea0966fe77e752a458aed424.json @@ -0,0 +1,68 @@ +{ + "data": { + "code_dossier": { + "name": "utils.ts", + "file_path": "app/src/lib/windows/utils.ts", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供Tauri应用中窗口管理的工具函数,支持单例窗口展示和带回调的窗口打开功能。", + "functions": [ + "openWithCallback", + "showWindowSingleton" + ], + "interfaces": [] + }, + "detailed_description": "该组件封装了Tauri框架下窗口(Window)与Webview的创建与管理逻辑。主要包含两个核心函数:`showWindowSingleton`用于确保指定label的窗口在应用中仅存在一个实例,若已存在则聚焦该窗口,否则创建新窗口;`openWithCallback`在此基础上扩展,允许在新窗口关闭时通过事件机制触发回调函数,实现跨窗口通信。URL中注入唯一事件ID以保证通信的安全性和隔离性。", + "responsibilities": [ + "管理Tauri应用中的窗口生命周期,确保单例模式", + "实现跨窗口异步回调通信机制", + "封装Webview的初始化与配置逻辑", + "处理URL参数拼接以支持事件回调绑定" + ], + "interfaces": [], + "dependencies": [ + { + "name": "@tauri-apps/api/window", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "@tauri-apps/api/webview", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "@tauri-apps/api/event", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 43, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024460, + "prompt_hash": "a733d5bbea0966fe77e752a458aed424", + "token_usage": { + "input_tokens": 718, + "output_tokens": 563, + "total_tokens": 1281 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/a9cb666db0a84608e1b88d30ff7c6cd1.json b/.litho/cache/ai_code_insight/a9cb666db0a84608e1b88d30ff7c6cd1.json new file mode 100644 index 0000000..1c5228f --- /dev/null +++ b/.litho/cache/ai_code_insight/a9cb666db0a84608e1b88d30ff7c6cd1.json @@ -0,0 +1,126 @@ +{ + "data": { + "code_dossier": { + "name": "Footer.svelte", + "file_path": "app/src/routes/main/widgets/Footer.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "页脚UI组件,显示任务加载状态并提供弹窗详情展示", + "functions": [ + "popoverClose" + ], + "interfaces": [ + "FooterProps" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,用于渲染页面底部的进度状态栏。它通过Popover展示当前待处理任务列表及其状态描述。当有任务处于加载中时,显示ProgressRing动画;否则显示空闲提示。用户可点击区域展开弹窗查看详细任务信息,并通过关闭按钮收起。支持右键菜单禁用以提升用户体验。", + "responsibilities": [ + "渲染任务状态指示器(加载动画或文本)", + "管理Popover弹窗的打开/关闭状态", + "展示待处理任务的详细列表信息", + "集成国际化文本支持", + "防止默认右键上下文菜单行为" + ], + "interfaces": [ + { + "name": "FooterProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "tasksStore", + "param_type": "TasksStore", + "is_optional": false, + "description": "包含pendingStatus、pendingStatusText和pendings等任务状态数据" + } + ], + "return_type": null, + "description": "定义传递给Footer组件的数据结构" + }, + { + "name": "trigger", + "interface_type": "snippet", + "visibility": "private", + "parameters": [], + "return_type": "Element", + "description": "Popover触发区域的UI渲染逻辑" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 3, + "dependency_type": "utility", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "ui_component", + "version": null + }, + { + "name": "lucide-svelte", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "icon", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 6, + "dependency_type": "ui_component", + "version": null + }, + { + "name": "../stores/loading.svelte", + "path": "../stores/loading.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "store", + "version": null + }, + { + "name": "./types", + "path": "./types", + "is_external": false, + "line_number": 8, + "dependency_type": "type_definition", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 74, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024222, + "prompt_hash": "a9cb666db0a84608e1b88d30ff7c6cd1", + "token_usage": { + "input_tokens": 1034, + "output_tokens": 798, + "total_tokens": 1832 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/aa5a4f69973c3b3787ca003a4abf79e9.json b/.litho/cache/ai_code_insight/aa5a4f69973c3b3787ca003a4abf79e9.json new file mode 100644 index 0000000..3a43a09 --- /dev/null +++ b/.litho/cache/ai_code_insight/aa5a4f69973c3b3787ca003a4abf79e9.json @@ -0,0 +1,123 @@ +{ + "data": { + "code_dossier": { + "name": "article.ts", + "file_path": "app/src/lib/types/article.ts", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义文章数据结构,用于表示系统中的文章实体及其属性。", + "functions": [], + "interfaces": [ + "Article" + ] + }, + "detailed_description": "该组件定义了一个名为 Article 的接口,用于描述系统中文章的数据结构。包含文章的基本信息如 ID、标题、阅读状态、发布时间、内容变体(purged、optimized、melted)、分组标识、收藏状态等。主要用于类型约束和前后端数据交互的结构一致性保障。", + "responsibilities": [ + "定义文章实体的数据结构", + "提供类型安全支持以确保数据一致性", + "作为多个模块间数据传输的契约" + ], + "interfaces": [ + { + "name": "Article", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "number", + "is_optional": false, + "description": "文章唯一标识符" + }, + { + "name": "title", + "param_type": "string", + "is_optional": false, + "description": "文章标题" + }, + { + "name": "head_read", + "param_type": "string", + "is_optional": false, + "description": "摘要或首段预览文本" + }, + { + "name": "published_at", + "param_type": "string", + "is_optional": false, + "description": "文章发布时间(ISO 字符串格式)" + }, + { + "name": "has_read", + "param_type": "boolean", + "is_optional": false, + "description": "用户是否已读该文章" + }, + { + "name": "source_link", + "param_type": "string", + "is_optional": false, + "description": "原始来源链接" + }, + { + "name": "purged_content", + "param_type": "string", + "is_optional": false, + "description": "清理后的纯文本内容" + }, + { + "name": "optimized_content", + "param_type": "string", + "is_optional": false, + "description": "优化渲染的内容(如富文本)" + }, + { + "name": "melted_content", + "param_type": "string", + "is_optional": false, + "description": "聚合或融合处理后的内容版本" + }, + { + "name": "created_at", + "param_type": "string", + "is_optional": false, + "description": "记录创建时间" + }, + { + "name": "group_id", + "param_type": "string", + "is_optional": false, + "description": "所属分组 ID" + }, + { + "name": "is_favorite", + "param_type": "boolean", + "is_optional": false, + "description": "是否被标记为收藏" + } + ], + "return_type": null, + "description": "表示一篇文章的完整数据结构" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 16, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024686, + "prompt_hash": "aa5a4f69973c3b3787ca003a4abf79e9", + "token_usage": { + "input_tokens": 488, + "output_tokens": 797, + "total_tokens": 1285 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/aa668edc04d179f5ee42c2304e991e0a.json b/.litho/cache/ai_code_insight/aa668edc04d179f5ee42c2304e991e0a.json new file mode 100644 index 0000000..4dcd4a8 --- /dev/null +++ b/.litho/cache/ai_code_insight/aa668edc04d179f5ee42c2304e991e0a.json @@ -0,0 +1,58 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/feed_api_rs/src/startup/types.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义了任务状态枚举和任务转储数据结构,用于表示任务的运行状态和执行时长。", + "functions": [], + "interfaces": [ + "Status", + "TaskDump" + ] + }, + "detailed_description": "该组件定义了两个核心类型:Status 枚举用于表示任务的生命周期状态(未启动、运行中、已完成、已中止、错误),TaskDump 结构体用于封装任务的状态和持续时间。这些类型主要用于任务监控、状态追踪和结果序列化等场景。通过派生 Clone 和 Copy trait,确保了类型的高效复制语义,适用于高频访问的上下文。", + "responsibilities": [ + "定义任务状态的枚举类型", + "封装任务运行时信息的数据结构", + "提供轻量级、可复制的任务状态表示" + ], + "interfaces": [ + { + "name": "Status", + "interface_type": "enum", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "表示任务的生命周期状态,包括未启动、运行中、完成、中止和错误五种状态。" + }, + { + "name": "TaskDump", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "包含任务当前状态和执行持续时间的只读快照结构体。" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 14, + "number_of_functions": 0, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805868, + "prompt_hash": "aa668edc04d179f5ee42c2304e991e0a", + "token_usage": { + "input_tokens": 457, + "output_tokens": 548, + "total_tokens": 1005 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ab1b0f4b4197fe537faf67a75318cfba.json b/.litho/cache/ai_code_insight/ab1b0f4b4197fe537faf67a75318cfba.json new file mode 100644 index 0000000..5afa937 --- /dev/null +++ b/.litho/cache/ai_code_insight/ab1b0f4b4197fe537faf67a75318cfba.json @@ -0,0 +1,204 @@ +{ + "data": { + "code_dossier": { + "name": "operator.rs", + "file_path": "crates/recorder/src/operator.rs", + "code_purpose": "database", + "importance_score": 0.8, + "description": "数据库操作封装器,提供对文章记录的增删改查及表初始化功能。", + "functions": [ + "new", + "ensure_db_initialized", + "create_table_if_not_existed", + "initialize", + "count", + "dispose", + "insert", + "update", + "query", + "query_by_filters", + "exists", + "query_without_filter", + "query_by_id", + "delete" + ], + "interfaces": [ + "Operator" + ] + }, + "detailed_description": "该组件是Recorder模块中负责与SQLite数据库交互的核心数据访问层。它封装了对`article_record`实体的完整CRUD操作,并提供了表结构自动创建、连接池配置、分页查询、条件过滤等高级功能。通过SeaORM异步ORM框架实现类型安全的数据库访问,支持基于链接、ID、分组等多种查询模式。组件采用惰性初始化策略,在首次使用时建立数据库连接并确保表存在,提升了启动效率和资源利用率。", + "responsibilities": [ + "管理数据库连接的生命周期(初始化、关闭)", + "提供对文章记录的增删改查操作接口", + "确保数据库表结构的存在性(自动建表)", + "执行条件化与非条件化的数据查询(支持分页和排序)", + "验证数据是否存在(基于过滤条件)" + ], + "interfaces": [ + { + "name": "Operator", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "数据库操作器主结构体,封装数据库连接并提供操作方法。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "构造一个新的Operator实例,初始状态无数据库连接。" + }, + { + "name": "initialize", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "异步初始化数据库连接并创建表(如不存在)。" + }, + { + "name": "dispose", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "释放数据库连接资源。" + }, + { + "name": "insert", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "entity", + "param_type": "article_record::ActiveModel", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "插入一条新的文章记录。" + }, + { + "name": "update", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "entity", + "param_type": "article_record::ActiveModel", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "更新一条文章记录并返回更新后的模型。" + }, + { + "name": "query", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "offset", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "limit", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "filter", + "param_type": "F", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "根据过滤条件分页查询文章记录,按发布时间降序排列。" + }, + { + "name": "count", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "统计当前文章记录总数。" + } + ], + "dependencies": [ + { + "name": "std::time::Duration", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "std", + "version": null + }, + { + "name": "sea_orm", + "path": "sea_orm::{ActiveModelTrait, ConnectionTrait, ConnectOptions, Database, DatabaseConnection, DeleteResult, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, Schema}", + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "sea_orm::sea_query::IntoCondition", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "article_record", + "path": "crate::entity::article_record", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "get_appdata_articles", + "path": "crate::path::get_appdata_articles", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 160, + "number_of_functions": 14, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805606, + "prompt_hash": "ab1b0f4b4197fe537faf67a75318cfba", + "token_usage": { + "input_tokens": 1930, + "output_tokens": 1347, + "total_tokens": 3277 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/abbddff0d4ee559593fb7202b8d69b56.json b/.litho/cache/ai_code_insight/abbddff0d4ee559593fb7202b8d69b56.json new file mode 100644 index 0000000..629dc69 --- /dev/null +++ b/.litho/cache/ai_code_insight/abbddff0d4ee559593fb7202b8d69b56.json @@ -0,0 +1,127 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/feeds/create_or_edit/+page.svelte", + "code_purpose": "page", + "importance_score": 0.8, + "description": "Svelte页面组件,用于创建或编辑信息源(feed)的表单界面。支持两种模式:创建和编辑。通过URL参数初始化表单数据,并在保存后关闭窗口并触发回调事件。", + "functions": [ + "onSave", + "onCancel" + ], + "interfaces": [ + "Mode" + ] + }, + "detailed_description": "该组件是SvelteKit路由系统中的一个页面组件,负责渲染创建或编辑feed的表单界面。组件根据URL查询参数动态判断操作模式(create/edit),并预填充表单字段如feed名称、抓取器类型(scrap/rss)、相关数据等。表单包含验证逻辑,确保必填项不为空,并通过派生状态$derived控制提交按钮的可用性。用户提交时调用featuresApi进行后端操作,在创建模式下新增feed,在编辑模式下更新名称和数据。操作完成后通过Tauri的window.emit发送回调事件并关闭当前窗口。组件还禁用了右键菜单以提升用户体验。", + "responsibilities": [ + "管理创建/编辑feed的UI表单状态", + "解析URL参数初始化表单数据", + "验证表单输入并控制提交可用性", + "调用API完成feed的增改操作", + "处理窗口通信与关闭流程" + ], + "interfaces": [ + { + "name": "Mode", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "定义表单操作模式,仅支持'create'和'edit'两种字符串字面量" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": false, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "@tauri-apps/api/window", + "path": "@tauri-apps/api/window", + "is_external": true, + "line_number": 3, + "dependency_type": "native", + "version": null + }, + { + "name": "$lib/widgets/SaveOperatePanel.svelte", + "path": "$lib/widgets/SaveOperatePanel.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "component", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 5, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 6, + "dependency_type": "api", + "version": null + }, + { + "name": "$lib/utils/id", + "path": "$lib/utils/id", + "is_external": false, + "line_number": 7, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 8, + "dependency_type": "types", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": 9, + "dependency_type": "utility", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 10.0, + "lines_of_code": 136, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 9.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758805792, + "prompt_hash": "abbddff0d4ee559593fb7202b8d69b56", + "token_usage": { + "input_tokens": 1608, + "output_tokens": 965, + "total_tokens": 2573 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/abf1f2badac95395e0086d153644ecd5.json b/.litho/cache/ai_code_insight/abf1f2badac95395e0086d153644ecd5.json new file mode 100644 index 0000000..83c8623 --- /dev/null +++ b/.litho/cache/ai_code_insight/abf1f2badac95395e0086d153644ecd5.json @@ -0,0 +1,101 @@ +{ + "data": { + "code_dossier": { + "name": "SaveOperatePanel.svelte", + "file_path": "app/src/lib/widgets/SaveOperatePanel.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.6, + "description": "一个用于保存操作的Svelte前端UI组件,包含保存和取消按钮。", + "functions": [], + "interfaces": [ + "onSave: MouseEventHandler", + "onCancel: MouseEventHandler", + "canSave: boolean" + ] + }, + "detailed_description": "该组件是一个轻量级的Svelte UI组件,主要用于呈现保存与取消操作按钮。它通过props接收三个参数:onSave(点击保存时触发的回调函数)、onCancel(点击取消时触发的回调函数)以及canSave(控制保存按钮是否可交互的布尔值)。保存按钮使用国际化文本$_('common_dialog.save'),取消按钮使用$_('common_dialog.cancel')。布局采用Flexbox实现右对齐排列,并添加间距。保存按钮在canSave为false时被禁用。", + "responsibilities": [ + "提供保存和取消操作的UI按钮", + "根据canSave状态控制保存按钮的启用/禁用状态", + "处理用户点击事件并调用传入的回调函数", + "支持多语言显示文本", + "保持简洁的操作面板布局" + ], + "interfaces": [ + { + "name": "onSave", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "event", + "param_type": "MouseEventHandler", + "is_optional": false, + "description": "鼠标事件对象" + } + ], + "return_type": "void", + "description": "保存操作的回调函数" + }, + { + "name": "onCancel", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "event", + "param_type": "MouseEventHandler", + "is_optional": false, + "description": "鼠标事件对象" + } + ], + "return_type": "void", + "description": "取消操作的回调函数" + }, + { + "name": "canSave", + "interface_type": "property", + "visibility": "public", + "parameters": [], + "return_type": "boolean", + "description": "控制保存按钮是否可用" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "svelte/elements", + "path": "svelte/elements", + "is_external": true, + "line_number": 2, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 21, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024710, + "prompt_hash": "abf1f2badac95395e0086d153644ecd5", + "token_usage": { + "input_tokens": 568, + "output_tokens": 770, + "total_tokens": 1338 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ad5591568fbf848ccc67c2f330d7e3a1.json b/.litho/cache/ai_code_insight/ad5591568fbf848ccc67c2f330d7e3a1.json new file mode 100644 index 0000000..bce3b9f --- /dev/null +++ b/.litho/cache/ai_code_insight/ad5591568fbf848ccc67c2f330d7e3a1.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/articles/search/index.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "实现文章搜索状态管理的Svelte store,用于维护过滤文本和激活状态。", + "functions": [ + "create" + ], + "interfaces": [ + "StoreType" + ] + }, + "detailed_description": "该组件定义了一个基于Svelte的响应式store,用于管理文章列表的搜索与过滤状态。其核心是`StoreType`类型和`create`工厂函数。`filterText`是一个可读写的响应式状态,表示当前输入的搜索关键词;`isFilterActived`是一个派生状态,当`filterText`非空时自动为true,表示过滤功能已激活。通过getter/setter封装了对`filterText`的访问,保证了状态的响应式更新,同时对外暴露只读的`isFilterActived`。此store设计简洁,符合Svelte的状态管理范式,专为UI层的搜索交互提供支持。", + "responsibilities": [ + "创建并初始化文章搜索相关的响应式状态", + "管理用户输入的搜索过滤文本", + "提供计算属性以判断当前过滤器是否处于激活状态", + "封装状态逻辑,为Svelte组件提供类型安全的store接口" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了文章搜索store的结构,包含filterText和isFilterActived两个属性。" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "StoreType", + "description": "工厂函数,用于创建并返回一个新的StoreType实例。" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 24, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024594, + "prompt_hash": "ad5591568fbf848ccc67c2f330d7e3a1", + "token_usage": { + "input_tokens": 518, + "output_tokens": 656, + "total_tokens": 1174 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/adcc64021e419e0c86e06f2bc3768e17.json b/.litho/cache/ai_code_insight/adcc64021e419e0c86e06f2bc3768e17.json new file mode 100644 index 0000000..be30d08 --- /dev/null +++ b/.litho/cache/ai_code_insight/adcc64021e419e0c86e06f2bc3768e17.json @@ -0,0 +1,129 @@ +{ + "data": { + "code_dossier": { + "name": "assistant.rs", + "file_path": "crates/intelligent/src/article_processor/assistant.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "智能助手组件,负责基于LLM的对话处理和文章内容分析。", + "functions": [ + "new", + "chat" + ], + "interfaces": [ + "Assistant" + ] + }, + "detailed_description": "该组件实现了一个智能助手(Assistant),封装了与大型语言模型(LLM)交互的能力。它通过CompletionAgent与底层LLM服务通信,接收文章内容、用户提问和会话历史,构造结构化提示(prompt)并获取模型回复。系统提示(SYSTEM_PROMPT)和用户指令后缀(USER_PROMPT_COMMAND_PURGE)从外部文件加载,增强了可配置性。chat方法负责将输入数据格式化为模型可理解的上下文,并返回生成的响应。", + "responsibilities": [ + "管理LLM代理实例的生命周期", + "构造包含文章、会话历史和用户提问的完整对话上下文", + "调用LLM完成文本生成任务", + "封装与大型语言模型的交互逻辑" + ], + "interfaces": [ + { + "name": "Assistant", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "智能助手的主要数据结构,包含LLM代理和用户提示命令。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定使用的LLM配置区域" + } + ], + "return_type": "Assistant", + "description": "创建一个新的Assistant实例,初始化LLM代理和默认选项。" + }, + { + "name": "chat", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "article", + "param_type": "String", + "is_optional": false, + "description": "待分析的文章正文" + }, + { + "name": "user_prompt", + "param_type": "&str", + "is_optional": false, + "description": "用户当前的提问内容" + }, + { + "name": "history", + "param_type": "Vec", + "is_optional": false, + "description": "之前的会话消息历史" + } + ], + "return_type": "anyhow::Result", + "description": "执行与LLM的对话交互,生成针对文章内容的回答。" + } + ], + "dependencies": [ + { + "name": "llm::llm_agent::CompletionAgent", + "path": "llm::llm_agent::CompletionAgent", + "is_external": true, + "line_number": null, + "dependency_type": "struct", + "version": null + }, + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types::AITargetOption", + "is_external": true, + "line_number": null, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::ConversationMessage", + "path": "types::ConversationMessage", + "is_external": true, + "line_number": null, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types::LLMSection", + "is_external": true, + "line_number": null, + "dependency_type": "struct", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 43, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.4, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024321, + "prompt_hash": "adcc64021e419e0c86e06f2bc3768e17", + "token_usage": { + "input_tokens": 804, + "output_tokens": 945, + "total_tokens": 1749 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/af4afc224c894109c3acc51738a7fc31.json b/.litho/cache/ai_code_insight/af4afc224c894109c3acc51738a7fc31.json new file mode 100644 index 0000000..532b47c --- /dev/null +++ b/.litho/cache/ai_code_insight/af4afc224c894109c3acc51738a7fc31.json @@ -0,0 +1,101 @@ +{ + "data": { + "code_dossier": { + "name": "ArticleRenderWidget.svelte", + "file_path": "app/src/lib/widgets/ArticleRenderWidget.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "渲染文章内容的UI组件,支持HTML和Markdown两种格式。", + "functions": [], + "interfaces": [ + "ArticleRenderProps", + "ArticleRenderType" + ] + }, + "detailed_description": "该组件用于渲染文章内容,根据输入内容自动判断是HTML还是Markdown格式。若为HTML,则直接插入并绑定容器以监听链接点击;若为Markdown,则通过Markdown子组件进行渲染。在挂载时注册事件监听器,拦截所有a标签的默认跳转行为,并通过featuresApi.open_article_external打开外部链接,确保应用内安全导航。", + "responsibilities": [ + "解析并判断文章内容类型(HTML或Markdown)", + "安全渲染HTML内容并防止XSS风险(通过预处理移除代码块包装)", + "拦截内部渲染的链接点击事件并交由API处理外部跳转", + "管理DOM事件生命周期(挂载时添加、卸载时移除监听器)", + "提供一致的文章展示样式与布局" + ], + "interfaces": [ + { + "name": "ArticleRenderProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": "文章原始内容,支持HTML或Markdown格式" + } + ], + "return_type": null, + "description": "定义传递给组件的属性结构" + } + ], + "dependencies": [ + { + "name": "ArticleRenderProps", + "path": "./types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "ArticleRenderType", + "path": "./types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "Markdown", + "path": "./Markdown.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "component", + "version": null + }, + { + "name": "removeCodeBlockWrapper", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 4, + "dependency_type": "function", + "version": null + }, + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 5, + "dependency_type": "api", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 39, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.83, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024499, + "prompt_hash": "af4afc224c894109c3acc51738a7fc31", + "token_usage": { + "input_tokens": 814, + "output_tokens": 729, + "total_tokens": 1543 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/afd44f4486d4c637660b1e531ab6bd89.json b/.litho/cache/ai_code_insight/afd44f4486d4c637660b1e531ab6bd89.json new file mode 100644 index 0000000..679f38d --- /dev/null +++ b/.litho/cache/ai_code_insight/afd44f4486d4c637660b1e531ab6bd89.json @@ -0,0 +1,99 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/hybrid-apis/tauri-regular/index.ts", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "Tauri插件调用的统一接口封装,用于与原生功能交互。", + "functions": [ + "call" + ], + "interfaces": [ + "InvokeArgs", + "Option" + ] + }, + "detailed_description": "该组件是Tauri框架下与原生插件通信的核心桥梁,通过`invoke`机制调用名为'feed-api'的Rust插件方法。它定义了类型安全的泛型函数`call`,接收方法名和参数,并返回Promise类型的响应结果。所有对外暴露的方法均通过'plugin:feed-api|{methodName}'格式进行路由,实现了前端JavaScript/TypeScript与后端Rust逻辑的安全异步通信。", + "responsibilities": [ + "提供统一的Tauri插件调用接口", + "封装底层invoke通信细节", + "实现类型安全的跨语言方法调用", + "管理与原生模块的异步通信协议" + ], + "interfaces": [ + { + "name": "InvokeArgs", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "允许传递对象、数字数组或二进制数据作为调用参数的联合类型" + }, + { + "name": "Option", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "T", + "param_type": "generic", + "is_optional": false, + "description": "泛型占位符" + } + ], + "return_type": null, + "description": "表示可选值的标准类型定义,兼容null和undefined" + }, + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "methodName", + "param_type": "string", + "is_optional": false, + "description": "要调用的Rust插件方法名称" + }, + { + "name": "args", + "param_type": "InvokeArgs", + "is_optional": false, + "description": "传递给方法的序列化参数" + } + ], + "return_type": "Promise", + "description": "执行异步插件调用并返回泛型结果" + } + ], + "dependencies": [ + { + "name": "@tauri-apps/api/core", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.08, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024456, + "prompt_hash": "afd44f4486d4c637660b1e531ab6bd89", + "token_usage": { + "input_tokens": 504, + "output_tokens": 715, + "total_tokens": 1219 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b21b6fe6400e3eb7598b2cc64511e74e.json b/.litho/cache/ai_code_insight/b21b6fe6400e3eb7598b2cc64511e74e.json new file mode 100644 index 0000000..74a6086 --- /dev/null +++ b/.litho/cache/ai_code_insight/b21b6fe6400e3eb7598b2cc64511e74e.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "build.rs", + "file_path": "app/src-tauri/build.rs", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Tauri应用的构建脚本,用于在编译时生成必要的绑定和资源。", + "functions": [ + "main" + ], + "interfaces": [ + "main" + ] + }, + "detailed_description": "该组件是Rust项目中Tauri框架的构建脚本(build script),在每次编译时自动执行。其主要功能是调用`tauri_build::build()`来生成Tauri所需的FFI绑定、检查配置并确保前端与后端集成正确。此脚本对于Tauri应用的安全性、插件系统和API暴露机制至关重要。", + "responsibilities": [ + "执行Tauri编译时代码生成", + "验证Tauri配置的完整性", + "生成必要的绑定以支持前后端通信", + "确保二进制构建过程符合安全策略" + ], + "interfaces": [ + { + "name": "main", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "构建脚本入口点,调用tauri_build库完成构建初始化。" + } + ], + "dependencies": [ + { + "name": "tauri_build", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 3, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805947, + "prompt_hash": "b21b6fe6400e3eb7598b2cc64511e74e", + "token_usage": { + "input_tokens": 404, + "output_tokens": 447, + "total_tokens": 851 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b24ca7810d9662bec32c2c4e492bc0f1.json b/.litho/cache/ai_code_insight/b24ca7810d9662bec32c2c4e492bc0f1.json new file mode 100644 index 0000000..5368c31 --- /dev/null +++ b/.litho/cache/ai_code_insight/b24ca7810d9662bec32c2c4e492bc0f1.json @@ -0,0 +1,98 @@ +{ + "data": { + "code_dossier": { + "name": "scrap_host.rs", + "file_path": "crates/tauri-plugin-feed-api/src/scrap_host.rs", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.8, + "description": "提供基于Tauri框架的网页内容抓取功能,通过创建隐藏Webview窗口加载指定URL并提取页面HTML内容。", + "functions": [ + "scrap_text_by_url" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了异步网页内容抓取功能。其核心逻辑是:接收一个URL地址,在Tauri应用中创建一个不可见的Webview窗口加载该页面;等待3秒确保页面渲染完成;通过执行JavaScript脚本读取document.documentElement.innerHTML;使用Tauri事件系统将结果回传,并通过channel发送出去;最后关闭临时窗口并返回抓取结果。若已有抓取任务正在进行,则拒绝新请求以避免并发冲突。", + "responsibilities": [ + "管理用于网页抓取的专用Webview窗口生命周期", + "防止并发抓取操作,保证单实例运行", + "执行JavaScript代码从远程页面提取HTML内容", + "通过异步通道返回抓取结果", + "处理Webview窗口的创建、通信与资源释放" + ], + "interfaces": [ + { + "name": "scrap_text_by_url", + "interface_type": "function", + "visibility": "pub(crate)", + "parameters": [ + { + "name": "app_handle", + "param_type": "AppHandle", + "is_optional": false, + "description": "Tauri应用句柄,用于管理Webview窗口" + }, + { + "name": "url", + "param_type": "&str", + "is_optional": false, + "description": "待抓取的网页URL字符串引用" + } + ], + "return_type": "Result", + "description": "异步抓取指定URL页面的完整HTML内容" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "spdlog::error", + "path": "spdlog::error", + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": "tauri", + "is_external": true, + "line_number": 5, + "dependency_type": "framework", + "version": null + }, + { + "name": "tokio::sync::oneshot", + "path": "tokio::sync::oneshot", + "is_external": true, + "line_number": 7, + "dependency_type": "async_channel", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 55, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 4.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024402, + "prompt_hash": "b24ca7810d9662bec32c2c4e492bc0f1", + "token_usage": { + "input_tokens": 888, + "output_tokens": 768, + "total_tokens": 1656 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b25782644749a3853e2e6b2566861bc4.json b/.litho/cache/ai_code_insight/b25782644749a3853e2e6b2566861bc4.json new file mode 100644 index 0000000..f03f1f6 --- /dev/null +++ b/.litho/cache/ai_code_insight/b25782644749a3853e2e6b2566861bc4.json @@ -0,0 +1,83 @@ +{ + "data": { + "code_dossier": { + "name": "melt.rs", + "file_path": "crates/intelligent/src/article_processor/melt.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "实现文章处理中的熔合逻辑,通过预设提示词调用LLM进行内容提炼。", + "functions": [], + "interfaces": [ + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件实现了IPresetArticleLLMProcessor接口,用于构建一个基于大语言模型的文章处理器。它使用固定的系统提示(SYSTEM_PROMPT)和用户指令(USER_PROMPT_COMMAND_PURGE),并配置了AI生成参数(如temperature=0.7),以执行文章内容的'熔合'或提炼操作。其主要作用是将原始文本通过LLM转化为更紧凑、高质量的输出。", + "responsibilities": [ + "实现预设型文章LLM处理器的创建逻辑", + "封装Melt功能所需的系统与用户提示语", + "配置合适的AI生成参数以优化输出质量", + "作为文章处理流程中的一环,提供内容提炼能力" + ], + "interfaces": [ + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定LLM服务的目标区域" + } + ], + "return_type": "anyhow::Result", + "description": "定义预设文章处理器的创建规范" + } + ], + "dependencies": [ + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crate::article_processor::llm_processor", + "is_external": false, + "line_number": 4, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 3.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024619, + "prompt_hash": "b25782644749a3853e2e6b2566861bc4", + "token_usage": { + "input_tokens": 600, + "output_tokens": 657, + "total_tokens": 1257 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b43f713a3ab866458b74ecb4ade7d085.json b/.litho/cache/ai_code_insight/b43f713a3ab866458b74ecb4ade7d085.json new file mode 100644 index 0000000..6d3e8e4 --- /dev/null +++ b/.litho/cache/ai_code_insight/b43f713a3ab866458b74ecb4ade7d085.json @@ -0,0 +1,57 @@ +{ + "data": { + "code_dossier": { + "name": "tauri.conf.json", + "file_path": "app/src-tauri/tauri.conf.json", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Tauri 框架的主配置文件,定义应用元数据、构建流程、窗口设置、打包选项和插件配置。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该配置文件用于 Tauri 桌面应用框架,全面定义了应用的核心属性与行为。主要包括:应用基本信息(名称、版本、标识符)、开发与构建生命周期命令(如 dev 和 build 前执行的脚本)、主窗口及保留窗口的 UI 特性(尺寸、标题、初始可见性)、安全策略(CSP 设置为空,表示使用默认策略)、应用打包配置(图标、版权、描述、目标平台)以及第三方插件(tauri-plugin-feed-api)的特定参数。此文件是应用构建和分发的中枢配置。", + "responsibilities": [ + "定义应用元数据(名称、版本、包标识)", + "配置开发与构建生命周期命令", + "管理应用窗口的初始化设置(尺寸、可见性等)", + "控制应用的打包与分发配置(图标、版权、语言等)", + "集成并配置 Tauri 插件的行为参数" + ], + "interfaces": [], + "dependencies": [ + { + "name": "bun", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "tool", + "version": null + }, + { + "name": "tauri-plugin-feed-api", + "path": null, + "is_external": true, + "line_number": 52, + "dependency_type": "plugin", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 62, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.2, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805938, + "prompt_hash": "b43f713a3ab866458b74ecb4ade7d085", + "token_usage": { + "input_tokens": 760, + "output_tokens": 576, + "total_tokens": 1336 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b4dff124eecfc611d49db5d9729c3e10.json b/.litho/cache/ai_code_insight/b4dff124eecfc611d49db5d9729c3e10.json new file mode 100644 index 0000000..a8b9f62 --- /dev/null +++ b/.litho/cache/ai_code_insight/b4dff124eecfc611d49db5d9729c3e10.json @@ -0,0 +1,207 @@ +{ + "data": { + "code_dossier": { + "name": "lite-edit.ts", + "file_path": "app/src/lib/windows/lite-edit.ts", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "负责管理订阅组和订阅项的窗口打开逻辑,封装了与 Tauri 窗口系统交互的细节。", + "functions": [ + "openFeedPackageCreateWindow", + "openFeedPackageEditWindow", + "openFeedCreateWindow", + "openFeedEditWindow", + "open" + ], + "interfaces": [ + "FeedsPackage", + "FeedTargetDescription", + "WindowOptions", + "UnlistenFn" + ] + }, + "detailed_description": "该组件主要用于在桌面应用中动态打开各类表单窗口(如创建/编辑订阅组、订阅项),通过统一的 `open` 函数调用底层 `openWithCallback` 工具函数实现窗口弹出,并传递 URL 参数与回调处理。所有公开函数均返回 Promise,便于异步等待用户操作结果。其核心是解耦 UI 层与窗口管理逻辑,提供类型安全的接口供其他模块调用。", + "responsibilities": [ + "封装窗口打开逻辑,统一配置窗口样式与行为", + "为订阅组和订阅项的增删改操作提供异步弹窗接口", + "处理窗口关闭后的回调数据解析与 Promise 解析", + "通过 URL 查询参数传递操作模式与上下文数据", + "确保窗口不可调整大小且始终置顶以提升用户体验" + ], + "interfaces": [ + { + "name": "openFeedPackageCreateWindow", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "Promise", + "description": "打开‘新增订阅组’窗口并返回创建的结果" + }, + { + "name": "openFeedPackageEditWindow", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "name", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise<{ submited: boolean; newName: string }>", + "description": "打开‘编辑订阅组’窗口并返回是否提交及新名称" + }, + { + "name": "openFeedCreateWindow", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "feedsPackageId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise", + "description": "打开‘新增订阅’窗口并返回创建的订阅描述" + }, + { + "name": "openFeedEditWindow", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "name", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "fetcher_id", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "data", + "param_type": "string[]", + "is_optional": false, + "description": null + }, + { + "name": "feedsPackageId", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": "Promise<{ submited: boolean; newName: string }>", + "description": "打开‘编辑订阅’窗口并返回是否提交及新名称" + }, + { + "name": "open", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "label", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "title", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "url", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "onFinish", + "param_type": "(submited: boolean, data: string) => void", + "is_optional": false, + "description": null + }, + { + "name": "windowOpt", + "param_type": "WindowOptions", + "is_optional": true, + "description": null + } + ], + "return_type": "void", + "description": "内部通用函数,用于实际打开窗口并绑定关闭回调" + } + ], + "dependencies": [ + { + "name": "@tauri-apps/api/event", + "path": "@tauri-apps/api/event", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "./utils", + "path": "app/src/lib/windows/utils", + "is_external": false, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "app/src/lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "@tauri-apps/api/window", + "path": "@tauri-apps/api/window", + "is_external": true, + "line_number": 4, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 103, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.4, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805737, + "prompt_hash": "b4dff124eecfc611d49db5d9729c3e10", + "token_usage": { + "input_tokens": 1076, + "output_tokens": 1306, + "total_tokens": 2382 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b528373e7983b7f77b17152b0f474e39.json b/.litho/cache/ai_code_insight/b528373e7983b7f77b17152b0f474e39.json new file mode 100644 index 0000000..6493a64 --- /dev/null +++ b/.litho/cache/ai_code_insight/b528373e7983b7f77b17152b0f474e39.json @@ -0,0 +1,112 @@ +{ + "data": { + "code_dossier": { + "name": "selector_extensions.rs", + "file_path": "crates/scrap/src/search/selector_extensions.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "为scraper库的ElementRef和Html类型扩展便捷的选择器查询方法,支持文本和属性提取。", + "functions": [ + "select_text", + "select_attr_text" + ], + "interfaces": [ + "ElementSelector" + ] + }, + "detailed_description": "该组件定义了一个名为ElementSelector的trait,并为scraper库中的ElementRef和Html类型实现了该trait。其主要功能是提供两个安全且带有错误提示的HTML选择器查询方法:select_text用于获取匹配元素的文本内容,select_attr_text用于获取匹配元素的指定属性值。两个实现均基于iterator的next()获取首个匹配项,若无匹配则返回语义化错误信息。代码使用anyhow进行错误处理,增强了调用链的可追溯性。", + "responsibilities": [ + "为HTML元素查询操作提供统一的扩展接口", + "封装文本内容的安全提取逻辑", + "封装属性值的安全提取逻辑", + "提供清晰的错误反馈机制", + "增强scraper库API的易用性" + ], + "interfaces": [ + { + "name": "ElementSelector", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "为HTML节点类型扩展选择器查询能力" + }, + { + "name": "select_text", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "self", + "param_type": "&self", + "is_optional": false, + "description": null + }, + { + "name": "selector", + "param_type": "&Selector", + "is_optional": false, + "description": "CSS选择器对象" + } + ], + "return_type": "anyhow::Result", + "description": "选择第一个匹配元素并返回其文本内容" + }, + { + "name": "select_attr_text", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "self", + "param_type": "&self", + "is_optional": false, + "description": null + }, + { + "name": "selector", + "param_type": "&Selector", + "is_optional": false, + "description": "CSS选择器对象" + }, + { + "name": "attr", + "param_type": "&str", + "is_optional": false, + "description": "要提取的HTML属性名" + } + ], + "return_type": "anyhow::Result", + "description": "选择第一个匹配元素并返回其指定属性的文本值" + } + ], + "dependencies": [ + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 15.0, + "lines_of_code": 57, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024369, + "prompt_hash": "b528373e7983b7f77b17152b0f474e39", + "token_usage": { + "input_tokens": 995, + "output_tokens": 829, + "total_tokens": 1824 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b5604c3dc5b0c3b1c76fbf43f82f2662.json b/.litho/cache/ai_code_insight/b5604c3dc5b0c3b1c76fbf43f82f2662.json new file mode 100644 index 0000000..eb6f607 --- /dev/null +++ b/.litho/cache/ai_code_insight/b5604c3dc5b0c3b1c76fbf43f82f2662.json @@ -0,0 +1,79 @@ +{ + "data": { + "code_dossier": { + "name": "MarkdownImg.svelte", + "file_path": "app/src/lib/widgets/MarkdownImg.svelte", + "code_purpose": "widget", + "importance_score": 0.6, + "description": "一个用于在Svelte应用中渲染Markdown图像的轻量级UI组件,具备错误处理机制。", + "functions": [ + "onerror" + ], + "interfaces": [ + "Props" + ] + }, + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于安全地渲染Markdown中的图片。它接收href、title和text作为可选属性,其中href为图片源地址,title为标题提示,text作为alt文本。组件通过$props()从父级接收属性,并使用Svelte的状态系统跟踪图片加载状态。当图片加载失败时,通过onerror事件触发内部错误处理函数,将error标志设为true,从而阻止后续渲染,避免显示损坏的图片链接。此设计提升了用户体验和界面健壮性。", + "responsibilities": [ + "接收并解析图片展示所需的属性参数", + "安全渲染Markdown中的图片元素", + "监控图片加载状态并在出错时进行优雅降级", + "防止因无效图片链接导致的UI异常" + ], + "interfaces": [ + { + "name": "Props", + "interface_type": "interface", + "visibility": "private", + "parameters": [ + { + "name": "href", + "param_type": "string", + "is_optional": true, + "description": "图片的源地址" + }, + { + "name": "title", + "param_type": "string", + "is_optional": true, + "description": "鼠标悬停时显示的标题" + }, + { + "name": "text", + "param_type": "string", + "is_optional": true, + "description": "替代文本,用于图片无法加载时的提示" + } + ], + "return_type": null, + "description": "定义组件可接收的外部属性" + }, + { + "name": "onerror", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "图片加载失败时的回调函数,用于设置错误状态并输出警告日志" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758806021, + "prompt_hash": "b5604c3dc5b0c3b1c76fbf43f82f2662", + "token_usage": { + "input_tokens": 508, + "output_tokens": 713, + "total_tokens": 1221 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b67c8489b2cd5da813598600e4966390.json b/.litho/cache/ai_code_insight/b67c8489b2cd5da813598600e4966390.json new file mode 100644 index 0000000..91bf406 --- /dev/null +++ b/.litho/cache/ai_code_insight/b67c8489b2cd5da813598600e4966390.json @@ -0,0 +1,226 @@ +{ + "data": { + "code_dossier": { + "name": "types.ts", + "file_path": "app/src/lib/hybrid-apis/feed/types.ts", + "code_purpose": "model", + "importance_score": 0.8, + "description": "定义了应用的核心数据结构和类型,包括LLM配置、信息流包、文章模型和对话消息等。", + "functions": [], + "interfaces": [ + "AppConfig", + "LLMProviderType", + "FeedsPackage", + "FeedTargetDescription", + "ArticleModel", + "FeedFetcherID", + "ConversationMessage", + "ConversationInput" + ] + }, + "detailed_description": "该组件是应用程序的中心类型定义文件,用于统一不同模块间的数据结构契约。它主要包含三类模型:1) LLM相关配置模型(如LLMProviderType、LLMSection、AppConfig),支持多提供商集成;2) 信息流处理模型(FeedFetcherID、FeedTargetDescription、FeedsPackage),用于描述内容抓取与组织结构;3) 内容展示与交互模型(ArticleModel、ConversationMessage、ConversationInput),规范文章数据格式及对话交互载荷。所有类型均使用TypeScript的interface或type进行强类型定义,确保编译期类型安全。", + "responsibilities": [ + "定义LLM服务提供商的配置结构和激活机制", + "规范信息流抓取源和聚合包的数据结构", + "提供文章内容的标准数据模型用于展示和存储", + "定义对话系统中消息和输入的统一格式", + "作为跨模块通信的基础类型契约" + ], + "interfaces": [ + { + "name": "AppConfig", + "interface_type": "model", + "visibility": "public", + "parameters": [ + { + "name": "llm", + "param_type": "LLMSection", + "is_optional": false, + "description": null + }, + { + "name": "scrap", + "param_type": "\"baidu\" | \"bing\"", + "is_optional": false, + "description": null + }, + { + "name": "daemon", + "param_type": "object", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "应用顶层配置模型,包含LLM、爬虫策略和守护进程设置" + }, + { + "name": "LLMProviderType", + "interface_type": "enum-type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "支持的LLM提供商枚举类型" + }, + { + "name": "FeedsPackage", + "interface_type": "model", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "name", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "feeds", + "param_type": "FeedTargetDescription[]", + "is_optional": false, + "description": null + }, + { + "name": "is_flat_on_root", + "param_type": "boolean", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "信息流聚合包的数据结构" + }, + { + "name": "ArticleModel", + "interface_type": "model", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "number", + "is_optional": false, + "description": null + }, + { + "name": "title", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "source_link", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "purged_content", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "optimized_content", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "melted_content", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "published_at", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "created_at", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "has_read", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "group_id", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "is_favorite", + "param_type": "boolean", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "文章实体的标准数据模型" + }, + { + "name": "ConversationMessage", + "interface_type": "model", + "visibility": "public", + "parameters": [ + { + "name": "role", + "param_type": "\"system\" | \"user\" | \"assistant\"", + "is_optional": false, + "description": null + }, + { + "name": "mtype", + "param_type": "\"text\" | \"image\" | \"video\" | \"audio\" | \"file\"", + "is_optional": false, + "description": null + }, + { + "name": "payload", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "created_at", + "param_type": "string", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "对话消息的标准化结构" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 89, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805714, + "prompt_hash": "b67c8489b2cd5da813598600e4966390", + "token_usage": { + "input_tokens": 819, + "output_tokens": 1294, + "total_tokens": 2113 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b70bd4d30a4a95f45ec6b91b748bfc1b.json b/.litho/cache/ai_code_insight/b70bd4d30a4a95f45ec6b91b748bfc1b.json new file mode 100644 index 0000000..6f53d01 --- /dev/null +++ b/.litho/cache/ai_code_insight/b70bd4d30a4a95f45ec6b91b748bfc1b.json @@ -0,0 +1,109 @@ +{ + "data": { + "code_dossier": { + "name": "api.rs", + "file_path": "crates/feed_api_rs/src/features/api.rs", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.8, + "description": "功能模块的门面API定义,提供统一接口供外部调用者访问核心功能。", + "functions": [ + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件定义了系统中所有核心功能的统一接口契约(FeaturesAPI trait),作为系统的门面层对外暴露异步操作方法。涵盖了订阅管理、内容更新与读取、用户配置操作、本地AI模型(Ollama)控制、文章交互及搜索等完整业务流程。所有方法均返回impl Future,支持非阻塞异步调用,适配现代Rust应用架构。", + "responsibilities": [ + "提供统一的功能访问接口(门面模式)", + "管理用户订阅包和订阅项的增删改查", + "协调内容抓取、存储与用户阅读状态", + "封装对本地AI服务(Ollama)的控制逻辑", + "支持基于关键词的文章内容搜索与交互式问答" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "trait", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "功能模块的门面API定义,集中暴露系统核心能力。" + } + ], + "dependencies": [ + { + "name": "ollama", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + }, + { + "name": "recorder", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "use", + "version": null + }, + { + "name": "types", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 136, + "number_of_functions": 22, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 4.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024285, + "prompt_hash": "b70bd4d30a4a95f45ec6b91b748bfc1b", + "token_usage": { + "input_tokens": 1782, + "output_tokens": 735, + "total_tokens": 2517 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b8fe66c348c62f74192dd7a2d9e09066.json b/.litho/cache/ai_code_insight/b8fe66c348c62f74192dd7a2d9e09066.json new file mode 100644 index 0000000..a30ee82 --- /dev/null +++ b/.litho/cache/ai_code_insight/b8fe66c348c62f74192dd7a2d9e09066.json @@ -0,0 +1,61 @@ +{ + "data": { + "code_dossier": { + "name": "api.ts", + "file_path": "app/src/lib/hybrid-apis/feed/api.ts", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.8, + "description": "定义了用于管理订阅源、文章内容、应用配置及AI辅助交互的一系列异步接口。", + "functions": [], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件定义了一个名为 FeaturesAPI 的 TypeScript 接口,封装了客户端与后端或原生层(如通过 Tauri)通信所需的所有方法。主要功能包括:对 FeedsPackage(订阅包)和 Feed(订阅源)的增删改查操作;获取和更新文章内容;基于关键词搜索文章;读取和设置应用配置;与 Ollama 模型服务进行交互(状态查询、下载、启动);支持外部打开文章链接和网页内容抓取;以及提供基于文章内容的智能对话能力。所有方法均以 Promise 形式返回,表明其异步特性,适用于跨进程或网络调用场景。", + "responsibilities": [ + "提供统一的异步接口契约以管理信息流订阅体系", + "支持本地应用配置的持久化读写操作", + "集成 AI 功能(Ollama)以实现智能内容处理与交互", + "定义文章内容检索、更新与外部交互的标准方法", + "为前端或业务逻辑层屏蔽底层通信细节" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "interface", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "核心 API 接口契约,声明了所有可用的异步功能方法。" + } + ], + "dependencies": [ + { + "name": "../tauri-regular", + "path": "app/src/lib/hybrid-apis/feed/../tauri-regular", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 73, + "number_of_functions": 17, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 6.0, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024446, + "prompt_hash": "b8fe66c348c62f74192dd7a2d9e09066", + "token_usage": { + "input_tokens": 861, + "output_tokens": 685, + "total_tokens": 1546 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/b9bed7e187467464983c670bd01a7e39.json b/.litho/cache/ai_code_insight/b9bed7e187467464983c670bd01a7e39.json new file mode 100644 index 0000000..4a12c5a --- /dev/null +++ b/.litho/cache/ai_code_insight/b9bed7e187467464983c670bd01a7e39.json @@ -0,0 +1,40 @@ +{ + "data": { + "code_dossier": { + "name": "app.d.ts", + "file_path": "app/src/app.d.ts", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.6, + "description": "SvelteKit应用的全局类型声明文件,用于扩展App命名空间下的类型定义。", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit项目的类型声明文件(app.d.ts),主要用于在TypeScript环境中为应用程序提供全局类型扩展能力。通过declare global语句,在App命名空间中预留了Error、Locals、PageData、PageState和Platform等接口的定义位置,开发者可根据需要取消注释并实现这些接口以增强类型安全性和开发体验。当前版本为空模板,未实际定义任何类型。", + "responsibilities": [ + "提供SvelteKit框架所需的全局类型扩展入口", + "定义应用程序级别的类型接口(如Locals、PageData等)", + "支持跨模块的类型共享与一致性校验", + "作为TypeScript类型系统的集成点" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 13, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024677, + "prompt_hash": "b9bed7e187467464983c670bd01a7e39", + "token_usage": { + "input_tokens": 474, + "output_tokens": 433, + "total_tokens": 907 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ba4ec27c19baa7853eb4668d13fca560.json b/.litho/cache/ai_code_insight/ba4ec27c19baa7853eb4668d13fca560.json new file mode 100644 index 0000000..fdcf029 --- /dev/null +++ b/.litho/cache/ai_code_insight/ba4ec27c19baa7853eb4668d13fca560.json @@ -0,0 +1,90 @@ +{ + "data": { + "code_dossier": { + "name": "SearchBar.svelte", + "file_path": "app/src/routes/main/widgets/SearchBar.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "搜索栏组件,支持绑定过滤文本并条件显示刷新按钮。", + "functions": [], + "interfaces": [ + "SearchBarProps" + ] + }, + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于实现主界面中的搜索功能。它接收一个包含store和articles_store的SearchBarProps类型属性,其中store用于双向绑定输入框的filterText字段,实现搜索关键词的实时同步;articles_store.isFeedSpecified用于判断是否指定了数据源,若未指定则显示刷新按钮,允许用户手动触发feeds更新操作。国际化通过svelte-i18n的$_函数实现占位符翻译。", + "responsibilities": [ + "提供用户可输入的搜索框界面元素", + "将用户的输入实时同步到外部store中进行过滤处理", + "根据数据源状态决定是否显示刷新按钮", + "支持多语言占位符文本展示", + "封装样式与交互逻辑以复用在主页面中" + ], + "interfaces": [ + { + "name": "SearchBarProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "store", + "param_type": "any", + "is_optional": false, + "description": "包含filterText的状态对象,用于双向绑定搜索输入" + }, + { + "name": "articles_store", + "param_type": "ArticlesStore", + "is_optional": false, + "description": "文章数据管理对象,提供isFeedSpecified状态及updateFeeds方法" + } + ], + "return_type": null, + "description": "定义SearchBar组件所需传入的属性结构" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 1, + "dependency_type": "i18n", + "version": null + }, + { + "name": "SearchBarProps", + "path": "./types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "IconRefresh", + "path": "lucide-svelte/icons/refresh-cw", + "is_external": true, + "line_number": 3, + "dependency_type": "component", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 26, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024551, + "prompt_hash": "ba4ec27c19baa7853eb4668d13fca560", + "token_usage": { + "input_tokens": 631, + "output_tokens": 732, + "total_tokens": 1363 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/bbbed2e929d9f9920c8808aac9a1bf5a.json b/.litho/cache/ai_code_insight/bbbed2e929d9f9920c8808aac9a1bf5a.json new file mode 100644 index 0000000..1a959a9 --- /dev/null +++ b/.litho/cache/ai_code_insight/bbbed2e929d9f9920c8808aac9a1bf5a.json @@ -0,0 +1,57 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/feed_api_rs/src/features/mod.rs", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust模块的组织文件,用于将`features`目录下的子模块(api和impl_default)进行公共导出。其主要作用是模块封装与命名空间管理,不包含具体业务逻辑实现,而是通过`pub mod`声明对外暴露内部功能模块。", + "responsibilities": [ + "组织和管理features目录下的子模块结构", + "提供统一的模块访问入口,支持外部代码引用api和impl_default模块", + "实现模块级别的封装与可见性控制,确保内部实现细节的隔离", + "作为系统功能扩展点的聚合层,便于未来新增功能模块" + ], + "interfaces": [], + "dependencies": [ + { + "name": "api", + "path": "crates/feed_api_rs/src/features/api", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "impl_default", + "path": "crates/feed_api_rs/src/features/impl_default", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 2, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024584, + "prompt_hash": "bbbed2e929d9f9920c8808aac9a1bf5a", + "token_usage": { + "input_tokens": 420, + "output_tokens": 449, + "total_tokens": 869 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/bdf4db3ae9767cfd45989fba4fb9f48c.json b/.litho/cache/ai_code_insight/bdf4db3ae9767cfd45989fba4fb9f48c.json new file mode 100644 index 0000000..6291f93 --- /dev/null +++ b/.litho/cache/ai_code_insight/bdf4db3ae9767cfd45989fba4fb9f48c.json @@ -0,0 +1,91 @@ +{ + "data": { + "code_dossier": { + "name": "Markdown.svelte", + "file_path": "app/src/lib/widgets/Markdown.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "一个Svelte组件,用于渲染Markdown内容并支持自定义渲染器,特别是图像的定制化展示。", + "functions": [], + "interfaces": [ + "MarkdownProps" + ] + }, + "detailed_description": "该组件封装了 '@humanspeak/svelte-markdown' 第三方库,通过传入的 `source` 字符串(Markdown 内容)进行解析和渲染。它允许通过 `renderers` 配置项自定义 HTML 元素的渲染方式,当前仅实现了 `image` 标签的自定义渲染,使用 `MarkdownImg.svelte` 组件来处理图片显示逻辑。组件同时通过全局样式(:global)统一设置了 h1-h4、p、ul、ol、table、code 等 Markdown 常见元素的视觉样式,确保与应用整体设计语言(如 Google Sans 字体)保持一致。", + "responsibilities": [ + "接收并解析Markdown格式的字符串内容", + "集成第三方Markdown解析库(SvelteMarkdown)进行内容渲染", + "提供自定义渲染器接口以扩展原生HTML标签的表现形式", + "为Markdown输出的各类HTML元素提供统一的样式定义", + "确保渲染内容的可读性和视觉一致性" + ], + "interfaces": [ + { + "name": "MarkdownProps", + "interface_type": "type", + "visibility": "private", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": "要渲染的Markdown源文本" + } + ], + "return_type": null, + "description": "定义传递给Markdown组件的属性结构" + } + ], + "dependencies": [ + { + "name": "@humanspeak/svelte-markdown", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "component", + "version": null + }, + { + "name": "./types", + "path": "./types", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "svelte", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "framework", + "version": null + }, + { + "name": "./MarkdownImg.svelte", + "path": "./MarkdownImg.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "component", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 136, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.04, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805750, + "prompt_hash": "bdf4db3ae9767cfd45989fba4fb9f48c", + "token_usage": { + "input_tokens": 1305, + "output_tokens": 727, + "total_tokens": 2032 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/be639f2c3fb0acbb72d4bae5312e9ea3.json b/.litho/cache/ai_code_insight/be639f2c3fb0acbb72d4bae5312e9ea3.json new file mode 100644 index 0000000..04aa9dc --- /dev/null +++ b/.litho/cache/ai_code_insight/be639f2c3fb0acbb72d4bae5312e9ea3.json @@ -0,0 +1,189 @@ +{ + "data": { + "code_dossier": { + "name": "article_reader.rs", + "file_path": "crates/scrap/src/article_reader.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "负责从指定URL抓取网页内容,并通过HTML解析提取正文文本。支持重定向处理和基于LLM的智能重定向检测。", + "functions": [ + "read", + "read_inner", + "acquire_html", + "read_inner_from_response" + ], + "interfaces": [ + "read" + ] + }, + "detailed_description": "该组件实现了一个异步网页内容读取器,主要功能是从给定URL获取HTML内容并提取标签内的纯文本。它首先使用reqwest客户端发起HTTP请求,支持禁用自动重定向以手动控制跳转逻辑。在收到响应后,会检查状态码是否为成功,若为重定向则递归处理Location头。对于正常响应,进一步通过scraper库选择body元素并去除脚本和样式标签后提取可见文本。特别地,该模块集成了LLM能力(CompletionAgent),用于识别页面中隐含的JavaScript重定向链接(如window.location.href),从而实现更智能的内容获取。整个流程支持来源主机验证与校准模式下的条件修正。", + "responsibilities": [ + "发起HTTP请求并安全获取目标网页的HTML内容", + "处理HTTP重定向及Location头解析", + "利用LLM智能识别JavaScript中的隐式重定向链接", + "使用HTML解析器提取页面主体文本内容", + "集成日志记录与错误处理机制" + ], + "interfaces": [ + { + "name": "read", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "url_str", + "param_type": "&str", + "is_optional": false, + "description": "目标网页的URL字符串" + }, + { + "name": "source_search_host", + "param_type": "Option", + "is_optional": true, + "description": "可选的搜索源主机名,用于判断是否来自特定搜索引擎结果页" + }, + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "LLM配置部分,用于初始化CompletionAgent进行智能分析" + } + ], + "return_type": "anyhow::Result<(String, String)>", + "description": "主入口函数,调用read_inner执行实际逻辑,返回抓取到的文本内容和最终URL" + }, + { + "name": "read_inner", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "url_str", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "auto_redirect", + "param_type": "bool", + "is_optional": false, + "description": null + }, + { + "name": "source_search_host", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result<(String, String)>", + "description": "内部核心逻辑函数,协调HTML获取与内容提取流程" + } + ], + "dependencies": [ + { + "name": "reqwest::redirect::Policy", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "library", + "version": null + }, + { + "name": "scraper::Html", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "library", + "version": null + }, + { + "name": "scraper::Selector", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "library", + "version": null + }, + { + "name": "spdlog::error", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "library", + "version": null + }, + { + "name": "spdlog::info", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "library", + "version": null + }, + { + "name": "llm::llm_agent::CompletionAgent", + "path": "crates/llm/src/llm_agent.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "crate", + "version": null + }, + { + "name": "llm::providers::types::AITargetOption", + "path": "crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "crate", + "version": null + }, + { + "name": "types::LLMSection", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "crate", + "version": null + }, + { + "name": "crate::connector", + "path": "crates/scrap/src/connector.rs", + "is_external": false, + "line_number": 9, + "dependency_type": "local", + "version": null + }, + { + "name": "crate::search::selector_extensions::ElementSelector", + "path": "crates/scrap/src/search/selector_extensions.rs", + "is_external": false, + "line_number": 11, + "dependency_type": "local", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 11.0, + "lines_of_code": 97, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 10.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758805414, + "prompt_hash": "be639f2c3fb0acbb72d4bae5312e9ea3", + "token_usage": { + "input_tokens": 1799, + "output_tokens": 1354, + "total_tokens": 3153 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/bf3bdacf1d45e059c908d7eb632419c7.json b/.litho/cache/ai_code_insight/bf3bdacf1d45e059c908d7eb632419c7.json new file mode 100644 index 0000000..1efd10b --- /dev/null +++ b/.litho/cache/ai_code_insight/bf3bdacf1d45e059c908d7eb632419c7.json @@ -0,0 +1,251 @@ +{ + "data": { + "code_dossier": { + "name": "llm_openaibase_like.rs", + "file_path": "crates/llm/src/providers/llm_openaibase_like.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现与类OpenAI API兼容的LLM完成服务,支持通过HTTP请求调用远程模型进行对话补全。", + "functions": [ + "OpenAILikeCompletionService::new", + "OpenAILikeCompletionService::completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了与OpenAI风格API兼容的语言模型调用逻辑。它封装了请求构造(RequestParameters、Message)、响应解析(Response、ChoiceChunk),并通过reqwest客户端发送POST请求到指定API端点。核心功能由OpenAILikeCompletionService结构体提供,遵循CompletionService trait接口,支持注入系统提示词和动态用户输入,适用于构建基于大语言模型的智能服务。", + "responsibilities": [ + "封装与OpenAI兼容API的通信协议", + "构造符合规范的请求数据结构", + "处理HTTP响应并提取生成文本", + "管理LLM调用所需的配置与认证信息", + "实现统一的补全服务接口" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义语言模型补全服务的标准接口,本组件为其提供具体实现。" + }, + { + "name": "RequestParameters", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "model", + "param_type": "String", + "is_optional": false, + "description": "指定使用的模型名称" + }, + { + "name": "messages", + "param_type": "Vec", + "is_optional": false, + "description": "对话消息序列" + } + ], + "return_type": null, + "description": "用于序列化为JSON请求体的参数结构" + }, + { + "name": "Message", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "role", + "param_type": "String", + "is_optional": false, + "description": "角色类型:system/user/assistant" + }, + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "消息内容" + } + ], + "return_type": null, + "description": "表示单条对话消息的数据结构" + }, + { + "name": "Response", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "choices", + "param_type": "Vec", + "is_optional": false, + "description": "模型返回的候选结果列表" + } + ], + "return_type": null, + "description": "用于反序列化API响应的结构体" + }, + { + "name": "ChoiceChunk", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "finish_reason", + "param_type": "Option", + "is_optional": true, + "description": "生成结束原因" + }, + { + "name": "message", + "param_type": "Option", + "is_optional": true, + "description": "返回的消息内容" + } + ], + "return_type": null, + "description": "表示单个生成选项的结果块" + }, + { + "name": "OpenAILikeCompletionService", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "OpenAILLMProvider", + "is_optional": false, + "description": "LLM提供者配置" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统级提示词" + }, + { + "name": "client", + "param_type": "Client", + "is_optional": false, + "description": "HTTP客户端实例" + } + ], + "return_type": null, + "description": "实现CompletionService的核心服务结构体" + }, + { + "name": "OpenAILikeCompletionService::new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&OpenAILLMProvider", + "is_optional": false, + "description": "引用配置对象" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "目标选项(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "构造新的服务实例,初始化HTTP客户端" + }, + { + "name": "OpenAILikeCompletionService::completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行一次完整的LLM补全过程,返回生成文本" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::OpenAILLMProvider", + "path": "./types.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 84, + "number_of_functions": 2, + "number_of_classes": 5, + "depth_of_inheritance": 0, + "coupling_factor": 0.59, + "cohesion_score": 0.87 + } + }, + "timestamp": 1759024269, + "prompt_hash": "bf3bdacf1d45e059c908d7eb632419c7", + "token_usage": { + "input_tokens": 1050, + "output_tokens": 1578, + "total_tokens": 2628 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/bf7caf80e892271f21f3392b5e723804.json b/.litho/cache/ai_code_insight/bf7caf80e892271f21f3392b5e723804.json new file mode 100644 index 0000000..3a95ae6 --- /dev/null +++ b/.litho/cache/ai_code_insight/bf7caf80e892271f21f3392b5e723804.json @@ -0,0 +1,269 @@ +{ + "data": { + "code_dossier": { + "name": "commands.rs", + "file_path": "crates/tauri-plugin-feed-api/src/commands.rs", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 0.8, + "description": "Tauri命令处理模块,封装了所有前端可调用的异步API接口,用于管理订阅源包、文章内容读取、AI交互等功能。", + "functions": [ + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "scrap_text_by_url", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "interfaces": [] + }, + "detailed_description": "该组件是Tauri插件的核心命令层,负责暴露Rust后端功能给前端JavaScript调用。每个函数通过`#[tauri::command]`宏导出为IPC接口,统一使用`Arc`状态管理共享资源,并通过`features_api`代理实际业务逻辑。包含对Feeds包的增删改查、文章内容抓取与标记、Ollama模型控制、外部网页打开、AI对话等完整功能集。错误处理采用anyhow Result转换为标准Result<()>模式,日志通过spdlog记录。特别地,`scrap_text_by_url`依赖独立WebView窗口实现页面内容抓取,具有较强的系统集成能力。", + "responsibilities": [ + "提供Tauri IPC命令接口供前端调用", + "协调应用状态(HybridRuntimeState)与核心业务逻辑(FeaturesAPI)之间的交互", + "处理订阅源(FeedsPackage)和文章(Article)的CRUD操作", + "管理Ollama本地AI服务的生命周期(下载、启动、状态查询)", + "实现网页内容抓取及基于LLM的文章智能交互功能" + ], + "interfaces": [ + { + "name": "add_feeds_package", + "interface_type": "command", + "visibility": "private", + "parameters": [ + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "feeds_package", + "param_type": "FeedsPackage", + "is_optional": false, + "description": null + } + ], + "return_type": "Result<(), ()>", + "description": "添加新的订阅源包" + }, + { + "name": "remove_feeds_package", + "interface_type": "command", + "visibility": "private", + "parameters": [ + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "Result<(), ()>", + "description": "移除指定ID的订阅源包" + }, + { + "name": "get_feeds_packages", + "interface_type": "command", + "visibility": "private", + "parameters": [ + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + } + ], + "return_type": "Result, ()>", + "description": "获取所有订阅源包列表" + }, + { + "name": "update_feed_contents", + "interface_type": "command", + "visibility": "private", + "parameters": [ + { + "name": "app_handle", + "param_type": "AppHandle", + "is_optional": false, + "description": null + }, + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "package_id", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "feed_id", + "param_type": "&str", + "is_optional": false, + "description": null + } + ], + "return_type": "Result<(), ()>", + "description": "更新指定订阅源的内容" + }, + { + "name": "chat_with_article_assistant", + "interface_type": "command", + "visibility": "private", + "parameters": [ + { + "name": "app_handle", + "param_type": "AppHandle", + "is_optional": false, + "description": null + }, + { + "name": "state", + "param_type": "State<'_, Arc>", + "is_optional": false, + "description": null + }, + { + "name": "article_id", + "param_type": "i32", + "is_optional": false, + "description": null + }, + { + "name": "user_prompt", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "history", + "param_type": "Vec", + "is_optional": false, + "description": null + } + ], + "return_type": "Result", + "description": "与文章助手进行聊天对话" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "std", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": null, + "dependency_type": "logging", + "version": null + }, + { + "name": "tauri", + "path": "tauri", + "is_external": true, + "line_number": null, + "dependency_type": "framework", + "version": null + }, + { + "name": "feed_api_rs", + "path": "feed_api_rs::features::api::FeaturesAPI", + "is_external": true, + "line_number": null, + "dependency_type": "business_logic", + "version": null + }, + { + "name": "ollama", + "path": "ollama::ProgramStatus", + "is_external": true, + "line_number": null, + "dependency_type": "ai_service", + "version": null + }, + { + "name": "recorder", + "path": "recorder::entity::article_record::Model", + "is_external": true, + "line_number": null, + "dependency_type": "data_access", + "version": null + }, + { + "name": "types", + "path": "types::{AppConfig, ConversationMessage, FeedTargetDescription, FeedsPackage}", + "is_external": true, + "line_number": null, + "dependency_type": "domain_model", + "version": null + }, + { + "name": "crate::scrap_host", + "path": "crate::scrap_host", + "is_external": false, + "line_number": null, + "dependency_type": "local_module", + "version": null + }, + { + "name": "crate::state::HybridRuntimeState", + "path": "crate::state::HybridRuntimeState", + "is_external": false, + "line_number": null, + "dependency_type": "local_state", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 299, + "number_of_functions": 24, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 9.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024417, + "prompt_hash": "bf7caf80e892271f21f3392b5e723804", + "token_usage": { + "input_tokens": 3187, + "output_tokens": 1610, + "total_tokens": 4797 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c01c639f0b5d2335780ca0bf9afa5a8f.json b/.litho/cache/ai_code_insight/c01c639f0b5d2335780ca0bf9afa5a8f.json new file mode 100644 index 0000000..a6b0f91 --- /dev/null +++ b/.litho/cache/ai_code_insight/c01c639f0b5d2335780ca0bf9afa5a8f.json @@ -0,0 +1,190 @@ +{ + "data": { + "code_dossier": { + "name": "llm_mistral.rs", + "file_path": "crates/llm/src/providers/llm_mistral.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "Mistral Qino Agent服务,基于Mistral AI API实现聊天补全功能的智能Agent组件", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了针对Mistral AI平台的聊天补全服务代理。通过封装OpenAILikeCompletionService,复用OpenAI兼容的接口逻辑,适配Mistral API的特定端点和认证信息。支持系统提示词配置,并通过reqwest客户端发送请求。主要处理流程包括:初始化服务时设置模型配置和系统提示,调用completion方法时转发请求至底层OpenAI类服务。", + "responsibilities": [ + "作为Mistral AI服务的适配层,提供统一的CompletionService接口", + "管理Mistral API的连接配置(URL、模型ID、密钥)", + "封装请求参数结构体(RequestParameters, Message)用于序列化", + "通过OpenAILikeCompletionService复用通用LLM交互逻辑", + "提供系统级提示词注入能力以引导AI行为" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义语言模型补全服务的标准接口" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词,用于初始化AI的行为模式" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "目标选项参数(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "构造一个新的MistralQinoAgentService实例" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行一次对话补全请求并返回AI响应" + }, + { + "name": "RequestParameters", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "messages", + "param_type": "Vec", + "is_optional": false, + "description": null + }, + { + "name": "agent_id", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "API请求参数结构体" + }, + { + "name": "Message", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "role", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "对话消息结构体" + }, + { + "name": "MistralQinoAgentService", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "Mistral服务主结构体" + }, + { + "name": "impl CompletionService for MistralQinoAgentService", + "interface_type": "impl", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "为MistralQinoAgentService实现CompletionService trait" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::OpenAILLMProvider", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "path": "./crates/llm/src/providers/llm_openaibase_like.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "service", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 50, + "number_of_functions": 2, + "number_of_classes": 3, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024273, + "prompt_hash": "c01c639f0b5d2335780ca0bf9afa5a8f", + "token_usage": { + "input_tokens": 856, + "output_tokens": 1207, + "total_tokens": 2063 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c0bf3f844db0e6208c3db258d3dd4ad8.json b/.litho/cache/ai_code_insight/c0bf3f844db0e6208c3db258d3dd4ad8.json new file mode 100644 index 0000000..9ef78f7 --- /dev/null +++ b/.litho/cache/ai_code_insight/c0bf3f844db0e6208c3db258d3dd4ad8.json @@ -0,0 +1,126 @@ +{ + "data": { + "code_dossier": { + "name": "reader.svelte.ts", + "file_path": "app/src/routes/main/stores/reader.svelte.ts", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "提供文章阅读状态管理和内容刷新功能的控制器组件,封装了与后端API和任务调度系统的交互逻辑。", + "functions": [ + "create", + "markAsRead", + "refreshByEnhancedScraper" + ], + "interfaces": [ + "StoreType", + "Associates" + ] + }, + "detailed_description": "该组件是一个Svelte store,用于管理用户对文章的读取状态及内容更新操作。它通过`create`函数接收依赖项(主要是任务管理器),并返回包含`markAsRead`和`refreshByEnhancedScraper`两个方法的对象。其中`markAsRead`调用API标记文章为已读;`refreshByEnhancedScraper`则实现智能刷新机制:先检查是否存在正在进行的任务,若存在则复用或清理失败任务,否则发起新的更新请求,并将异步任务注册到全局任务队列中以支持并发控制和状态共享。", + "responsibilities": [ + "管理文章的已读状态变更请求", + "协调文章内容的增强式抓取与刷新流程", + "集成任务调度系统以避免重复请求", + "封装底层API调用细节,提供简洁的接口供上层使用" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "export", + "parameters": [], + "return_type": null, + "description": "定义了本模块对外暴露的方法集合,包括markAsRead和refreshByEnhancedScraper" + }, + { + "name": "Associates", + "interface_type": "type", + "visibility": "internal", + "parameters": [], + "return_type": null, + "description": "依赖注入结构,当前仅包含tasks任务管理器引用" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "export", + "parameters": [ + { + "name": "associates", + "param_type": "Associates", + "is_optional": false, + "description": "注入的关联服务实例" + } + ], + "return_type": "StoreType", + "description": "工厂函数,用于创建并初始化store实例" + }, + { + "name": "markAsRead", + "interface_type": "function", + "visibility": "internal", + "parameters": [ + { + "name": "articleId", + "param_type": "number", + "is_optional": false, + "description": "目标文章ID" + } + ], + "return_type": "Promise", + "description": "标记指定文章为已读状态" + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "api-client", + "version": null + }, + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 2, + "dependency_type": "model", + "version": null + }, + { + "name": "Status", + "path": "./loading.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "constant", + "version": null + }, + { + "name": "TasksStoreType", + "path": "./tasks.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "store-type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 47, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.92 + } + }, + "timestamp": 1758800996, + "prompt_hash": "c0bf3f844db0e6208c3db258d3dd4ad8", + "token_usage": { + "input_tokens": 720, + "output_tokens": 962, + "total_tokens": 1682 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c312653a8b6a3384796c5604548dc15e.json b/.litho/cache/ai_code_insight/c312653a8b6a3384796c5604548dc15e.json new file mode 100644 index 0000000..c206628 --- /dev/null +++ b/.litho/cache/ai_code_insight/c312653a8b6a3384796c5604548dc15e.json @@ -0,0 +1,124 @@ +{ + "data": { + "code_dossier": { + "name": "article.ts", + "file_path": "app/src/lib/types/article.ts", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义文章数据结构,用于表示系统中的文章实体及其属性。", + "functions": [], + "interfaces": [ + "Article" + ] + }, + "detailed_description": "该组件定义了一个名为 Article 的接口,用于描述系统中文章的数据结构。包含文章的基本信息如ID、标题、阅读状态、发布时间、内容版本(purged、optimized、melted)、创建时间、分组ID以及收藏状态等字段。主要用于类型约束和数据契约,在前后端交互或内部模块间传递文章数据时提供类型安全。", + "responsibilities": [ + "定义文章实体的数据结构", + "提供类型安全保证", + "支持多版本内容展示", + "统一数据契约", + "支持前端展示与状态管理" + ], + "interfaces": [ + { + "name": "Article", + "interface_type": "interface", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "number", + "is_optional": false, + "description": null + }, + { + "name": "title", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "head_read", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "published_at", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "has_read", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "source_link", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "purged_content", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "optimized_content", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "melted_content", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "created_at", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "group_id", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "is_favorite", + "param_type": "boolean", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "表示系统中一篇文章的完整数据结构,包含元数据、内容版本和用户交互状态。" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 16, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805986, + "prompt_hash": "c312653a8b6a3384796c5604548dc15e", + "token_usage": { + "input_tokens": 479, + "output_tokens": 717, + "total_tokens": 1196 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c37f1b5ec9dae2ca73697002dfc56a37.json b/.litho/cache/ai_code_insight/c37f1b5ec9dae2ca73697002dfc56a37.json new file mode 100644 index 0000000..4926ee5 --- /dev/null +++ b/.litho/cache/ai_code_insight/c37f1b5ec9dae2ca73697002dfc56a37.json @@ -0,0 +1,151 @@ +{ + "data": { + "code_dossier": { + "name": "init_logger.rs", + "file_path": "crates/feed_api_rs/src/startup/init_logger.rs", + "code_purpose": "util", + "importance_score": 0.8, + "description": "日志初始化工具模块,根据应用配置动态设置日志输出方式和格式。", + "functions": [ + "call", + "init_by", + "specify_logger_format" + ], + "interfaces": [ + "call", + "init_by", + "specify_logger_format" + ] + }, + "detailed_description": "该组件负责根据 AppConfig 中的 log 配置项初始化全局日志系统。支持三种输出模式:Stdout、Disk 和 UnSpecified。在 Debug 模式下自动启用全量日志输出。当选择磁盘输出时,使用按天轮转的日志文件策略,并将日志写入指定目录下的时间命名文件中。所有日志输出均采用统一的格式化模板,包含日期、时间、线程ID、日志级别和消息内容。", + "responsibilities": [ + "解析应用配置中的日志设置", + "根据配置初始化日志输出目标(控制台或磁盘)", + "设置全局日志格式和级别过滤器", + "支持调试模式下的自动日志启用机制", + "管理日志文件的轮转与刷新策略" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "app_config", + "param_type": "&AppConfig", + "is_optional": false, + "description": "应用配置对象引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "主入口函数,通过应用配置调用日志初始化" + }, + { + "name": "init_by", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "log_section", + "param_type": "&AppConfigLogSection", + "is_optional": false, + "description": "日志配置节引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "根据日志配置节执行具体的初始化逻辑" + }, + { + "name": "specify_logger_format", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "logger", + "param_type": "&Arc", + "is_optional": false, + "description": "日志记录器智能指针引用" + } + ], + "return_type": null, + "description": "为指定日志记录器设置统一的格式化模式" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "std", + "version": null + }, + { + "name": "std::time::Duration", + "path": null, + "is_external": false, + "line_number": 2, + "dependency_type": "std", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "third_party", + "version": null + }, + { + "name": "recorder::path::get_appdata_file_in_dir", + "path": "recorder/path.rs", + "is_external": false, + "line_number": 9, + "dependency_type": "internal", + "version": null + }, + { + "name": "types::AppConfig", + "path": "types/config.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + }, + { + "name": "types::AppConfigLogSection", + "path": "types/config.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + }, + { + "name": "types::OutputType", + "path": "types/enums.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 74, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801184, + "prompt_hash": "c37f1b5ec9dae2ca73697002dfc56a37", + "token_usage": { + "input_tokens": 1113, + "output_tokens": 1000, + "total_tokens": 2113 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c44c3751c4e7f5a384d11932ea147240.json b/.litho/cache/ai_code_insight/c44c3751c4e7f5a384d11932ea147240.json new file mode 100644 index 0000000..a42d565 --- /dev/null +++ b/.litho/cache/ai_code_insight/c44c3751c4e7f5a384d11932ea147240.json @@ -0,0 +1,50 @@ +{ + "data": { + "code_dossier": { + "name": "settings.ts", + "file_path": "app/src/lib/windows/settings.ts", + "code_purpose": "config", + "importance_score": 0.6, + "description": "负责管理设置窗口的打开行为,封装窗口配置参数", + "functions": [ + "open" + ], + "interfaces": [] + }, + "detailed_description": "该组件定义了一个异步函数 open,用于打开一个名为 'settings' 的独立窗口。通过调用 showWindowSingleton 工具函数,传入窗口标识、URL 路径以及一系列窗口属性(如标题、尺寸、居中显示、不可调整大小和不可最大化),确保应用设置窗口以单例模式展示,避免重复实例化。", + "responsibilities": [ + "提供打开设置窗口的统一入口", + "维护设置窗口的静态配置属性", + "确保设置窗口以单例模式运行", + "封装窗口创建的实现细节" + ], + "interfaces": [], + "dependencies": [ + { + "name": "showWindowSingleton", + "path": "./utils", + "is_external": false, + "line_number": 1, + "dependency_type": "function", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 14, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758806001, + "prompt_hash": "c44c3751c4e7f5a384d11932ea147240", + "token_usage": { + "input_tokens": 469, + "output_tokens": 408, + "total_tokens": 877 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c4f21b3653affea2e24af9666cd06e43.json b/.litho/cache/ai_code_insight/c4f21b3653affea2e24af9666cd06e43.json new file mode 100644 index 0000000..5dcd305 --- /dev/null +++ b/.litho/cache/ai_code_insight/c4f21b3653affea2e24af9666cd06e43.json @@ -0,0 +1,96 @@ +{ + "data": { + "code_dossier": { + "name": "utils.rs", + "file_path": "crates/feed_api_rs/src/utils.rs", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供异步任务并行执行的限流控制工具函数,用于管理高并发场景下的资源使用。", + "functions": [ + "do_parallel_with_limit" + ], + "interfaces": [] + }, + "detailed_description": "该组件实现了一个名为 `do_parallel_with_limit` 的异步工具函数,用于在指定最大并发数的限制下并行执行一组 Future。通过使用 Tokio 的 Semaphore(信号量)机制,确保同时运行的任务数量不会超过设定阈值,从而防止资源耗尽。当 max_concurrent 为 0 时,默认设置为 1,避免非法状态。此函数广泛适用于需要控制异步任务并发度的场景,如批量网络请求、数据库操作等。", + "responsibilities": [ + "提供异步任务的并发控制能力", + "防止系统资源因过多并发任务而耗尽", + "封装复杂的并发同步逻辑,提升上层代码可读性", + "支持动态配置最大并发数,并具备默认值容错处理" + ], + "interfaces": [ + { + "name": "do_parallel_with_limit", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "futures", + "param_type": "Vec", + "is_optional": false, + "description": "待执行的异步任务列表" + }, + { + "name": "max_concurrent", + "param_type": "usize", + "is_optional": false, + "description": "最大允许的并发任务数,0 表示自动调整为 1" + } + ], + "return_type": "Vec", + "description": "返回所有异步任务完成后的结果向量" + } + ], + "dependencies": [ + { + "name": "std::future::Future", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": 2, + "dependency_type": "use", + "version": null + }, + { + "name": "futures::future::join_all", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "tokio::sync::Semaphore", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 29, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.138, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805876, + "prompt_hash": "c4f21b3653affea2e24af9666cd06e43", + "token_usage": { + "input_tokens": 619, + "output_tokens": 741, + "total_tokens": 1360 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c51195d4607339d5b49e118ff6004474.json b/.litho/cache/ai_code_insight/c51195d4607339d5b49e118ff6004474.json new file mode 100644 index 0000000..d8f0f5f --- /dev/null +++ b/.litho/cache/ai_code_insight/c51195d4607339d5b49e118ff6004474.json @@ -0,0 +1,118 @@ +{ + "data": { + "code_dossier": { + "name": "Footer.svelte", + "file_path": "app/src/routes/main/widgets/Footer.svelte", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "底部状态栏组件,显示任务加载状态并提供任务详情弹窗", + "functions": [ + "popoverClose" + ], + "interfaces": [ + "FooterProps" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,作为应用主界面的底部状态栏。它通过Popover展示当前待处理任务的详细信息,支持国际化文本显示,并集成右键菜单禁用功能。组件监听tasksStore中的pendingStatus和pendingStatusText,动态渲染加载进度环和任务描述列表。当有任务处于加载状态时,显示ProgressRing动画;当无任务时显示空闲提示。用户可点击触发区域展开弹窗查看所有待处理任务,每个任务项包含状态标签和描述文本,支持通过关闭按钮或外部点击收起弹窗。", + "responsibilities": [ + "渲染底部状态栏UI布局", + "展示当前任务加载状态和进度指示", + "管理Popover弹窗的打开/关闭状态", + "显示待处理任务列表及其状态详情", + "处理右键上下文菜单禁用逻辑" + ], + "interfaces": [ + { + "name": "FooterProps", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义传递给Footer组件的属性类型,包含tasksStore引用" + }, + { + "name": "trigger", + "interface_type": "snippet", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "Popover触发区域的UI模板" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "app/src/lib/utils/dom.ts", + "is_external": false, + "line_number": 3, + "dependency_type": "utility", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 4, + "dependency_type": "ui_component", + "version": null + }, + { + "name": "lucide-svelte", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "icon", + "version": null + }, + { + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "is_external": true, + "line_number": 6, + "dependency_type": "ui_component", + "version": null + }, + { + "name": "../stores/loading.svelte", + "path": "app/src/routes/main/stores/loading.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "store", + "version": null + }, + { + "name": "./types", + "path": "app/src/routes/main/widgets/types.ts", + "is_external": false, + "line_number": 8, + "dependency_type": "type_definition", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 74, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.857, + "cohesion_score": 0.72 + } + }, + "timestamp": 1758801079, + "prompt_hash": "c51195d4607339d5b49e118ff6004474", + "token_usage": { + "input_tokens": 1025, + "output_tokens": 863, + "total_tokens": 1888 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c58c1199b0ac1a118b33fbee882f34e8.json b/.litho/cache/ai_code_insight/c58c1199b0ac1a118b33fbee882f34e8.json new file mode 100644 index 0000000..508acfa --- /dev/null +++ b/.litho/cache/ai_code_insight/c58c1199b0ac1a118b33fbee882f34e8.json @@ -0,0 +1,191 @@ +{ + "data": { + "code_dossier": { + "name": "article_reader.rs", + "file_path": "crates/scrap/src/article_reader.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现网页内容抓取与智能重定向处理的核心组件,支持基于LLM的页面跳转检测", + "functions": [ + "read", + "read_inner", + "acquire_html", + "read_inner_from_response" + ], + "interfaces": [ + "read", + "read_inner" + ] + }, + "detailed_description": "该组件负责从指定URL抓取网页内容,并通过HTML解析提取正文文本。其核心流程包括:1) 发起HTTP请求获取原始HTML;2) 处理重定向响应(状态码3xx);3) 利用scraper库选择body标签内容并去除脚本和样式;4) 在自动重定向模式下,使用LLM分析是否存在JavaScript跳转链接并递归抓取目标页面。特别地,当启用了auto_redirect且来源主机匹配时,会调用大模型服务判断是否存在window.location.href跳转,从而实现对前端重定向的智能化处理。", + "responsibilities": [ + "发起HTTP请求并安全获取网页HTML内容", + "处理HTTP重定向及递归抓取最终页面", + "利用LLM智能识别前端JavaScript重定向链接", + "清洗HTML内容并提取纯文本正文", + "集成日志记录与错误处理机制" + ], + "interfaces": [ + { + "name": "read", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "url_str", + "param_type": "&str", + "is_optional": false, + "description": "目标网页URL字符串引用" + }, + { + "name": "source_search_host", + "param_type": "Option", + "is_optional": true, + "description": "源搜索网站主机名,用于判定是否来自搜索引擎结果页" + }, + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "大语言模型配置节,用于初始化CompletionAgent" + } + ], + "return_type": "anyhow::Result<(String, String)>", + "description": "公共入口函数,启动网页读取流程" + }, + { + "name": "read_inner", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "url_str", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "auto_redirect", + "param_type": "bool", + "is_optional": false, + "description": "是否启用智能重定向检测" + }, + { + "name": "source_search_host", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result<(String, String)>", + "description": "内部实现函数,包含完整的抓取与重定向逻辑" + } + ], + "dependencies": [ + { + "name": "reqwest", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "scraper", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "html_parser", + "version": null + }, + { + "name": "spdlog", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "logging", + "version": null + }, + { + "name": "llm::llm_agent::CompletionAgent", + "path": "crates/llm/src/llm_agent.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "ai_service", + "version": null + }, + { + "name": "llm::providers::types::AITargetOption", + "path": "crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "ai_config", + "version": null + }, + { + "name": "types::LLMSection", + "path": "crates/types/src/lib.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "config_struct", + "version": null + }, + { + "name": "crate::connector", + "path": "crates/scrap/src/connector.rs", + "is_external": false, + "line_number": 9, + "dependency_type": "network_connector", + "version": null + }, + { + "name": "crate::connector::ClientOption", + "path": "crates/scrap/src/connector.rs", + "is_external": false, + "line_number": 10, + "dependency_type": "config_struct", + "version": null + }, + { + "name": "crate::search::selector_extensions::ElementSelector", + "path": "crates/scrap/src/search/selector_extensions.rs", + "is_external": false, + "line_number": 11, + "dependency_type": "extension_trait", + "version": null + }, + { + "name": "crate::search::utils::trim_html_with_script_and_style", + "path": "crates/scrap/src/search/utils.rs", + "is_external": false, + "line_number": 12, + "dependency_type": "utility_function", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 11.0, + "lines_of_code": 97, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 10.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024333, + "prompt_hash": "c58c1199b0ac1a118b33fbee882f34e8", + "token_usage": { + "input_tokens": 1807, + "output_tokens": 1291, + "total_tokens": 3098 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c60a9b128f104e5a03201e8e57e928b8.json b/.litho/cache/ai_code_insight/c60a9b128f104e5a03201e8e57e928b8.json new file mode 100644 index 0000000..08d397f --- /dev/null +++ b/.litho/cache/ai_code_insight/c60a9b128f104e5a03201e8e57e928b8.json @@ -0,0 +1,76 @@ +{ + "data": { + "code_dossier": { + "name": "hooks.client.ts", + "file_path": "app/src/hooks.client.ts", + "source_summary": "", + "code_purpose": "middleware", + "importance_score": 0.6, + "description": "Sentry客户端错误监控和会话重放初始化配置文件", + "functions": [ + "handleError" + ], + "interfaces": [] + }, + "detailed_description": "该组件用于在SvelteKit客户端环境中初始化Sentry错误追踪服务,配置了分布式追踪、会话采样率以及错误发生时的重放机制。通过集成replayIntegration实现了用户行为回放功能,并导出经过封装的handleError函数以统一处理运行时异常。", + "responsibilities": [ + "初始化Sentry客户端监控实例", + "配置错误追踪与性能监控参数", + "启用用户会话重放功能以辅助调试", + "提供标准化的错误处理函数", + "管理前端异常上报策略" + ], + "interfaces": [ + { + "name": "handleError", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "input", + "param_type": "{ error: unknown; event: import('@sentry/sveltekit').RequestEvent }", + "is_optional": false, + "description": "包含错误对象和请求事件的输入参数" + } + ], + "return_type": "void", + "description": "处理并上报捕获到的错误至Sentry服务" + } + ], + "dependencies": [ + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 21, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.095, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024682, + "prompt_hash": "c60a9b128f104e5a03201e8e57e928b8", + "token_usage": { + "input_tokens": 609, + "output_tokens": 550, + "total_tokens": 1159 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c6e2e7311d296bf3ab8e0f8679f39e74.json b/.litho/cache/ai_code_insight/c6e2e7311d296bf3ab8e0f8679f39e74.json new file mode 100644 index 0000000..f7d3a7e --- /dev/null +++ b/.litho/cache/ai_code_insight/c6e2e7311d296bf3ab8e0f8679f39e74.json @@ -0,0 +1,161 @@ +{ + "data": { + "code_dossier": { + "name": "llm_agent.rs", + "file_path": "crates/llm/src/llm_agent.rs", + "source_summary": "", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "LLM服务代理组件,封装多种LLM提供商的调用逻辑,提供统一的completion接口。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionAgent" + ] + }, + "detailed_description": "该组件实现了一个面向多种LLM(大语言模型)提供商的代理模式。通过枚举类型CompletionServiceEnums封装了Ollama、Mistral、Platform、GLM和OpenAI等不同提供商的具体服务实现,并在CompletionAgent结构体中根据配置动态选择实际的服务实例。其主要功能是屏蔽底层不同LLM提供商的接口差异,向上层提供统一的文本生成能力(completion)。构造函数new根据LLMSection中的active_provider_type字段初始化对应的服务实例,而异步方法completion则负责将用户输入的消息转发给对应提供商并返回结果。", + "responsibilities": [ + "作为多种LLM服务的统一入口,实现服务路由", + "根据配置动态初始化对应的LLM服务提供者", + "转发用户请求到具体的LLM服务并处理响应", + "封装底层LLM服务的差异性,提供一致的API接口" + ], + "interfaces": [ + { + "name": "CompletionAgent", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "LLM生成服务代理,负责调用不同提供商的completion服务。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "包含LLM配置信息的结构体" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词" + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "AI目标选项" + } + ], + "return_type": "anyhow::Result", + "description": "创建一个新的CompletionAgent实例,根据提供的LLMSection配置选择具体的LLM服务实现。" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "message", + "param_type": "String", + "is_optional": false, + "description": "用户输入的消息" + } + ], + "return_type": "anyhow::Result", + "description": "调用底层LLM服务进行文本生成,将用户消息作为prompt传递。" + }, + { + "name": "CompletionServiceEnums", + "interface_type": "enum", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "内部枚举类型,用于持有不同类型LLM服务的实例。" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_glm::GLMCompletionService", + "path": "crates/llm/src/providers/llm_glm.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_mistral::MistralQinoAgentService", + "path": "crates/llm/src/providers/llm_mistral.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_ollama::OllamaCompletionService", + "path": "crates/llm/src/providers/llm_ollama.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "path": "crates/llm/src/providers/llm_openaibase_like.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_platform::PlatformAgentService", + "path": "crates/llm/src/providers/llm_platform.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": "crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 8, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 82, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024278, + "prompt_hash": "c6e2e7311d296bf3ab8e0f8679f39e74", + "token_usage": { + "input_tokens": 1280, + "output_tokens": 1244, + "total_tokens": 2524 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c90166d7b174ef9ba698081eac51e92f.json b/.litho/cache/ai_code_insight/c90166d7b174ef9ba698081eac51e92f.json new file mode 100644 index 0000000..9fcbb28 --- /dev/null +++ b/.litho/cache/ai_code_insight/c90166d7b174ef9ba698081eac51e92f.json @@ -0,0 +1,55 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/feed_api_rs/src/features/mod.rs", + "code_purpose": "api", + "importance_score": 0.6, + "description": "模块声明文件,用于组织和导出 feed_api_rs 功能特性子模块", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个 Rust 模块定义文件(mod.rs),其主要作用是作为功能特性的组织入口,通过 `pub mod` 声明了两个公共子模块:`api` 和 `impl_default`。它本身不包含具体实现逻辑或接口定义,而是承担命名空间管理和模块结构划分的角色,使得外部可以通过 `features::api` 和 `features::impl_default` 路径访问下层功能。", + "responsibilities": [ + "组织并导出 feed 相关的功能子模块", + "提供清晰的模块层次结构以支持代码可维护性", + "控制子模块的可见性与访问权限" + ], + "interfaces": [], + "dependencies": [ + { + "name": "api", + "path": "crates/feed_api_rs/src/features/api", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "impl_default", + "path": "crates/feed_api_rs/src/features/impl_default", + "is_external": false, + "line_number": 2, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 2, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805862, + "prompt_hash": "c90166d7b174ef9ba698081eac51e92f", + "token_usage": { + "input_tokens": 412, + "output_tokens": 460, + "total_tokens": 872 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/c945e65bc2a07dbce8bce5ab0d808a21.json b/.litho/cache/ai_code_insight/c945e65bc2a07dbce8bce5ab0d808a21.json new file mode 100644 index 0000000..c49037b --- /dev/null +++ b/.litho/cache/ai_code_insight/c945e65bc2a07dbce8bce5ab0d808a21.json @@ -0,0 +1,188 @@ +{ + "data": { + "code_dossier": { + "name": "llm_mistral.rs", + "file_path": "crates/llm/src/providers/llm_mistral.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "Mistral Qino Agent服务,基于Mistral AI API实现的LLM代理,封装了与Mistral API的通信逻辑。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了针对Mistral AI平台的智能Agent服务,通过适配OpenAI类接口的方式,封装了与Mistral API的交互。它使用OpenAILikeCompletionService作为内部实现,构造符合Mistral API规范的请求,并通过reqwest客户端发送请求。主要功能包括初始化服务配置(API地址、密钥、模型ID)和执行聊天补全请求。系统提示词(system_prompt)在初始化时注入,用于指导LLM的行为。", + "responsibilities": [ + "作为Mistral AI服务的客户端代理", + "封装Mistral API的调用细节", + "提供统一的CompletionService接口", + "管理API连接配置和认证信息", + "转发补全请求并处理响应" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了补全服务的标准接口,此组件实现了该接口以提供具体功能。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "初始化Agent时使用的系统提示词" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "目标选项参数,当前未使用" + } + ], + "return_type": "anyhow::Result", + "description": "构造函数,用于创建MistralQinoAgentService实例。" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入的对话内容" + } + ], + "return_type": "anyhow::Result", + "description": "异步执行补全请求,返回LLM生成的响应文本。" + }, + { + "name": "RequestParameters", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "messages", + "param_type": "Vec", + "is_optional": false, + "description": null + }, + { + "name": "agent_id", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "用于序列化为JSON的请求参数结构体。" + }, + { + "name": "Message", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "role", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "表示对话消息的结构体,包含角色和内容。" + }, + { + "name": "MistralQinoAgentService", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "inner", + "param_type": "OpenAILikeCompletionService", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "Mistral Agent服务的主要结构体,包装了OpenAI类服务实现。" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::OpenAILLMProvider", + "path": "./types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "path": "./crates/llm/src/providers/llm_openaibase_like.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "service", + "version": null + }, + { + "name": "crate::providers::types::{AITargetOption, CompletionService}", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 50, + "number_of_functions": 2, + "number_of_classes": 3, + "depth_of_inheritance": 0, + "coupling_factor": 0.4, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801139, + "prompt_hash": "c945e65bc2a07dbce8bce5ab0d808a21", + "token_usage": { + "input_tokens": 847, + "output_tokens": 1218, + "total_tokens": 2065 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cb907ee0f1aeb477c494af7dcd643a7a.json b/.litho/cache/ai_code_insight/cb907ee0f1aeb477c494af7dcd643a7a.json new file mode 100644 index 0000000..a2edc23 --- /dev/null +++ b/.litho/cache/ai_code_insight/cb907ee0f1aeb477c494af7dcd643a7a.json @@ -0,0 +1,36 @@ +{ + "data": { + "code_dossier": { + "name": "FeedEditPanel.svelte", + "file_path": "app/src/routes/main/widgets/FeedEditPanel.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件为空,未包含任何代码实现。无法确定其具体功能和业务逻辑。", + "responsibilities": [ + "未知:组件无内容,职责无法识别" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805822, + "prompt_hash": "cb907ee0f1aeb477c494af7dcd643a7a", + "token_usage": { + "input_tokens": 407, + "output_tokens": 182, + "total_tokens": 589 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cc353396746ffeee557b1e15e395cdcf.json b/.litho/cache/ai_code_insight/cc353396746ffeee557b1e15e395cdcf.json new file mode 100644 index 0000000..84fd7d2 --- /dev/null +++ b/.litho/cache/ai_code_insight/cc353396746ffeee557b1e15e395cdcf.json @@ -0,0 +1,39 @@ +{ + "data": { + "code_dossier": { + "name": "en.json", + "file_path": "app/src/lib/i18n/locales/en.json", + "code_purpose": "config", + "importance_score": 0.6, + "description": "English language localization file containing all UI text strings for the application, organized by functional modules.", + "functions": [], + "interfaces": [] + }, + "detailed_description": "This component is a JSON-based internationalization (i18n) configuration file that provides English translations for the entire application's user interface. It contains structured key-value pairs grouped under semantic namespaces such as 'common', 'main', 'reader', 'aisprite', 'settings', etc., each corresponding to different parts of the application. The values include UI labels, prompts, tooltips, error messages, and form placeholders used throughout the app. This file enables multilingual support by allowing runtime switching between language packs without modifying source code. It supports dynamic content insertion via template placeholders (e.g., {name}, {length}) for contextual messaging in dialogs and notifications.", + "responsibilities": [ + "Provide English translations for all user-facing text in the application", + "Support dynamic message templating with variable interpolation for context-aware UI messages", + "Organize localization strings by functional module (e.g., settings, reader, feeds) for maintainability", + "Enable consistent UI text rendering across components through centralized string management" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 183, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.1, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758806009, + "prompt_hash": "cc353396746ffeee557b1e15e395cdcf", + "token_usage": { + "input_tokens": 2316, + "output_tokens": 417, + "total_tokens": 2733 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cc9a86a891aafdf33ec771553270a43f.json b/.litho/cache/ai_code_insight/cc9a86a891aafdf33ec771553270a43f.json new file mode 100644 index 0000000..5a60eb8 --- /dev/null +++ b/.litho/cache/ai_code_insight/cc9a86a891aafdf33ec771553270a43f.json @@ -0,0 +1,89 @@ +{ + "data": { + "code_dossier": { + "name": "llm_endpoint.rs", + "file_path": "crates/types/src/llm_endpoint.rs", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.8, + "description": "定义LLM服务端点结构,支持Ollama API兼容的聊天和生成接口。", + "functions": [ + "get_api_chat_completion", + "get_api_generate_completion" + ], + "interfaces": [ + "LLMEndPoint" + ] + }, + "detailed_description": "该组件定义了与LLM(如Ollama)交互所需的端点配置结构体LLMEndPoint,包含API基础URL、聊天和生成接口路径以及模型名称。通过实现Default trait提供本地开发默认配置,并提供两个方法用于拼接完整的API请求地址。主要用于解耦LLM服务配置与具体调用逻辑,提升可配置性和可测试性。", + "responsibilities": [ + "定义LLM服务的连接配置参数", + "提供默认本地Ollama服务配置", + "构建完整的API请求URL", + "支持序列化与反序列化以便配置传递", + "保持与Ollama API规范的兼容性" + ], + "interfaces": [ + { + "name": "LLMEndPoint", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "api_base_url", + "param_type": "String", + "is_optional": false, + "description": "服务基地址" + }, + { + "name": "api_path_generate_completion", + "param_type": "String", + "is_optional": false, + "description": "Completion接口的path" + }, + { + "name": "api_path_chat_completion", + "param_type": "String", + "is_optional": false, + "description": "Chat接口的path" + }, + { + "name": "model", + "param_type": "String", + "is_optional": false, + "description": "模型名称" + } + ], + "return_type": null, + "description": "表示LLM服务端点的配置信息" + } + ], + "dependencies": [ + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "serialization", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 55, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.2, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024231, + "prompt_hash": "cc9a86a891aafdf33ec771553270a43f", + "token_usage": { + "input_tokens": 846, + "output_tokens": 610, + "total_tokens": 1456 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cca07707e11e5cc5c434ca48a0dd83e9.json b/.litho/cache/ai_code_insight/cca07707e11e5cc5c434ca48a0dd83e9.json new file mode 100644 index 0000000..4a881e9 --- /dev/null +++ b/.litho/cache/ai_code_insight/cca07707e11e5cc5c434ca48a0dd83e9.json @@ -0,0 +1,173 @@ +{ + "data": { + "code_dossier": { + "name": "llm_processor.rs", + "file_path": "crates/intelligent/src/article_processor/llm_processor.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "基于LLM的文章处理器,通过CompletionAgent与大模型交互,执行文章内容的智能处理和转换。", + "functions": [ + "new", + "process" + ], + "interfaces": [ + "IArticleProcessor", + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件是一个智能Agent,负责利用大语言模型(LLM)对文章内容进行处理。它封装了CompletionAgent实例,并通过用户指令提示词(user_prompt_command)构造完整的对话上下文,调用LLM生成改写后的内容。支持根据系统或指定语言设置输出语种,适用于多语言场景下的内容智能化处理任务。", + "responsibilities": [ + "作为LLM驱动的文章处理核心Agent", + "实现IArticleProcessor接口以支持统一调度流程", + "构建包含原文、指令和语言要求的完整prompt用于LLM交互", + "管理CompletionAgent生命周期并执行异步内容生成", + "处理多语言需求,自动识别系统locale或使用指定语言" + ], + "interfaces": [ + { + "name": "IArticleProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "文章处理器通用接口,定义process方法用于处理文章" + }, + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "LLM配置节" + } + ], + "return_type": "anyhow::Result", + "description": "预设处理器创建trait,用于工厂模式初始化处理器实例" + }, + { + "name": "process", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "input", + "param_type": "&Article", + "is_optional": false, + "description": null + }, + { + "name": "opt", + "param_type": "LLMInstructOption", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result
", + "description": "异步处理输入文章并返回结果" + }, + { + "name": "new", + "interface_type": "constructor", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": null + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "user_prompt_command", + "param_type": "String", + "is_optional": false, + "description": null + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "构造新的ArticleLLMProcessor实例" + } + ], + "dependencies": [ + { + "name": "llm::llm_agent::CompletionAgent", + "path": "llm::llm_agent::CompletionAgent", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types::AITargetOption", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "types::Article", + "path": "types::Article", + "is_external": false, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMInstructOption", + "path": "types::LLMInstructOption", + "is_external": false, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types::LLMSection", + "is_external": false, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "sys_locale::get_locale", + "path": "sys_locale::get_locale", + "is_external": false, + "line_number": 5, + "dependency_type": "function", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 61, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805375, + "prompt_hash": "cca07707e11e5cc5c434ca48a0dd83e9", + "token_usage": { + "input_tokens": 1013, + "output_tokens": 1102, + "total_tokens": 2115 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cd39ba3772e0585b6b1349549060b61b.json b/.litho/cache/ai_code_insight/cd39ba3772e0585b6b1349549060b61b.json new file mode 100644 index 0000000..c1a148d --- /dev/null +++ b/.litho/cache/ai_code_insight/cd39ba3772e0585b6b1349549060b61b.json @@ -0,0 +1,60 @@ +{ + "data": { + "code_dossier": { + "name": "state.rs", + "file_path": "crates/tauri-plugin-feed-api/src/state.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义混合运行时状态结构,封装功能API实现。", + "functions": [], + "interfaces": [ + "HybridRuntimeState" + ] + }, + "detailed_description": "该组件定义了一个名为 HybridRuntimeState 的结构体,用于在 Tauri 插件中持有 feed_api_rs 功能模块的实现实例。其主要作用是作为共享状态在不同组件间传递,使得前端或后端逻辑可以安全地访问底层功能 API。目前仅包含一个字段 features_api,类型为 FeaturesAPIImpl,来自 feed_api_rs crate 的默认实现模块。", + "responsibilities": [ + "封装底层功能API的实现实例", + "作为Tauri应用中的共享状态载体", + "提供类型安全的状态结构定义", + "解耦业务逻辑与具体API实现" + ], + "interfaces": [ + { + "name": "HybridRuntimeState", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "混合运行时状态结构,用于在Tauri插件中共享FeaturesAPIImpl实例。" + } + ], + "dependencies": [ + { + "name": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "path": "feed_api_rs::features::impl_default", + "is_external": true, + "line_number": 1, + "dependency_type": "struct", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 5, + "number_of_functions": 0, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1759024648, + "prompt_hash": "cd39ba3772e0585b6b1349549060b61b", + "token_usage": { + "input_tokens": 447, + "output_tokens": 501, + "total_tokens": 948 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cd42fa388f1ab964e886320df30e3fa7.json b/.litho/cache/ai_code_insight/cd42fa388f1ab964e886320df30e3fa7.json new file mode 100644 index 0000000..e3a539b --- /dev/null +++ b/.litho/cache/ai_code_insight/cd42fa388f1ab964e886320df30e3fa7.json @@ -0,0 +1,176 @@ +{ + "data": { + "code_dossier": { + "name": "llm_platform.rs", + "file_path": "crates/llm/src/providers/llm_platform.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "实现基于外部平台的LLM智能Agent服务,通过HTTP请求与远程LLM平台交互,提供文本补全功能。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了PlatformAgentService结构体,作为连接到外部LLM平台的智能代理。它使用reqwest客户端发送带有提示词的POST请求至远程服务,并返回生成的文本响应。当前硬编码了空URL,需要在运行时配置具体端点。组件遵循异步编程模型,支持非阻塞I/O操作,适用于高并发场景。", + "responsibilities": [ + "初始化LLM平台客户端连接", + "封装LLM请求参数", + "执行远程文本补全请求", + "处理HTTP通信异常", + "实现统一的CompletionService接口" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义LLM补全服务的标准接口" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&PlatformLLMProvider", + "is_optional": false, + "description": "平台配置信息" + }, + { + "name": "_system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词(当前未使用)" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "AI目标选项(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "创建PlatformAgentService实例" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "prompt", + "param_type": "String", + "is_optional": false, + "description": "用户输入提示" + } + ], + "return_type": "anyhow::Result", + "description": "执行文本补全请求" + }, + { + "name": "RequestParameters", + "interface_type": "struct", + "visibility": "pub", + "parameters": [ + { + "name": "prompt", + "param_type": "String", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "序列化为JSON的请求体参数" + }, + { + "name": "PlatformAgentService", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "LLM平台代理服务主结构体" + }, + { + "name": "config", + "interface_type": "field", + "visibility": "private", + "parameters": [], + "return_type": "PlatformLLMProvider", + "description": "平台配置(当前标记为dead_code)" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "serde::Serialize", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::PlatformLLMProvider", + "path": "types", + "is_external": false, + "line_number": 4, + "dependency_type": "type_dependency", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "module_dependency", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "type_dependency", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": null, + "is_external": false, + "line_number": 7, + "dependency_type": "trait_dependency", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 45, + "number_of_functions": 2, + "number_of_classes": 2, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801109, + "prompt_hash": "cd42fa388f1ab964e886320df30e3fa7", + "token_usage": { + "input_tokens": 756, + "output_tokens": 1059, + "total_tokens": 1815 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cdf2f03db5ef55d8a85e74a24485a76d.json b/.litho/cache/ai_code_insight/cdf2f03db5ef55d8a85e74a24485a76d.json new file mode 100644 index 0000000..70c92ba --- /dev/null +++ b/.litho/cache/ai_code_insight/cdf2f03db5ef55d8a85e74a24485a76d.json @@ -0,0 +1,145 @@ +{ + "data": { + "code_dossier": { + "name": "llm_openaibase_like.rs", + "file_path": "crates/llm/src/providers/llm_openaibase_like.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "实现与OpenAI兼容API的LLM服务调用,封装请求构造、HTTP通信和响应解析逻辑", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionService" + ] + }, + "detailed_description": "该组件实现了与OpenAI风格API兼容的语言模型调用服务。它负责构造符合OpenAI API规范的请求体,包含系统提示和用户消息,通过HTTP客户端发送到指定的API端点,并解析返回的JSON响应以提取生成的文本内容。组件使用reqwest进行异步HTTP通信,利用serde进行序列化和反序列化,依赖外部connector模块创建配置好的HTTP客户端实例。", + "responsibilities": [ + "封装OpenAI兼容API的请求参数构造逻辑", + "管理LLM服务的配置信息(API地址、密钥、模型名称)", + "执行异步HTTP请求并与远程LLM服务通信", + "解析API响应并提取生成的文本内容", + "实现统一的CompletionService接口供上层调用" + ], + "interfaces": [ + { + "name": "CompletionService", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义语言模型补全服务的标准接口" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "config", + "param_type": "&OpenAILLMProvider", + "is_optional": false, + "description": "LLM提供者配置" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "系统提示词" + }, + { + "name": "_options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "AI目标选项(当前未使用)" + } + ], + "return_type": "anyhow::Result", + "description": "创建新的OpenAI兼容服务实例" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "content", + "param_type": "String", + "is_optional": false, + "description": "用户输入内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行补全请求并返回生成的文本" + } + ], + "dependencies": [ + { + "name": "reqwest::Client", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "http_client", + "version": null + }, + { + "name": "serde", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "serialization", + "version": null + }, + { + "name": "types::OpenAILLMProvider", + "path": "types::OpenAILLMProvider", + "is_external": false, + "line_number": 3, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + }, + { + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": "./crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 84, + "number_of_functions": 2, + "number_of_classes": 5, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801118, + "prompt_hash": "cdf2f03db5ef55d8a85e74a24485a76d", + "token_usage": { + "input_tokens": 1042, + "output_tokens": 989, + "total_tokens": 2031 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ceebe79b5444b6ad84fddc50e7af4c00.json b/.litho/cache/ai_code_insight/ceebe79b5444b6ad84fddc50e7af4c00.json new file mode 100644 index 0000000..3c0734f --- /dev/null +++ b/.litho/cache/ai_code_insight/ceebe79b5444b6ad84fddc50e7af4c00.json @@ -0,0 +1,116 @@ +{ + "data": { + "code_dossier": { + "name": "ArticleRenderWidget.svelte", + "file_path": "app/src/lib/widgets/ArticleRenderWidget.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "渲染文章内容的Svelte组件,支持HTML和Markdown两种格式。", + "functions": [], + "interfaces": [ + "ArticleRenderProps", + "ArticleRenderType" + ] + }, + "detailed_description": "该组件用于渲染文章内容,根据输入内容判断是HTML还是Markdown格式,并相应地使用内联HTML或Markdown子组件进行渲染。对于HTML内容,它绑定一个div容器并动态插入净化后的HTML。同时,在挂载时添加点击事件监听器,拦截所有锚点链接的默认跳转行为,并通过featuresApi.open_article_external打开外部链接,确保应用内导航控制。", + "responsibilities": [ + "解析输入内容类型(HTML或Markdown)", + "净化HTML内容以移除代码块包装", + "渲染文章内容到UI界面", + "拦截并处理内部链接点击事件", + "管理DOM事件监听器的生命周期" + ], + "interfaces": [ + { + "name": "ArticleRenderProps", + "interface_type": "type", + "visibility": "public", + "parameters": [ + { + "name": "value", + "param_type": "string", + "is_optional": false, + "description": "要渲染的文章原始内容" + } + ], + "return_type": null, + "description": "定义传递给组件的属性结构" + }, + { + "name": "ArticleRenderType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "表示文章渲染类型的联合类型,可能是'html'或'markdown'" + } + ], + "dependencies": [ + { + "name": "ArticleRenderProps", + "path": "./types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "ArticleRenderType", + "path": "./types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "Markdown", + "path": "./Markdown.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "component", + "version": null + }, + { + "name": "removeCodeBlockWrapper", + "path": "$lib/utils/text", + "is_external": false, + "line_number": 4, + "dependency_type": "function", + "version": null + }, + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 5, + "dependency_type": "service", + "version": null + }, + { + "name": "onMount", + "path": "svelte", + "is_external": true, + "line_number": 6, + "dependency_type": "lifecycle", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 39, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805765, + "prompt_hash": "ceebe79b5444b6ad84fddc50e7af4c00", + "token_usage": { + "input_tokens": 805, + "output_tokens": 768, + "total_tokens": 1573 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/cf5c8c7340c35a40db8c879ac1f24695.json b/.litho/cache/ai_code_insight/cf5c8c7340c35a40db8c879ac1f24695.json new file mode 100644 index 0000000..46f0b9d --- /dev/null +++ b/.litho/cache/ai_code_insight/cf5c8c7340c35a40db8c879ac1f24695.json @@ -0,0 +1,250 @@ +{ + "data": { + "code_dossier": { + "name": "operator.rs", + "file_path": "crates/recorder/src/operator.rs", + "source_summary": "", + "code_purpose": "database", + "importance_score": 0.8, + "description": "负责管理与SQLite数据库的连接,并提供对文章记录(entity::article_record)的CRUD操作封装。支持条件查询、分页、计数、存在性检查等核心数据访问功能。", + "functions": [ + "new", + "ensure_db_initialized", + "create_table_if_not_existed", + "initialize", + "count", + "dispose", + "insert", + "update", + "query", + "query_by_filters", + "exists", + "query_without_filter", + "query_by_id", + "delete" + ], + "interfaces": [ + "Operator" + ] + }, + "detailed_description": "该组件是Recorder模块中用于持久化文章记录的核心数据库操作器。它封装了SeaORM框架对`article_record`实体的访问逻辑,通过内部持有可选的DatabaseConnection实例实现连接管理。组件在初始化时建立到SQLite数据库的连接池,并确保`t_article_record`表的存在。其主要行为包括:插入新文章记录、更新已有记录、根据ID或复杂过滤条件查询记录(支持分页和排序)、判断记录是否存在、删除记录以及获取总数量。所有操作均以异步方式执行,符合Rust异步编程模型。组件设计为单例模式使用,需先调用initialize完成初始化后方可执行其他操作。", + "responsibilities": [ + "管理数据库连接生命周期(初始化、关闭)", + "确保数据表结构存在", + "提供对文章记录的增删改查操作接口", + "支持基于条件和分页的数据查询", + "保证数据操作的安全性和事务一致性" + ], + "interfaces": [ + { + "name": "Operator", + "interface_type": "struct", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "数据库操作器主结构体,封装数据库连接与操作方法" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "Operator", + "description": "创建一个新的Operator实例,初始状态无数据库连接" + }, + { + "name": "initialize", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result<()>", + "description": "异步初始化数据库连接并创建必要数据表" + }, + { + "name": "dispose", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result<()>", + "description": "异步释放数据库连接资源" + }, + { + "name": "insert", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "entity", + "param_type": "article_record::ActiveModel", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result<()>", + "description": "插入一条新的文章记录" + }, + { + "name": "update", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "entity", + "param_type": "article_record::ActiveModel", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "更新一条已有文章记录并返回更新后的模型" + }, + { + "name": "query", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "offset", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "limit", + "param_type": "Option", + "is_optional": true, + "description": null + }, + { + "name": "filter", + "param_type": "F", + "is_optional": false, + "description": "实现了IntoCondition trait的过滤条件" + } + ], + "return_type": "anyhow::Result>", + "description": "根据过滤条件分页查询文章记录,按发布时间和ID降序排列" + }, + { + "name": "count", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result", + "description": "获取文章记录总数" + }, + { + "name": "exists", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "filter", + "param_type": "F", + "is_optional": false, + "description": "实现了IntoCondition trait的过滤条件" + } + ], + "return_type": "anyhow::Result", + "description": "检查满足特定条件的文章记录是否存在" + }, + { + "name": "query_by_id", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "id", + "param_type": "i32", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result>", + "description": "根据ID精确查询单条文章记录" + }, + { + "name": "delete", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "entity", + "param_type": "article_record::ActiveModel", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result", + "description": "删除指定的文章记录" + } + ], + "dependencies": [ + { + "name": "std::time::Duration", + "path": null, + "is_external": false, + "line_number": null, + "dependency_type": "std", + "version": null + }, + { + "name": "sea_orm", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "anyhow", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "log", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "crate", + "version": null + }, + { + "name": "article_record", + "path": "crates/recorder/src/entity/article_record.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + }, + { + "name": "get_appdata_articles", + "path": "crates/recorder/src/path.rs", + "is_external": false, + "line_number": null, + "dependency_type": "local", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 160, + "number_of_functions": 14, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024391, + "prompt_hash": "cf5c8c7340c35a40db8c879ac1f24695", + "token_usage": { + "input_tokens": 1938, + "output_tokens": 1705, + "total_tokens": 3643 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/d3587c6595fba24b01396252e690b278.json b/.litho/cache/ai_code_insight/d3587c6595fba24b01396252e690b278.json new file mode 100644 index 0000000..6484374 --- /dev/null +++ b/.litho/cache/ai_code_insight/d3587c6595fba24b01396252e690b278.json @@ -0,0 +1,158 @@ +{ + "data": { + "code_dossier": { + "name": "task.rs", + "file_path": "crates/feed_api_rs/src/startup/task.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": "定义了初始化任务的执行器和状态管理,用于异步启动并监控系统启动阶段的任务。", + "functions": [ + "start", + "dump" + ], + "interfaces": [ + "TaskInitializer", + "InitTask" + ] + }, + "detailed_description": "该组件实现了系统启动过程中关键任务的异步执行与状态追踪功能。通过 `TaskInitializer` trait 提供统一接口,允许对任意返回 `anyhow::Result` 的异步函数进行封装执行,并记录执行耗时、状态(运行中、完成、错误)以及结果数据。`InitTask` 结构体作为具体实现,具备默认初始化能力,支持在执行失败时记录错误日志,在成功时输出耗时信息,增强了可观测性。", + "responsibilities": [ + "封装异步任务的执行流程,确保统一的启动逻辑", + "监控任务执行时间并记录性能指标", + "维护任务的生命周期状态(未启动、运行中、完成、出错)", + "提供任务状态转储接口以供外部查询", + "处理任务执行中的异常并进行日志记录" + ], + "interfaces": [ + { + "name": "TaskInitializer", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "TResult", + "param_type": "generic", + "is_optional": false, + "description": "任务结果的包装类型" + }, + { + "name": "TData", + "param_type": "generic", + "is_optional": false, + "description": "任务实际产出的数据类型" + } + ], + "return_type": null, + "description": "定义任务初始化器的核心行为,包括启动任务和导出状态快照" + }, + { + "name": "start", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "task_name", + "param_type": "&str", + "is_optional": false, + "description": "任务名称,用于日志标记" + }, + { + "name": "function", + "param_type": "F", + "is_optional": false, + "description": "返回 Future 的可调用对象" + } + ], + "return_type": "impl Future>", + "description": "异步执行传入的任务闭包,自动记录耗时和状态变化" + }, + { + "name": "dump", + "interface_type": "method", + "visibility": "public", + "parameters": [], + "return_type": "TaskDump", + "description": "导出当前任务的状态摘要" + }, + { + "name": "InitTask", + "interface_type": "struct", + "visibility": "public", + "parameters": [ + { + "name": "result", + "param_type": "Option", + "is_optional": true, + "description": "任务执行结果" + }, + { + "name": "task_cost", + "param_type": "u128", + "is_optional": false, + "description": "任务执行耗时(毫秒)" + }, + { + "name": "task_status", + "param_type": "Status", + "is_optional": false, + "description": "当前任务状态" + } + ], + "return_type": null, + "description": "具体任务执行容器,持有执行结果、耗时和状态" + } + ], + "dependencies": [ + { + "name": "std::future::Future", + "path": "std::future::Future", + "is_external": false, + "line_number": 1, + "dependency_type": "std", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": 3, + "dependency_type": "crate", + "version": null + }, + { + "name": "tokio::time::Instant", + "path": "tokio::time::Instant", + "is_external": true, + "line_number": 4, + "dependency_type": "crate", + "version": null + }, + { + "name": "anyhow::Result", + "path": "anyhow", + "is_external": true, + "line_number": 6, + "dependency_type": "crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 64, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.57, + "cohesion_score": 0.88 + } + }, + "timestamp": 1759024313, + "prompt_hash": "d3587c6595fba24b01396252e690b278", + "token_usage": { + "input_tokens": 867, + "output_tokens": 1130, + "total_tokens": 1997 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/d6132493918884adf65900c81985801d.json b/.litho/cache/ai_code_insight/d6132493918884adf65900c81985801d.json new file mode 100644 index 0000000..c25ef03 --- /dev/null +++ b/.litho/cache/ai_code_insight/d6132493918884adf65900c81985801d.json @@ -0,0 +1,180 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/articles/list/index.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "文章列表状态管理Store,负责聚合文章数据、处理分页加载、搜索过滤及与后端服务交互。基于Svelte的响应式系统实现。", + "functions": [ + "create", + "generateTaskIdForUpdateFeed", + "refresh", + "updateFeeds", + "loadMore", + "notifyDatasourceUpdated", + "attachInitLoadingFuture" + ], + "interfaces": [ + "StoreType", + "Associations" + ] + }, + "detailed_description": "该组件是Svelte应用中的核心状态管理模块(Store),用于管理文章列表的展示逻辑。它封装了文章分组、分页加载、搜索过滤、数据刷新等关键功能。通过依赖注入方式关联tasks和search两个外部store,形成协作关系。使用$state和$derived实现响应式状态,利用$effect监听搜索条件变化并触发内容检索。支持初始化加载、连续加载更多、强制刷新、更新订阅源等操作,并通过loading store管理不同场景下的加载状态。整体采用工厂模式(create函数)生成具名store实例,符合Svelte stores规范。", + "responsibilities": [ + "管理文章列表的分组显示状态(按发布时间聚合)", + "协调与后端API的交互(加载、刷新、更新feed内容)", + "处理分页逻辑(初始加载与滚动加载更多)", + "响应搜索输入变化并更新过滤结果", + "维护多个加载状态(初始化、连续加载、过滤加载)" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义文章列表Store的完整接口结构,包含状态字段和行为方法" + }, + { + "name": "Associations", + "interface_type": "type", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "内部类型,定义该Store所依赖的其他Store引用集合" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "associations", + "param_type": "Associations", + "is_optional": false, + "description": "注入的依赖Store集合" + } + ], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个具备完整功能的文章列表Store实例" + }, + { + "name": "generateTaskIdForUpdateFeed", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "associatedFeedId", + "param_type": "string", + "is_optional": false, + "description": "目标Feed的ID" + } + ], + "return_type": "string", + "description": "生成用于任务追踪的唯一任务ID" + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "isSpecifyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "tick", + "path": "svelte", + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + }, + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "ArticlesGroup", + "path": "../../../widgets/types", + "is_external": false, + "line_number": 4, + "dependency_type": "import", + "version": null + }, + { + "name": "createLoading", + "path": "../../loading.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "import", + "version": null + }, + { + "name": "Status", + "path": "../../loading.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "import", + "version": null + }, + { + "name": "LoadingStore", + "path": "../../loading.svelte", + "is_external": false, + "line_number": 6, + "dependency_type": "import", + "version": null + }, + { + "name": "SearchStore", + "path": "../search/index.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "import", + "version": null + }, + { + "name": "TasksStoreType", + "path": "../../tasks.svelte", + "is_external": false, + "line_number": 8, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 11.0, + "lines_of_code": 221, + "number_of_functions": 7, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.875, + "cohesion_score": 0.72 + } + }, + "timestamp": 1759024164, + "prompt_hash": "d6132493918884adf65900c81985801d", + "token_usage": { + "input_tokens": 2188, + "output_tokens": 1280, + "total_tokens": 3468 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/d643935497bac76af9b36320b1325eba.json b/.litho/cache/ai_code_insight/d643935497bac76af9b36320b1325eba.json new file mode 100644 index 0000000..44ae9f6 --- /dev/null +++ b/.litho/cache/ai_code_insight/d643935497bac76af9b36320b1325eba.json @@ -0,0 +1,80 @@ +{ + "data": { + "code_dossier": { + "name": "impl.ts", + "file_path": "app/src/lib/hybrid-apis/feed/impl.ts", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.8, + "description": "实现了 Feeds 功能相关的 API 接口,封装了与后端 Tauri 模块的通信逻辑,提供 RSS/信息流管理、文章操作、AI 助手交互等功能。", + "functions": [ + "isSpecifyFeed", + "isRecentFamilyFeed" + ], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件是 FeaturesAPI 的具体实现类 FeaturesAPIImpl,通过调用 Tauri 的通用 call 方法与原生后端进行异步通信。它提供了对信息流(Feeds)的完整 CRUD 操作支持,包括包管理、订阅增删改查、内容更新与读取;同时集成了应用配置管理、Ollama AI 引擎控制、外部链接打开、文本抓取、 favorites 标记、全文搜索及基于文章的智能对话功能。此外,还定义了特殊虚拟 feed ID 常量集合,并提供了判断 feed 类型的辅助函数。整体作为前端与本地后端之间的桥梁,承担混合 API 调用的核心职责。", + "responsibilities": [ + "封装 Tauri RPC 调用以实现 Feeds 相关业务逻辑", + "提供统一接口用于管理信息流订阅与内容同步", + "支持文章的阅读状态、收藏状态和内容检索操作", + "集成 AI 功能如 Ollama 控制与文章智能问答", + "导出工具函数以识别特定类型的 Feed" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "class", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了所有 Feeds 功能所需的方法契约,由 FeaturesAPIImpl 实现" + } + ], + "dependencies": [ + { + "name": "../tauri-regular", + "path": "app/src/lib/hybrid-apis/feed/../tauri-regular", + "is_external": false, + "line_number": 1, + "dependency_type": "module_import", + "version": null + }, + { + "name": "./api", + "path": "app/src/lib/hybrid-apis/feed/api", + "is_external": false, + "line_number": 3, + "dependency_type": "module_import", + "version": null + }, + { + "name": "./types", + "path": "app/src/lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 4, + "dependency_type": "module_import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 164, + "number_of_functions": 20, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024444, + "prompt_hash": "d643935497bac76af9b36320b1325eba", + "token_usage": { + "input_tokens": 1457, + "output_tokens": 778, + "total_tokens": 2235 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/d934c7110198737cb6db6d97841ee982.json b/.litho/cache/ai_code_insight/d934c7110198737cb6db6d97841ee982.json new file mode 100644 index 0000000..5f629cb --- /dev/null +++ b/.litho/cache/ai_code_insight/d934c7110198737cb6db6d97841ee982.json @@ -0,0 +1,74 @@ +{ + "data": { + "code_dossier": { + "name": "+layout.ts", + "file_path": "app/src/routes/+layout.ts", + "code_purpose": "router", + "importance_score": 0.6, + "description": "SvelteKit布局加载器,负责国际化初始化和区域设置配置", + "functions": [ + "load" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit应用的布局级加载器(+layout.ts),在路由层级上为所有子页面提供共享的加载逻辑。其主要功能是在客户端环境中初始化国际化(i18n)支持:导入并执行i18n初始化模块,检测浏览器语言环境,并将其设置为当前locale,然后等待本地化资源加载完成。prerender标志设为true表明此布局支持静态预渲染,有利于SEO和性能优化。", + "responsibilities": [ + "初始化应用的国际化系统", + "根据浏览器语言环境设置默认区域设置", + "确保本地化资源在页面渲染前已准备就绪", + "支持静态预渲染以提升性能" + ], + "interfaces": [], + "dependencies": [ + { + "name": "$lib/i18n", + "path": "$lib/i18n", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": true, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 3, + "dependency_type": "library", + "version": null + }, + { + "name": "./$types", + "path": "./$types", + "is_external": false, + "line_number": 4, + "dependency_type": "generated", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 13, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.3076923076923077, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758806034, + "prompt_hash": "d934c7110198737cb6db6d97841ee982", + "token_usage": { + "input_tokens": 488, + "output_tokens": 555, + "total_tokens": 1043 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/d93af0f5eff898e99fdc34ac5700bb28.json b/.litho/cache/ai_code_insight/d93af0f5eff898e99fdc34ac5700bb28.json new file mode 100644 index 0000000..eeb27da --- /dev/null +++ b/.litho/cache/ai_code_insight/d93af0f5eff898e99fdc34ac5700bb28.json @@ -0,0 +1,49 @@ +{ + "data": { + "code_dossier": { + "name": "default.json", + "file_path": "app/src-tauri/capabilities/default.json", + "code_purpose": "config", + "importance_score": 0.6, + "description": "Capability configuration for the In-App window in a Tauri application, defining allowed windows and permissions.", + "functions": [], + "interfaces": [] + }, + "detailed_description": "This configuration file defines a capability set named 'default' for a Tauri desktop application. It specifies which windows are available in the app (such as main, settings, about, and various feed-related windows) and grants a comprehensive set of permissions required for core functionality including window management, webview control, event handling, shell operations, clipboard access, feed API interaction, autostart features, OS integration, and dialog usage. The schema reference ensures structural validation against the desktop-schema.json specification.", + "responsibilities": [ + "Define the set of available application windows", + "Declare essential runtime permissions for core application features", + "Enforce security by explicitly listing permitted capabilities", + "Provide configuration for role-based access control in the Tauri framework", + "Enable modular capability management through JSON-based schema" + ], + "interfaces": [], + "dependencies": [ + { + "name": "../gen/schemas/desktop-schema.json", + "path": "../gen/schemas/desktop-schema.json", + "is_external": false, + "line_number": 2, + "dependency_type": "schema", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 43, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.023, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805938, + "prompt_hash": "d93af0f5eff898e99fdc34ac5700bb28", + "token_usage": { + "input_tokens": 667, + "output_tokens": 407, + "total_tokens": 1074 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/da0ddc21f17ec5c8ec642b79137a5fb0.json b/.litho/cache/ai_code_insight/da0ddc21f17ec5c8ec642b79137a5fb0.json new file mode 100644 index 0000000..2ac5e5f --- /dev/null +++ b/.litho/cache/ai_code_insight/da0ddc21f17ec5c8ec642b79137a5fb0.json @@ -0,0 +1,87 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/scrap/src/types.rs", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义了抓取器接口 IFetcher,用于异步获取文章数据。", + "functions": [], + "interfaces": [ + "IFetcher" + ] + }, + "detailed_description": "该组件定义了一个名为 IFetcher 的 trait,用于抽象不同来源的内容抓取逻辑。该 trait 提供了一个泛型异步方法 fetch,接收 AppHandle、LLMSection 和 FeedTargetDescription 参数,并返回一个包含 Article 向量的 Result。此设计支持在 Tauri 框架下进行安全的跨线程异步调用,适用于插件化或模块化的信息采集系统。", + "responsibilities": [ + "定义内容抓取操作的统一接口规范", + "支持异步非阻塞的数据获取过程", + "集成 Tauri 应用上下文以访问原生功能", + "传递 LLM 处理片段和目标源描述以指导抓取行为", + "确保返回结果符合 Article 数据结构约定" + ], + "interfaces": [ + { + "name": "IFetcher", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri 应用句柄,用于访问应用级资源" + }, + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "LLM 处理所需的上下文片段配置" + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": "目标数据源的描述信息" + } + ], + "return_type": "impl std::future::Future>> + Send", + "description": "内容抓取器接口,用于实现从指定源异步提取文章的功能。" + } + ], + "dependencies": [ + { + "name": "tauri", + "path": "tauri", + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 11, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805904, + "prompt_hash": "da0ddc21f17ec5c8ec642b79137a5fb0", + "token_usage": { + "input_tokens": 489, + "output_tokens": 685, + "total_tokens": 1174 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/db707f8f79f7dbe558f55ae6b44122cf.json b/.litho/cache/ai_code_insight/db707f8f79f7dbe558f55ae6b44122cf.json new file mode 100644 index 0000000..d71f9c8 --- /dev/null +++ b/.litho/cache/ai_code_insight/db707f8f79f7dbe558f55ae6b44122cf.json @@ -0,0 +1,75 @@ +{ + "data": { + "code_dossier": { + "name": "main.rs", + "file_path": "app/src-tauri/src/main.rs", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "Tauri应用的主入口文件,负责初始化并启动客户端库。", + "functions": [ + "main" + ], + "interfaces": [] + }, + "detailed_description": "该组件是Tauri框架下Rust后端的程序入口点。它通过调用qino_feed_client_lib::run()启动应用程序。代码使用了条件编译属性#![cfg_attr(not(debug_assertions), windows_subsystem = \"windows\")]来在Windows发布版本中隐藏控制台窗口。模块声明mod daemon和mod env引入了后台守护进程和环境判断逻辑的支持。整体结构简洁,符合Rust项目入口的标准模式。", + "responsibilities": [ + "作为应用程序的唯一入口点", + "配置平台特定的构建行为(如Windows下的窗口子系统)", + "初始化核心功能模块(daemon、env)", + "委托实际运行逻辑到外部库qino_feed_client_lib" + ], + "interfaces": [ + { + "name": "main", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "程序入口函数,启动客户端库运行循环" + } + ], + "dependencies": [ + { + "name": "qino_feed_client_lib", + "path": null, + "is_external": true, + "line_number": 7, + "dependency_type": "library", + "version": null + }, + { + "name": "daemon", + "path": "./app/src-tauri/src/daemon", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + }, + { + "name": "env", + "path": "./app/src-tauri/src/env.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 9, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805684, + "prompt_hash": "db707f8f79f7dbe558f55ae6b44122cf", + "token_usage": { + "input_tokens": 508, + "output_tokens": 555, + "total_tokens": 1063 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/df2928a7262264d67e322a18eca6e5b0.json b/.litho/cache/ai_code_insight/df2928a7262264d67e322a18eca6e5b0.json new file mode 100644 index 0000000..7831816 --- /dev/null +++ b/.litho/cache/ai_code_insight/df2928a7262264d67e322a18eca6e5b0.json @@ -0,0 +1,48 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/feed_api_rs/src/lib.rs", + "code_purpose": "api", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件作为feed_api_rs库的根模块,主要负责组织和导出子模块。它本身不包含具体实现逻辑,而是通过mod声明引入application_context、features、startup和utils四个子模块,并将前三个标记为公共(pub),使其对外暴露。其核心作用是模块化封装和API边界定义,形成清晰的内部结构层次。", + "responsibilities": [ + "组织和管理子模块结构", + "控制模块的可见性与导出", + "提供统一的模块入口点", + "隔离内部实现细节(如utils)" + ], + "interfaces": [], + "dependencies": [ + { + "name": "utils", + "path": "./crates/feed_api_rs/src/utils.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 4, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.9 + } + }, + "timestamp": 1758805857, + "prompt_hash": "df2928a7262264d67e322a18eca6e5b0", + "token_usage": { + "input_tokens": 642, + "output_tokens": 364, + "total_tokens": 1006 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/df32560b0e620b76f2259be2b70b310c.json b/.litho/cache/ai_code_insight/df32560b0e620b76f2259be2b70b310c.json new file mode 100644 index 0000000..fa6b742 --- /dev/null +++ b/.litho/cache/ai_code_insight/df32560b0e620b76f2259be2b70b310c.json @@ -0,0 +1,132 @@ +{ + "data": { + "code_dossier": { + "name": "path.rs", + "file_path": "crates/recorder/src/path.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "提供对应用数据目录和数据库文件路径的管理功能,确保所需目录存在并返回正确的路径。", + "functions": [ + "get_appdata_articles", + "get_appdata_file", + "get_appdata_file_in_dir", + "ensure_app_data_prepared", + "ensure_dir_in_appdata_prepared", + "ensure_dir_prepared" + ], + "interfaces": [] + }, + "detailed_description": "该组件主要用于管理和生成应用程序的数据存储路径。它封装了对本地文件系统中特定目录(如用户本地数据目录下的 qino_feed.app_data)的操作,确保目标目录结构在访问前已正确创建。主要功能包括获取主数据库文件路径、构建子文件或子目录的完整路径,并自动创建缺失的目录结构。所有路径操作基于 `std::path::PathBuf` 并结合 `dirs` crate 获取标准系统路径,适用于跨平台场景。", + "responsibilities": [ + "管理应用专属数据目录的路径生成", + "确保应用所需的数据目录结构存在(不存在则自动创建)", + "提供类型安全且可复用的路径构造接口", + "封装底层文件系统操作细节,降低调用方复杂度" + ], + "interfaces": [ + { + "name": "get_appdata_articles", + "interface_type": "function", + "visibility": "pub", + "parameters": [], + "return_type": "PathBuf", + "description": "获取文章记录器数据库文件的完整路径" + }, + { + "name": "get_appdata_file", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "file_name", + "param_type": "P: AsRef", + "is_optional": false, + "description": null + } + ], + "return_type": "PathBuf", + "description": "获取App Data下指定文件的完整路径" + }, + { + "name": "get_appdata_file_in_dir", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "sub_dir_name", + "param_type": "&str", + "is_optional": false, + "description": null + }, + { + "name": "file_name", + "param_type": "P: AsRef", + "is_optional": false, + "description": null + } + ], + "return_type": "PathBuf", + "description": "获取App Data下指定子目录中某个文件的完整路径" + }, + { + "name": "ensure_dir_prepared", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "dir_path", + "param_type": "PathBuf", + "is_optional": false, + "description": null + } + ], + "return_type": "PathBuf", + "description": "确保给定路径的目录存在,若不存在则创建" + } + ], + "dependencies": [ + { + "name": "std::fs", + "path": "std::fs", + "is_external": false, + "line_number": 1, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "std::path", + "path": "std::path", + "is_external": false, + "line_number": 2, + "dependency_type": "standard_library", + "version": null + }, + { + "name": "dirs", + "path": "dirs", + "is_external": true, + "line_number": null, + "dependency_type": "external_crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 45, + "number_of_functions": 6, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024391, + "prompt_hash": "df32560b0e620b76f2259be2b70b310c", + "token_usage": { + "input_tokens": 923, + "output_tokens": 966, + "total_tokens": 1889 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e0891eb9d02d52ed1ad99afb60adc4e0.json b/.litho/cache/ai_code_insight/e0891eb9d02d52ed1ad99afb60adc4e0.json new file mode 100644 index 0000000..1365f7d --- /dev/null +++ b/.litho/cache/ai_code_insight/e0891eb9d02d52ed1ad99afb60adc4e0.json @@ -0,0 +1,99 @@ +{ + "data": { + "code_dossier": { + "name": "SaveOperatePanel.svelte", + "file_path": "app/src/lib/widgets/SaveOperatePanel.svelte", + "code_purpose": "widget", + "importance_score": 0.6, + "description": "一个用于显示保存和取消操作按钮的前端UI组件,支持国际化文本显示。", + "functions": [], + "interfaces": [ + "onSave: MouseEventHandler", + "onCancel: MouseEventHandler", + "canSave: boolean" + ] + }, + "detailed_description": "该组件是一个可复用的Svelte前端UI小组件,主要用于表单或对话框底部渲染‘保存’和‘取消’两个操作按钮。其中‘保存’按钮是否可用由传入的canSave布尔值控制,实现禁用状态管理;两个按钮的点击事件分别绑定onSave和onCancel回调函数。文本内容通过svelte-i18n的$_进行国际化处理,适配多语言环境。整体结构简洁,符合无状态函数式组件的设计理念。", + "responsibilities": [ + "渲染保存和取消操作按钮界面", + "根据canSave属性控制保存按钮的启用/禁用状态", + "处理用户点击保存和取消按钮的事件分发", + "支持国际化文本显示" + ], + "interfaces": [ + { + "name": "onSave", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "event", + "param_type": "MouseEventHandler", + "is_optional": false, + "description": "鼠标点击事件对象" + } + ], + "return_type": "void", + "description": "当用户点击保存按钮时触发的回调函数" + }, + { + "name": "onCancel", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "event", + "param_type": "MouseEventHandler", + "is_optional": false, + "description": "鼠标点击事件对象" + } + ], + "return_type": "void", + "description": "当用户点击取消按钮时触发的回调函数" + }, + { + "name": "canSave", + "interface_type": "property", + "visibility": "public", + "parameters": [], + "return_type": "boolean", + "description": "控制保存按钮是否可点击" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "i18n", + "version": null + }, + { + "name": "svelte/elements", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 21, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758806015, + "prompt_hash": "e0891eb9d02d52ed1ad99afb60adc4e0", + "token_usage": { + "input_tokens": 560, + "output_tokens": 779, + "total_tokens": 1339 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e10b377d096175bbd3fe3908637a979d.json b/.litho/cache/ai_code_insight/e10b377d096175bbd3fe3908637a979d.json new file mode 100644 index 0000000..4e4aa78 --- /dev/null +++ b/.litho/cache/ai_code_insight/e10b377d096175bbd3fe3908637a979d.json @@ -0,0 +1,118 @@ +{ + "data": { + "code_dossier": { + "name": "reader.svelte.ts", + "file_path": "app/src/routes/main/stores/reader.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "提供文章阅读状态管理与内容刷新功能的Svelte store控制器", + "functions": [ + "create", + "markAsRead", + "refreshByEnhancedScraper" + ], + "interfaces": [ + "StoreType", + "Associates" + ] + }, + "detailed_description": "该组件是一个Svelte store实现,用于管理文章的阅读状态和内容刷新逻辑。它通过create函数接收关联依赖(如tasks store),并返回包含markAsRead和refreshByEnhancedScraper两个方法的StoreType对象。markAsRead调用API标记文章为已读;refreshByEnhancedScraper则实现了智能去重的任务调度机制:先检查是否存在相同任务ID的待处理请求,若存在且出错则清除,若正在进行则复用原有Promise,否则创建新任务并注册到tasks store中。", + "responsibilities": [ + "管理文章的已读状态更新", + "协调文章内容的增强式刷新流程", + "通过任务去重避免重复网络请求", + "集成外部API与本地任务调度系统", + "提供类型安全的store接口供UI层使用" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "export", + "parameters": [ + { + "name": "markAsRead", + "param_type": "(articleId: number) => Promise", + "is_optional": false, + "description": null + }, + { + "name": "refreshByEnhancedScraper", + "param_type": "(articleId: number, url: string) => Promise
", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + }, + { + "name": "Associates", + "interface_type": "type", + "visibility": "local", + "parameters": [ + { + "name": "tasks", + "param_type": "TasksStoreType", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": null + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 1, + "dependency_type": "api", + "version": null + }, + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 2, + "dependency_type": "model", + "version": null + }, + { + "name": "Status", + "path": "./loading.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "constant", + "version": null + }, + { + "name": "TasksStoreType", + "path": "./tasks.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "store", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 47, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.85, + "cohesion_score": 0.92 + } + }, + "timestamp": 1759024151, + "prompt_hash": "e10b377d096175bbd3fe3908637a979d", + "token_usage": { + "input_tokens": 729, + "output_tokens": 771, + "total_tokens": 1500 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e2436fe098e7dc07b40960531fb0be5d.json b/.litho/cache/ai_code_insight/e2436fe098e7dc07b40960531fb0be5d.json new file mode 100644 index 0000000..e4ddf53 --- /dev/null +++ b/.litho/cache/ai_code_insight/e2436fe098e7dc07b40960531fb0be5d.json @@ -0,0 +1,158 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "app/src-tauri/src/lib.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "Tauri应用主入口与系统级Agent,负责初始化插件、创建托盘、处理窗口事件及启动后台任务。", + "functions": [ + "run" + ], + "interfaces": [ + "run" + ] + }, + "detailed_description": "该组件是Tauri桌面应用的核心启动器和智能Agent,承担系统级职责。它通过`run`函数初始化多个Tauri插件(如单实例、对话框、剪贴板、自动启动等),配置全局窗口事件处理器(拦截macOS主窗口关闭请求并隐藏而非退出),并在`setup`阶段执行关键逻辑:检测是否为守护进程模式、显示主窗口或跳过UI、启动定时信息源更新任务。同时,它集成Sentry进行错误监控,并在桌面平台创建系统托盘以提供快捷入口。整体上,该组件作为应用的中枢控制器,协调各模块的初始化与运行时行为。", + "responsibilities": [ + "作为Tauri应用的主入口点,启动并初始化整个应用", + "配置并注册所有Tauri插件,构建应用功能基础", + "管理应用生命周期,处理主窗口关闭事件(最小化到托盘)", + "在应用启动时触发核心后台服务(如定时信息源更新)", + "协调子模块(如tray, daemon, env)完成桌面端特定功能" + ], + "interfaces": [ + { + "name": "run", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "void", + "description": "应用的主启动函数,由Tauri框架调用,负责构建App并运行事件循环。" + } + ], + "dependencies": [ + { + "name": "constrant", + "path": "./app/src-tauri/src/constrant.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "daemon", + "path": "./app/src-tauri/src/daemon", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "env", + "path": "./app/src-tauri/src/env.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "monitor", + "path": "./app/src-tauri/src/monitor.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "tray", + "path": "./app/src-tauri/src/tray.rs", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "std::sync::Arc", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 7, + "dependency_type": "crate", + "version": null + }, + { + "name": "tauri_plugin_autostart", + "path": null, + "is_external": true, + "line_number": 8, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_feed_api", + "path": null, + "is_external": true, + "line_number": 9, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_single_instance", + "path": null, + "is_external": true, + "line_number": 13, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_dialog", + "path": null, + "is_external": true, + "line_number": 15, + "dependency_type": "plugin", + "version": null + }, + { + "name": "tauri_plugin_os", + "path": null, + "is_external": true, + "line_number": 16, + "dependency_type": "plugin", + "version": null + }, + { + "name": "sentry", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "crate", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 68, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.84, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758805662, + "prompt_hash": "e2436fe098e7dc07b40960531fb0be5d", + "token_usage": { + "input_tokens": 2413, + "output_tokens": 1079, + "total_tokens": 3492 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e2624ceec999bc0558ad736e61475553.json b/.litho/cache/ai_code_insight/e2624ceec999bc0558ad736e61475553.json new file mode 100644 index 0000000..e3cd16a --- /dev/null +++ b/.litho/cache/ai_code_insight/e2624ceec999bc0558ad736e61475553.json @@ -0,0 +1,77 @@ +{ + "data": { + "code_dossier": { + "name": "loading.svelte.ts", + "file_path": "app/src/routes/main/stores/loading.svelte.ts", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "Svelte状态存储组件,用于管理加载状态的生命周期,包括未设定、加载中、完成和错误四种状态,并提供相应的控制方法和状态文本映射。", + "functions": [ + "create" + ], + "interfaces": [ + "StoreType", + "Status" + ] + }, + "detailed_description": "该组件是一个Svelte状态存储实现,主要用于管理UI中的加载状态。它定义了一个枚举Status表示四种可能的状态:未设定(Unset)、加载中(Loading)、已完成(Completed)和出错(Error)。通过create函数创建一个响应式状态对象,内部使用$state实现状态管理。组件暴露unset、load、error、complete四个方法用于变更状态,并通过getter属性status和statusText提供当前状态及其对应的中文描述文本。状态文本根据当前状态自动计算返回,便于在模板中直接显示友好的状态提示信息。", + "responsibilities": [ + "管理加载状态的生命周期(未设定/加载中/完成/错误)", + "提供状态变更的控制方法(unset/load/complete/error)", + "维护状态与用户可读文本的映射关系", + "作为响应式数据源供Svelte组件消费", + "封装状态转换逻辑并保证状态一致性" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义加载状态存储的接口类型,包含状态操作方法和只读属性" + }, + { + "name": "Status", + "interface_type": "enum", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "枚举类型,定义加载状态的四种可能取值" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "initStatus", + "param_type": "Status", + "is_optional": true, + "description": "初始状态,默认为Status.Unset" + } + ], + "return_type": "StoreType", + "description": "工厂函数,创建并返回一个新的加载状态存储实例" + } + ], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 61, + "number_of_functions": 5, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1758805809, + "prompt_hash": "e2624ceec999bc0558ad736e61475553", + "token_usage": { + "input_tokens": 654, + "output_tokens": 810, + "total_tokens": 1464 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e4a42ef3a4528ff76e5b29e6fe2f57d3.json b/.litho/cache/ai_code_insight/e4a42ef3a4528ff76e5b29e6fe2f57d3.json new file mode 100644 index 0000000..9d6be1a --- /dev/null +++ b/.litho/cache/ai_code_insight/e4a42ef3a4528ff76e5b29e6fe2f57d3.json @@ -0,0 +1,38 @@ +{ + "data": { + "code_dossier": { + "name": "+page.svelte", + "file_path": "app/src/routes/+page.svelte", + "code_purpose": "page", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Svelte路由页面组件,但由于源代码为空,未实现任何具体功能。它可能作为路由占位符或待开发页面存在。", + "responsibilities": [ + "作为应用路由的页面入口点", + "待定业务逻辑展示(当前未实现)", + "用户界面渲染容器(当前为空)" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 0, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 0.0 + } + }, + "timestamp": 1758806028, + "prompt_hash": "e4a42ef3a4528ff76e5b29e6fe2f57d3", + "token_usage": { + "input_tokens": 399, + "output_tokens": 242, + "total_tokens": 641 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e586cef0f5902fe32364a4a45617361d.json b/.litho/cache/ai_code_insight/e586cef0f5902fe32364a4a45617361d.json new file mode 100644 index 0000000..64cb8e0 --- /dev/null +++ b/.litho/cache/ai_code_insight/e586cef0f5902fe32364a4a45617361d.json @@ -0,0 +1,52 @@ +{ + "data": { + "code_dossier": { + "name": "settings.ts", + "file_path": "app/src/lib/i18n/settings.ts", + "source_summary": "", + "code_purpose": "config", + "importance_score": 0.6, + "description": "国际化语言设置配置模块,用于获取浏览器语言并提供默认和备用语言选项", + "functions": [ + "getLocale", + "setLocale" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit应用中的国际化(i18n)配置模块,主要负责语言环境的初始化设置。在浏览器环境中,通过window.navigator.language获取用户首选语言;在服务端则返回默认中文(zh)。提供了默认语言和备用语言的常量定义,并导出了获取当前语言和设置语言的函数接口,为应用的多语言支持提供基础配置。", + "responsibilities": [ + "管理应用的默认和备用语言配置", + "根据运行环境获取用户的语言偏好", + "提供语言设置的基础API接口", + "支持SSR/CSR环境下的语言检测" + ], + "interfaces": [], + "dependencies": [ + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 12, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.8 + } + }, + "timestamp": 1759024704, + "prompt_hash": "e586cef0f5902fe32364a4a45617361d", + "token_usage": { + "input_tokens": 475, + "output_tokens": 459, + "total_tokens": 934 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e748ac4f91e2148bd4912f201b538863.json b/.litho/cache/ai_code_insight/e748ac4f91e2148bd4912f201b538863.json new file mode 100644 index 0000000..3268b0a --- /dev/null +++ b/.litho/cache/ai_code_insight/e748ac4f91e2148bd4912f201b538863.json @@ -0,0 +1,112 @@ +{ + "data": { + "code_dossier": { + "name": "ContextMenuProvider.svelte", + "file_path": "app/src/lib/widgets/ContextMenuProvider.svelte", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "Svelte组件,提供可复用的右键上下文菜单功能,支持动态菜单项和位置自适应", + "functions": [ + "showContextMenu", + "onHideMenu", + "getContextMenuDimension", + "wrapMenuPressHandler" + ], + "interfaces": [ + "menus", + "children" + ] + }, + "detailed_description": "该组件是一个Svelte前端UI组件,用于在网页中实现右键上下文菜单功能。它接收菜单配置数组和子元素作为插槽内容,当用户在子元素上右键点击时,显示对应的上下文菜单。组件会自动计算菜单显示位置,避免超出浏览器视窗边界。菜单项可以是普通按钮或分隔线('hr'),每个按钮都有图标、文本和点击处理函数。通过wrapMenuPressHandler包装器确保菜单操作后自动隐藏。使用Svelte的$state进行响应式状态管理,并通过use指令获取菜单尺寸以实现智能定位。", + "responsibilities": [ + "管理上下文菜单的显示与隐藏状态", + "处理右键点击事件并定位菜单位置", + "防止菜单显示超出浏览器视窗边界", + "提供菜单项点击处理的包装逻辑", + "通过插槽机制封装受保护的内容区域" + ], + "interfaces": [ + { + "name": "menus", + "interface_type": "property", + "visibility": "public", + "parameters": [], + "return_type": "MenuType[]", + "description": "菜单配置数组,包含菜单项的名称、显示文本、CSS类名和点击回调函数" + }, + { + "name": "children", + "interface_type": "slot", + "visibility": "public", + "parameters": [], + "return_type": "Snippet", + "description": "默认插槽,用于包裹需要启用上下文菜单功能的子元素" + }, + { + "name": "showContextMenu", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "e", + "param_type": "MouseEvent", + "is_optional": false, + "description": "鼠标事件对象" + } + ], + "return_type": "boolean", + "description": "处理右键点击事件,显示上下文菜单并计算最佳显示位置" + }, + { + "name": "onHideMenu", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "void", + "description": "处理页面点击事件,隐藏当前显示的上下文菜单" + }, + { + "name": "getContextMenuDimension", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "node", + "param_type": "HTMLElement", + "is_optional": false, + "description": "上下文菜单DOM节点" + } + ], + "return_type": "void", + "description": "获取上下文菜单的实际尺寸,用于位置计算" + } + ], + "dependencies": [ + { + "name": "svelte", + "path": "svelte", + "is_external": true, + "line_number": 3, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 7.0, + "lines_of_code": 160, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.25, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805757, + "prompt_hash": "e748ac4f91e2148bd4912f201b538863", + "token_usage": { + "input_tokens": 1335, + "output_tokens": 997, + "total_tokens": 2332 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e7cf88813582429de3aa801c8ff9f699.json b/.litho/cache/ai_code_insight/e7cf88813582429de3aa801c8ff9f699.json new file mode 100644 index 0000000..8994cd5 --- /dev/null +++ b/.litho/cache/ai_code_insight/e7cf88813582429de3aa801c8ff9f699.json @@ -0,0 +1,108 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/tauri-plugin-feed-api/src/lib.rs", + "source_summary": "", + "code_purpose": "api", + "importance_score": 0.8, + "description": "Tauri插件入口,定义并注册所有与feed功能相关的前端可调用命令。通过依赖注入管理应用状态,并初始化底层业务逻辑组件。", + "functions": [ + "init" + ], + "interfaces": [] + }, + "detailed_description": "该组件是Tauri框架下的一个原生插件(`tauri-plugin-feed-api`)的核心入口文件。其主要职责是将位于`commands`模块中的异步Rust函数暴露给前端JavaScript环境,使其能够安全地调用本地系统能力。组件通过`tauri::plugin::Builder`构建插件实例,使用`generate_handler!`宏批量注册了24个由`#[tauri::command]`标记的函数。这些函数覆盖了从RSS源管理(增删改查)、文章内容获取、AI模型(Ollama)交互到全文搜索等完整的feed应用核心功能。在初始化阶段(`setup`),它异步启动了一个`Startup`流程来创建全局共享的`FeaturesAPIImpl`业务逻辑实例,并将其包裹在`Arc>`中通过`app_handle.manage()`进行状态管理,确保了跨命令调用的数据一致性和线程安全。此外,还包含了一个针对macOS的`on_event`监听器,用于处理应用重新打开事件时窗口的显示逻辑。", + "responsibilities": [ + "作为Tauri插件的初始化入口,协调整个插件的生命周期", + "集中注册和暴露所有后端功能命令(Commands)供前端调用", + "管理插件级共享状态(HybridRuntimeState),实现依赖注入", + "处理特定于平台的应用程序事件(如macOS的Reopen事件)" + ], + "interfaces": [ + { + "name": "init", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "TauriPlugin", + "description": "插件的初始化函数,返回一个构建好的Tauri插件实例。" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": null, + "is_external": false, + "line_number": 1, + "dependency_type": "std_lib", + "version": null + }, + { + "name": "tauri", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "external_crate", + "version": null + }, + { + "name": "feed_api_rs::application_context::ContextHost", + "path": "crates/feed-api-rs", + "is_external": false, + "line_number": 7, + "dependency_type": "internal_crate", + "version": null + }, + { + "name": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "path": "crates/feed-api-rs", + "is_external": false, + "line_number": 8, + "dependency_type": "internal_crate", + "version": null + }, + { + "name": "feed_api_rs::startup::Startup", + "path": "crates/feed-api-rs", + "is_external": false, + "line_number": 9, + "dependency_type": "internal_crate", + "version": null + }, + { + "name": "crate::commands", + "path": "./crates/tauri-plugin-feed-api/src/commands.rs", + "is_external": false, + "line_number": 11, + "dependency_type": "internal_module", + "version": null + }, + { + "name": "crate::state::HybridRuntimeState", + "path": "./crates/tauri-plugin-feed-api/src/state.rs", + "is_external": false, + "line_number": 15, + "dependency_type": "internal_module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 86, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.82, + "cohesion_score": 0.75 + } + }, + "timestamp": 1759024406, + "prompt_hash": "e7cf88813582429de3aa801c8ff9f699", + "token_usage": { + "input_tokens": 3408, + "output_tokens": 1051, + "total_tokens": 4459 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e7f285a5bb282d303bedf23ebc850cf5.json b/.litho/cache/ai_code_insight/e7f285a5bb282d303bedf23ebc850cf5.json new file mode 100644 index 0000000..d63e804 --- /dev/null +++ b/.litho/cache/ai_code_insight/e7f285a5bb282d303bedf23ebc850cf5.json @@ -0,0 +1,69 @@ +{ + "data": { + "code_dossier": { + "name": "hooks.server.ts", + "file_path": "app/src/hooks.server.ts", + "source_summary": "", + "code_purpose": "middleware", + "importance_score": 0.6, + "description": "SvelteKit服务端钩子文件,集成Sentry错误监控并处理国际化语言设置", + "functions": [ + "handle", + "handleError" + ], + "interfaces": [] + }, + "detailed_description": "该组件是SvelteKit应用的服务端钩子(hooks),主要负责两个核心功能:一是初始化Sentry性能监控和错误追踪系统,配置DSN和采样率;二是通过HTTP请求头中的accept-language字段动态设置国际化语言环境。组件使用sequence组合多个handle处理器,确保Sentry的中间件优先执行,然后处理语言本地化逻辑。", + "responsibilities": [ + "初始化Sentry监控系统并配置DSN和追踪采样率", + "作为请求处理中间件链的一部分,处理进入的HTTP请求", + "从请求头提取accept-language信息并设置当前locale", + "集成Sentry错误处理机制,捕获和上报运行时异常", + "维护应用的可观测性和错误监控能力" + ], + "interfaces": [], + "dependencies": [ + { + "name": "@sveltejs/kit", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "framework", + "version": null + }, + { + "name": "@sentry/sveltekit", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "monitoring", + "version": null + }, + { + "name": "svelte-i18n", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "internationalization", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 25, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.6, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024721, + "prompt_hash": "e7f285a5bb282d303bedf23ebc850cf5", + "token_usage": { + "input_tokens": 645, + "output_tokens": 557, + "total_tokens": 1202 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e8595e72c8feb61776378d498ce4d287.json b/.litho/cache/ai_code_insight/e8595e72c8feb61776378d498ce4d287.json new file mode 100644 index 0000000..ac615f7 --- /dev/null +++ b/.litho/cache/ai_code_insight/e8595e72c8feb61776378d498ce4d287.json @@ -0,0 +1,38 @@ +{ + "data": { + "code_dossier": { + "name": "args.rs", + "file_path": "app/src-tauri/src/daemon/args.rs", + "code_purpose": "config", + "importance_score": 0.6, + "description": "定义守护进程命令行参数的常量", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件定义了一个公共常量DAEMON_FEEDS_SCHEDULE_UPDATE,用于表示守护进程中控制feeds定时更新功能的命令行参数标志。它作为配置项被其他模块引用,以实现命令行参数解析和功能调度的一致性。", + "responsibilities": [ + "定义守护进程相关的命令行参数常量", + "提供跨模块共享的参数标识符", + "确保命令行接口的一致性和可维护性" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805974, + "prompt_hash": "e8595e72c8feb61776378d498ce4d287", + "token_usage": { + "input_tokens": 415, + "output_tokens": 314, + "total_tokens": 729 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e86640141e810421f144c0a6911ba74d.json b/.litho/cache/ai_code_insight/e86640141e810421f144c0a6911ba74d.json new file mode 100644 index 0000000..c8bf5fe --- /dev/null +++ b/.litho/cache/ai_code_insight/e86640141e810421f144c0a6911ba74d.json @@ -0,0 +1,161 @@ +{ + "data": { + "code_dossier": { + "name": "llm_agent.rs", + "file_path": "crates/llm/src/llm_agent.rs", + "code_purpose": "agent", + "importance_score": 0.8, + "description": "LLM服务代理组件,封装多种LLM提供商的调用逻辑,提供统一的completion接口。", + "functions": [ + "new", + "completion" + ], + "interfaces": [ + "CompletionAgent" + ] + }, + "detailed_description": "该组件实现了一个LLM生成服务代理(CompletionAgent),用于抽象不同LLM服务提供商的实现差异。通过枚举类型CompletionServiceEnums持有具体的LLM服务实例(如Ollama、Mistral、GLM、OpenAI等),并在初始化时根据配置的provider_type动态创建对应的后端服务。其核心方法`completion`接受用户输入消息并异步转发请求至底层服务,实现统一的文本生成功能调用入口。整体设计遵循策略模式思想,解耦了上层应用与具体LLM实现之间的依赖。", + "responsibilities": [ + "根据配置选择并初始化对应的LLM服务提供者", + "封装多LLM提供商的接入逻辑,提供统一调用接口", + "转发用户的completion请求到底层具体的服务实现", + "管理LLM服务实例的生命周期(通过所有权机制)", + "处理不同提供商之间的运行时多态调用" + ], + "interfaces": [ + { + "name": "CompletionAgent", + "interface_type": "struct", + "visibility": "pub", + "parameters": [], + "return_type": null, + "description": "LLM生成服务代理主结构体,对外暴露new和completion两个主要方法。" + }, + { + "name": "new", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "包含当前激活的LLM提供商及其配置信息" + }, + { + "name": "system_prompt", + "param_type": "String", + "is_optional": false, + "description": "预设的系统级提示词" + }, + { + "name": "options", + "param_type": "AITargetOption", + "is_optional": false, + "description": "目标AI平台相关选项" + } + ], + "return_type": "anyhow::Result", + "description": "根据LLMSection配置、系统提示和选项创建CompletionAgent实例。" + }, + { + "name": "completion", + "interface_type": "function", + "visibility": "pub", + "parameters": [ + { + "name": "message", + "param_type": "String", + "is_optional": false, + "description": "用户输入的消息内容" + } + ], + "return_type": "anyhow::Result", + "description": "执行一次LLM文本生成请求,将用户消息传递给底层服务。" + }, + { + "name": "CompletionServiceEnums", + "interface_type": "enum", + "visibility": "private", + "parameters": [], + "return_type": null, + "description": "内部枚举类型,用于持有不同类型LLM服务的实例,支持运行时多态。" + } + ], + "dependencies": [ + { + "name": "types", + "path": "types", + "is_external": false, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_glm::GLMCompletionService", + "path": "crates/llm/src/providers/llm_glm.rs", + "is_external": false, + "line_number": 3, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_mistral::MistralQinoAgentService", + "path": "crates/llm/src/providers/llm_mistral.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_ollama::OllamaCompletionService", + "path": "crates/llm/src/providers/llm_ollama.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "path": "crates/llm/src/providers/llm_openaibase_like.rs", + "is_external": false, + "line_number": 6, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::llm_platform::PlatformAgentService", + "path": "crates/llm/src/providers/llm_platform.rs", + "is_external": false, + "line_number": 7, + "dependency_type": "use", + "version": null + }, + { + "name": "crate::providers::types::CompletionService", + "path": "crates/llm/src/providers/types.rs", + "is_external": false, + "line_number": 8, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 82, + "number_of_functions": 2, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801141, + "prompt_hash": "e86640141e810421f144c0a6911ba74d", + "token_usage": { + "input_tokens": 1272, + "output_tokens": 1270, + "total_tokens": 2542 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/e94fa7de235161815ab4279639df6a33.json b/.litho/cache/ai_code_insight/e94fa7de235161815ab4279639df6a33.json new file mode 100644 index 0000000..0a8d93a --- /dev/null +++ b/.litho/cache/ai_code_insight/e94fa7de235161815ab4279639df6a33.json @@ -0,0 +1,167 @@ +{ + "data": { + "code_dossier": { + "name": "index.svelte.ts", + "file_path": "app/src/routes/main/stores/index.svelte.ts", + "source_summary": "", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "核心状态管理容器,协调文章、任务、订阅源等子模块的状态与行为。", + "functions": [ + "createStore", + "setCurrentArticle", + "getCurrentArticle", + "scheduleUpdate", + "onSelectToday", + "onSelectWeekend", + "onSelectFavorite", + "onSelectUnread", + "setCurrentFeedId" + ], + "interfaces": [ + "IContext" + ] + }, + "detailed_description": "该组件是Svelte应用中的核心状态存储模块,通过`createStore`函数创建一个集中式的状态管理器。它整合了feeds、articles、tasks、reader和sprite等多个子store,并对外暴露统一的访问接口。组件利用Svelte的反应式特性($state, $derived, $effect)实现自动更新。主要功能包括:当前feed和文章的管理、特定筛选条件(今日/周末/收藏/未读)的选择逻辑、定时内容更新调度、以及初始化时的数据加载控制。特别地,通过全局共享的`globalSharedScheduleUpdatingFuture`确保更新任务不被重复触发。", + "responsibilities": [ + "作为应用主界面的核心状态容器,聚合多个子状态模块", + "管理当前选中的feed和文章,支持基于虚拟feed ID的特殊筛选视图", + "协调定时内容更新流程,避免并发执行", + "处理应用启动时的初始化数据加载逻辑", + "提供统一的API供UI层调用以改变状态或获取数据" + ], + "interfaces": [ + { + "name": "IContext", + "interface_type": "type", + "visibility": "imported", + "parameters": [], + "return_type": null, + "description": "定义上下文对象的结构,用于在store间传递共享状态" + }, + { + "name": "createStore", + "interface_type": "function", + "visibility": "exported", + "parameters": [], + "return_type": "object", + "description": "工厂函数,创建并返回一个新的store实例,包含所有子模块和操作方法" + } + ], + "dependencies": [ + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 1, + "dependency_type": "type", + "version": null + }, + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 4, + "dependency_type": "variable", + "version": null + }, + { + "name": "isRecentFamilyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 5, + "dependency_type": "function", + "version": null + }, + { + "name": "isSpecifyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 6, + "dependency_type": "function", + "version": null + }, + { + "name": "SPECIFY_FEED_IDSET", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": false, + "line_number": 7, + "dependency_type": "constant", + "version": null + }, + { + "name": "createArticles", + "path": "./articles/index.svelte", + "is_external": false, + "line_number": 8, + "dependency_type": "function", + "version": null + }, + { + "name": "createTasks", + "path": "./tasks.svelte", + "is_external": false, + "line_number": 9, + "dependency_type": "function", + "version": null + }, + { + "name": "createFeeds", + "path": "./feeds.svelte", + "is_external": false, + "line_number": 10, + "dependency_type": "function", + "version": null + }, + { + "name": "createReader", + "path": "./reader.svelte", + "is_external": false, + "line_number": 11, + "dependency_type": "function", + "version": null + }, + { + "name": "createSprite", + "path": "./sprite.svelte", + "is_external": false, + "line_number": 12, + "dependency_type": "function", + "version": null + }, + { + "name": "currentDateText", + "path": "$lib/utils/date", + "is_external": false, + "line_number": 13, + "dependency_type": "function", + "version": null + }, + { + "name": "IContext", + "path": "./context", + "is_external": false, + "line_number": 14, + "dependency_type": "type", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 14.0, + "lines_of_code": 203, + "number_of_functions": 13, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5625, + "cohesion_score": 0.78 + } + }, + "timestamp": 1759024182, + "prompt_hash": "e94fa7de235161815ab4279639df6a33", + "token_usage": { + "input_tokens": 1821, + "output_tokens": 1154, + "total_tokens": 2975 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/eba31b09180ad9babb41912ebe7c52de.json b/.litho/cache/ai_code_insight/eba31b09180ad9babb41912ebe7c52de.json new file mode 100644 index 0000000..4cacee6 --- /dev/null +++ b/.litho/cache/ai_code_insight/eba31b09180ad9babb41912ebe7c52de.json @@ -0,0 +1,77 @@ +{ + "data": { + "code_dossier": { + "name": "main.rs", + "file_path": "app/src-tauri/src/main.rs", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "Tauri应用的主入口文件,负责初始化并启动核心运行时。", + "functions": [ + "main" + ], + "interfaces": [ + "run" + ] + }, + "detailed_description": "该组件是Tauri桌面应用的程序入口点。通过cfg_attr属性在Windows发布版本中隐藏控制台窗口,确保用户体验整洁。它导入本地模块daemon和env,并在main函数中调用qino_feed_client_lib库的run函数来启动应用程序。整体逻辑简洁,专注于引导流程。", + "responsibilities": [ + "作为应用程序的启动入口点", + "配置平台特定行为(如Windows下的控制台隐藏)", + "协调底层库的初始化与执行" + ], + "interfaces": [ + { + "name": "run", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "Result<(), anyhow::Error>", + "description": "来自qino_feed_client_lib的核心启动函数,初始化应用服务、窗口及事件循环" + } + ], + "dependencies": [ + { + "name": "qino_feed_client_lib", + "path": "crate::qino_feed_client_lib", + "is_external": false, + "line_number": 7, + "dependency_type": "library", + "version": null + }, + { + "name": "daemon", + "path": "./daemon", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "env", + "path": "./env", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 9, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.33, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024437, + "prompt_hash": "eba31b09180ad9babb41912ebe7c52de", + "token_usage": { + "input_tokens": 516, + "output_tokens": 514, + "total_tokens": 1030 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ecd06cf71483c78301f89c9f58242253.json b/.litho/cache/ai_code_insight/ecd06cf71483c78301f89c9f58242253.json new file mode 100644 index 0000000..24c31ea --- /dev/null +++ b/.litho/cache/ai_code_insight/ecd06cf71483c78301f89c9f58242253.json @@ -0,0 +1,152 @@ +{ + "data": { + "code_dossier": { + "name": "init_logger.rs", + "file_path": "crates/feed_api_rs/src/startup/init_logger.rs", + "source_summary": "", + "code_purpose": "util", + "importance_score": 0.8, + "description": "初始化日志系统,根据配置决定日志输出方式(stdout或磁盘文件),并设置统一的日志格式。", + "functions": [ + "call", + "init_by", + "specify_logger_format" + ], + "interfaces": [ + "call", + "init_by", + "specify_logger_format" + ] + }, + "detailed_description": "该组件负责应用程序启动时的日志系统初始化。它读取应用配置中的日志部分(AppConfigLogSection),根据是否启用日志、输出类型(标准输出或磁盘)以及调试模式状态来动态配置全局日志行为。在磁盘模式下,使用按天轮转的策略将日志写入指定路径,并设置3秒的刷新周期以平衡性能与持久性。同时,为所有日志记录器统一设置包含时间、线程ID、日志级别和消息内容的可读格式。", + "responsibilities": [ + "解析日志配置并决定日志启用策略", + "根据输出类型初始化对应的目标sink(stdout或文件)", + "设置统一的日志格式以增强可读性和一致性", + "支持调试模式下的自动日志开启机制", + "管理日志刷新频率和文件轮转策略" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "app_config", + "param_type": "&AppConfig", + "is_optional": false, + "description": "应用完整配置,从中提取日志配置部分" + } + ], + "return_type": "anyhow::Result<()>", + "description": "入口函数,接收整体应用配置并调用实际初始化逻辑" + }, + { + "name": "init_by", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "log_section", + "param_type": "&AppConfigLogSection", + "is_optional": false, + "description": "日志模块的配置节" + } + ], + "return_type": "anyhow::Result<()>", + "description": "核心初始化函数,根据日志配置执行具体的日志系统设置" + }, + { + "name": "specify_logger_format", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "logger", + "param_type": "&Arc", + "is_optional": false, + "description": "待格式化的日志记录器实例" + } + ], + "return_type": null, + "description": "内部辅助函数,为指定日志器设置统一的输出格式" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "is_external": false, + "line_number": 1, + "dependency_type": "std", + "version": null + }, + { + "name": "std::time::Duration", + "path": "std::time::Duration", + "is_external": false, + "line_number": 2, + "dependency_type": "std", + "version": null + }, + { + "name": "spdlog", + "path": "spdlog", + "is_external": true, + "line_number": 4, + "dependency_type": "third_party", + "version": null + }, + { + "name": "recorder::path::get_appdata_file_in_dir", + "path": "recorder::path::get_appdata_file_in_dir", + "is_external": false, + "line_number": 9, + "dependency_type": "internal", + "version": null + }, + { + "name": "types::AppConfig", + "path": "types::AppConfig", + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + }, + { + "name": "types::AppConfigLogSection", + "path": "types::AppConfigLogSection", + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + }, + { + "name": "types::OutputType", + "path": "types::OutputType", + "is_external": false, + "line_number": 10, + "dependency_type": "internal", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 74, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.65, + "cohesion_score": 0.88 + } + }, + "timestamp": 1759024306, + "prompt_hash": "ecd06cf71483c78301f89c9f58242253", + "token_usage": { + "input_tokens": 1121, + "output_tokens": 1122, + "total_tokens": 2243 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ee27b33c42144764d2d90581004791bf.json b/.litho/cache/ai_code_insight/ee27b33c42144764d2d90581004791bf.json new file mode 100644 index 0000000..b5d52c8 --- /dev/null +++ b/.litho/cache/ai_code_insight/ee27b33c42144764d2d90581004791bf.json @@ -0,0 +1,90 @@ +{ + "data": { + "code_dossier": { + "name": "types.rs", + "file_path": "crates/scrap/src/search/types.rs", + "source_summary": "", + "code_purpose": "model", + "importance_score": 0.6, + "description": "定义搜索功能所需的数据类型和核心行为契约,特别是文章搜索的异步处理接口。", + "functions": [], + "interfaces": [ + "IProvider" + ] + }, + "detailed_description": "该组件定义了一个名为 IProvider 的 trait,用于规范搜索服务的行为。它要求实现者提供一个基于关键词搜索文章的异步方法 search_by_words,该方法接受字符串切片向量和可选的 Tauri AppHandle,返回一个异步 Future,解析为包含 Article 对象向量的结果。此 trait 是搜索功能的核心抽象,允许不同搜索引擎(如本地、网络等)以统一方式集成。", + "responsibilities": [ + "定义搜索服务的行为契约", + "声明异步搜索方法的统一接口", + "支持可选应用上下文传递以便内部操作", + "作为多种搜索实现的公共抽象基类", + "促进依赖注入和模块化设计" + ], + "interfaces": [ + { + "name": "IProvider", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "搜索服务提供者的抽象接口,规定了必须实现的异步搜索方法。" + }, + { + "name": "search_by_words", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "words", + "param_type": "Vec<&str>", + "is_optional": false, + "description": "用于搜索的关键词列表" + }, + { + "name": "app_handle", + "param_type": "Option>", + "is_optional": true, + "description": "Tauri 应用句柄,用于访问应用状态或资源" + } + ], + "return_type": "impl std::future::Future>>", + "description": "根据提供的关键词执行搜索并返回文章结果的异步操作" + } + ], + "dependencies": [ + { + "name": "tauri", + "path": "tauri::{AppHandle, Runtime}", + "is_external": true, + "line_number": 1, + "dependency_type": "use", + "version": null + }, + { + "name": "types::Article", + "path": "types::Article", + "is_external": false, + "line_number": 2, + "dependency_type": "use", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 10, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 2.0, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024634, + "prompt_hash": "ee27b33c42144764d2d90581004791bf", + "token_usage": { + "input_tokens": 480, + "output_tokens": 762, + "total_tokens": 1242 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/ef3d38c3da8134420ef27e7b01559a4e.json b/.litho/cache/ai_code_insight/ef3d38c3da8134420ef27e7b01559a4e.json new file mode 100644 index 0000000..186f885 --- /dev/null +++ b/.litho/cache/ai_code_insight/ef3d38c3da8134420ef27e7b01559a4e.json @@ -0,0 +1,103 @@ +{ + "data": { + "code_dossier": { + "name": "impl.ts", + "file_path": "app/src/lib/hybrid-apis/feed/impl.ts", + "code_purpose": "api", + "importance_score": 0.8, + "description": "该文件定义了 Feeds 功能的 API 实现类 FeaturesAPIImpl,通过 Tauri 调用后端原生方法,提供对订阅源、文章内容、应用配置及 AI 助手交互等操作的支持。", + "functions": [ + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "set_favorite", + "scrap_text_by_url", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword", + "isSpecifyFeed", + "isRecentFamilyFeed" + ], + "interfaces": [ + "FeaturesAPI" + ] + }, + "detailed_description": "该组件是 Feed 系统的核心接口实现层,采用代理模式封装 Tauri 原生调用。它实现了 FeaturesAPI 接口,所有方法均通过 `call` 函数转发至 Rust 后端执行,实现了前后端逻辑解耦。组件还包含两个辅助函数 isSpecifyFeed 和 isRecentFamilyFeed,用于判断特殊虚拟 Feed 类型(如今日、周末、收藏等)。此外导出了预定义的 SPECIFY_FEED_IDSET 常量集合和单例实例 featuresApi,便于全局使用。", + "responsibilities": [ + "提供对 RSS 订阅包和订阅项的增删改查操作", + "管理文章内容读取、搜索与状态更新(已读/收藏)", + "封装与 Ollama 本地大模型服务的交互接口", + "处理外部链接打开与网页内容抓取功能", + "提供特殊虚拟 Feed 的识别逻辑" + ], + "interfaces": [ + { + "name": "FeaturesAPI", + "interface_type": "class", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了 Feed 相关功能的接口契约" + } + ], + "dependencies": [ + { + "name": "../tauri-regular", + "path": "app/src/lib/hybrid-apis/feed/../tauri-regular", + "is_external": false, + "line_number": 1, + "dependency_type": "module", + "version": null + }, + { + "name": "./api", + "path": "app/src/lib/hybrid-apis/feed/api", + "is_external": false, + "line_number": 3, + "dependency_type": "module", + "version": null + }, + { + "name": "./types", + "path": "app/src/lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": 4, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 164, + "number_of_functions": 25, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.88 + } + }, + "timestamp": 1758805699, + "prompt_hash": "ef3d38c3da8134420ef27e7b01559a4e", + "token_usage": { + "input_tokens": 1449, + "output_tokens": 811, + "total_tokens": 2260 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f1c2b75a29e47cae9bca4dde201ea6f4.json b/.litho/cache/ai_code_insight/f1c2b75a29e47cae9bca4dde201ea6f4.json new file mode 100644 index 0000000..cbe87e4 --- /dev/null +++ b/.litho/cache/ai_code_insight/f1c2b75a29e47cae9bca4dde201ea6f4.json @@ -0,0 +1,85 @@ +{ + "data": { + "code_dossier": { + "name": "+layout.svelte", + "file_path": "app/src/routes/+layout.svelte", + "source_summary": "", + "code_purpose": "router", + "importance_score": 0.6, + "description": "SvelteKit路由布局组件,负责应用主题的初始化与系统级暗黑模式监听。", + "functions": [ + "onMount" + ], + "interfaces": [ + "themeListener" + ] + }, + "detailed_description": "该组件是SvelteKit应用的根布局组件,主要职责是在页面挂载时初始化UI主题。通过监听`prefers-color-scheme`媒体查询,动态响应用户的系统级深色/浅色模式偏好,并调用`$lib/themes`中的`applyTheme`和`setWebInnerOnly`函数进行主题应用与状态同步。使用`onMount`确保仅在客户端执行DOM相关操作,并正确清理事件监听器以避免内存泄漏。", + "responsibilities": [ + "监听系统颜色偏好变化以实现自动主题切换", + "初始化应用的主题配置", + "管理主题相关的事件监听器生命周期", + "作为路由布局容器提供内容渲染" + ], + "interfaces": [ + { + "name": "themeListener", + "interface_type": "function", + "visibility": "private", + "parameters": [ + { + "name": "event", + "param_type": "MediaQueryListEvent", + "is_optional": false, + "description": "媒体查询状态变更事件" + } + ], + "return_type": "void", + "description": "响应系统暗黑模式切换的事件处理器" + } + ], + "dependencies": [ + { + "name": "svelte", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "framework", + "version": null + }, + { + "name": "$lib/themes", + "path": "$lib/themes", + "is_external": false, + "line_number": 3, + "dependency_type": "library", + "version": null + }, + { + "name": "app.css", + "path": "app/src/app.css", + "is_external": false, + "line_number": 1, + "dependency_type": "stylesheet", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 20, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.15, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024729, + "prompt_hash": "f1c2b75a29e47cae9bca4dde201ea6f4", + "token_usage": { + "input_tokens": 545, + "output_tokens": 622, + "total_tokens": 1167 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f20e85176e96fbc66a38669eed2f8023.json b/.litho/cache/ai_code_insight/f20e85176e96fbc66a38669eed2f8023.json new file mode 100644 index 0000000..075b455 --- /dev/null +++ b/.litho/cache/ai_code_insight/f20e85176e96fbc66a38669eed2f8023.json @@ -0,0 +1,113 @@ +{ + "data": { + "code_dossier": { + "name": "init_app_config.rs", + "file_path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.9, + "description": "负责应用配置的初始化、读取与持久化,确保系统启动时具备有效的配置数据。", + "functions": [ + "call", + "sync_to", + "default_app_config" + ], + "interfaces": [ + "call", + "sync_to" + ] + }, + "detailed_description": "该组件是应用程序启动流程中的关键初始化模块,主要职责为加载或创建默认的应用配置(AppConfig)。它首先尝试从指定路径读取 TOML 格式的配置文件 `app_config.toml`,若文件不存在或读取失败,则生成一个包含默认值的 AppConfig 对象,并将其同步写入磁盘。配置内容涵盖 LLM 提供商设置(如 Ollama、OpenAI、GLM 等)、爬虫模块、日志、守护进程及诊断选项。通过调用 `InitTask` 异步任务机制,保证初始化过程的可追踪性和错误处理能力。`sync_to` 函数支持运行时动态保存配置,实现配置的持久化管理。", + "responsibilities": [ + "初始化并加载应用配置文件(TOML格式)", + "在配置缺失时提供结构完整且合理的默认配置", + "将内存中的配置对象持久化写入文件系统", + "集成到异步初始化任务框架中,支持可组合的任务执行流程", + "管理多LLM提供商的默认参数设置" + ], + "interfaces": [ + { + "name": "call", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "anyhow::Result>", + "description": "主入口函数,启动配置初始化任务,返回封装了结果的异步任务对象。" + }, + { + "name": "sync_to", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "app_config", + "param_type": "&AppConfig", + "is_optional": false, + "description": "待持久化的配置引用" + } + ], + "return_type": "anyhow::Result<()>", + "description": "将给定的 AppConfig 对象序列化为 TOML 并写入磁盘文件。" + }, + { + "name": "default_app_config", + "interface_type": "function", + "visibility": "private", + "parameters": [], + "return_type": "AppConfig", + "description": "构建并返回一个具有默认字段值的应用配置实例。" + } + ], + "dependencies": [ + { + "name": "tokio", + "path": null, + "is_external": true, + "line_number": 1, + "dependency_type": "async_runtime", + "version": null + }, + { + "name": "recorder", + "path": null, + "is_external": true, + "line_number": 5, + "dependency_type": "utility", + "version": null + }, + { + "name": "types", + "path": "crates/types", + "is_external": false, + "line_number": 7, + "dependency_type": "model", + "version": null + }, + { + "name": "toml", + "path": null, + "is_external": true, + "line_number": null, + "dependency_type": "serialization", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 76, + "number_of_functions": 3, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.4, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024235, + "prompt_hash": "f20e85176e96fbc66a38669eed2f8023", + "token_usage": { + "input_tokens": 1043, + "output_tokens": 967, + "total_tokens": 2010 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f3bccab8840913564a2b9ac5f196e846.json b/.litho/cache/ai_code_insight/f3bccab8840913564a2b9ac5f196e846.json new file mode 100644 index 0000000..562f923 --- /dev/null +++ b/.litho/cache/ai_code_insight/f3bccab8840913564a2b9ac5f196e846.json @@ -0,0 +1,108 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/tauri-plugin-feed-api/src/lib.rs", + "code_purpose": "api", + "importance_score": 0.8, + "description": "Tauri插件的核心模块,定义了与订阅源管理、内容抓取和AI助手交互的全部API接口。负责初始化应用上下文并注册所有命令处理器。", + "functions": [ + "init" + ], + "interfaces": [] + }, + "detailed_description": "该组件是feed-api功能的核心Tauri插件入口,通过`init`函数创建并配置TauriPlugin实例。它集成了来自feed_api_rs后端服务的功能API,并通过调用`generate_handler!`宏将commands模块中定义的25个异步命令暴露给前端调用。插件在setup阶段异步启动应用上下文(Startup::launch),并将FeaturesAPIImpl实例包装在Arc智能指针中进行全局状态管理。同时实现了macOS平台特定的窗口重开逻辑,确保应用从Dock点击时能正确显示主窗口。所有外部命令都通过State机制安全地访问共享的HybridRuntimeState状态对象。", + "responsibilities": [ + "作为Tauri插件注册并暴露所有feed相关API命令", + "初始化并管理应用核心功能组件(FeaturesAPI)的生命周期", + "在运行时全局状态中安全地托管共享服务实例", + "处理跨平台特定事件(如macOS重新打开应用)", + "协调前端请求与后端业务逻辑之间的桥梁作用" + ], + "interfaces": [ + { + "name": "init", + "interface_type": "function", + "visibility": "public", + "parameters": [], + "return_type": "TauriPlugin", + "description": "初始化并构建feed-api插件,注册所有命令处理器,设置全局状态和事件监听器" + } + ], + "dependencies": [ + { + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + }, + { + "name": "tauri", + "path": "tauri", + "is_external": true, + "line_number": 3, + "dependency_type": "import", + "version": null + }, + { + "name": "feed_api_rs::application_context::ContextHost", + "path": "feed_api_rs::application_context::ContextHost", + "is_external": true, + "line_number": 7, + "dependency_type": "import", + "version": null + }, + { + "name": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "path": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "is_external": true, + "line_number": 8, + "dependency_type": "import", + "version": null + }, + { + "name": "feed_api_rs::startup::Startup", + "path": "feed_api_rs::startup::Startup", + "is_external": true, + "line_number": 9, + "dependency_type": "import", + "version": null + }, + { + "name": "crate::commands", + "path": "crates/tauri-plugin-feed-api/src/commands.rs", + "is_external": false, + "line_number": 11, + "dependency_type": "import", + "version": null + }, + { + "name": "crate::state::HybridRuntimeState", + "path": "crates/tauri-plugin-feed-api/src/state/mod.rs", + "is_external": false, + "line_number": 13, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 86, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805640, + "prompt_hash": "f3bccab8840913564a2b9ac5f196e846", + "token_usage": { + "input_tokens": 3400, + "output_tokens": 963, + "total_tokens": 4363 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f47463c7ae23c2d554caae4cf5663c35.json b/.litho/cache/ai_code_insight/f47463c7ae23c2d554caae4cf5663c35.json new file mode 100644 index 0000000..d9d3b4e --- /dev/null +++ b/.litho/cache/ai_code_insight/f47463c7ae23c2d554caae4cf5663c35.json @@ -0,0 +1,105 @@ +{ + "data": { + "code_dossier": { + "name": "sprite.svelte.ts", + "file_path": "app/src/routes/main/stores/sprite.svelte.ts", + "code_purpose": "controller", + "importance_score": 1.0, + "description": "管理对话状态和交互的Svelte store,用于处理用户与文章助手之间的聊天逻辑。", + "functions": [ + "create", + "send", + "cleanUp", + "toggle" + ], + "interfaces": [ + "StoreType", + "ConversationInput", + "ConversationMessage" + ] + }, + "detailed_description": "该组件是一个Svelte状态管理store,负责管理一个对话窗口的打开/关闭状态、消息历史记录以及发送新消息的逻辑。它通过调用外部API(featuresApi.chat_with_article_assistant)实现与文章相关的智能助手对话功能,并集成loading状态以控制UI加载反馈。当对话框关闭时会清理历史记录和加载状态。组件使用$state进行响应式状态管理,符合Svelte 5的信号语法。", + "responsibilities": [ + "管理对话界面的展开/收起状态", + "维护用户与系统之间的消息历史记录", + "封装向文章助手发送消息并接收回复的异步逻辑", + "协调loading状态以反映请求过程中的UI反馈", + "在对话关闭时清理本地状态数据" + ], + "interfaces": [ + { + "name": "StoreType", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": null, + "description": "定义了对话store的公开接口结构,包括状态字段和方法" + }, + { + "name": "create", + "interface_type": "function", + "visibility": "exported", + "parameters": [ + { + "name": "context", + "param_type": "IContext", + "is_optional": false, + "description": "提供当前上下文信息,如当前文章ID" + } + ], + "return_type": "StoreType", + "description": "工厂函数,用于创建并初始化一个新的对话store实例" + }, + { + "name": "send", + "interface_type": "function", + "visibility": "internal", + "parameters": [ + { + "name": "input", + "param_type": "ConversationInput", + "is_optional": false, + "description": "用户输入的消息内容" + } + ], + "return_type": "Promise", + "description": "发送用户消息并获取助手回复,返回操作是否成功" + } + ], + "dependencies": [ + { + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "is_external": true, + "line_number": 4, + "dependency_type": "api", + "version": null + }, + { + "name": "LoadingStore", + "path": "./loading.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "store", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 3.0, + "lines_of_code": 90, + "number_of_functions": 4, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.67, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801010, + "prompt_hash": "f47463c7ae23c2d554caae4cf5663c35", + "token_usage": { + "input_tokens": 919, + "output_tokens": 840, + "total_tokens": 1759 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f48390bc5679776b9834f47f13ff85f9.json b/.litho/cache/ai_code_insight/f48390bc5679776b9834f47f13ff85f9.json new file mode 100644 index 0000000..b69db58 --- /dev/null +++ b/.litho/cache/ai_code_insight/f48390bc5679776b9834f47f13ff85f9.json @@ -0,0 +1,38 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/index.ts", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "项目执行入口文件,用于通过 `$lib` 别名导入所需模块", + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个占位性质的入口文件,主要作用是作为 `$lib` 模块别名的导入目标。当前文件仅包含注释说明,未实际导出或导入任何功能模块。其设计意图是为项目提供一个统一的库导入路径,便于模块管理和引用。", + "responsibilities": [ + "作为 `$lib` 别名的入口点,集中管理可复用的库模块", + "提供模块导入的标准化路径,增强代码组织结构", + "作为项目架构中的公共依赖聚合层(当前未实现)" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805711, + "prompt_hash": "f48390bc5679776b9834f47f13ff85f9", + "token_usage": { + "input_tokens": 418, + "output_tokens": 366, + "total_tokens": 784 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f6d899c0803ef1ddcfe74878756a3492.json b/.litho/cache/ai_code_insight/f6d899c0803ef1ddcfe74878756a3492.json new file mode 100644 index 0000000..09eaf52 --- /dev/null +++ b/.litho/cache/ai_code_insight/f6d899c0803ef1ddcfe74878756a3492.json @@ -0,0 +1,328 @@ +{ + "data": { + "code_dossier": { + "name": "types.ts", + "file_path": "app/src/routes/main/widgets/types.ts", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "定义前端组件间通信的类型接口,主要用于Svelte组件的props类型声明", + "functions": [], + "interfaces": [ + "FeedsListProps", + "SearchBarProps", + "ArticleReaderProps", + "ArticlesGroup", + "ArticlesListProps", + "FooterProps", + "AISpriteProps", + "ArticleReadMode" + ] + }, + "detailed_description": "该文件是Svelte前端应用中的类型定义中心,专门用于定义UI组件之间的属性传递接口(Props)。它通过TypeScript的interface和type语法,为多个Svelte组件提供类型安全的props定义,包括Feeds列表、搜索栏、文章阅读器、文章分组列表、页脚和AI精灵等组件。同时定义了文章阅读模式的字面量联合类型。所有类型均通过export type导出,确保类型仅在编译时使用,不产生运行时开销。", + "responsibilities": [ + "为Feeds列表组件提供类型定义", + "为文章阅读器组件提供类型定义", + "定义文章列表分组的数据结构", + "管理跨组件的状态store类型引用", + "定义UI交互事件的回调函数签名" + ], + "interfaces": [ + { + "name": "FeedsListProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "FeedsStoreType", + "is_optional": false, + "description": "Feeds状态管理store" + }, + { + "name": "selectedFeedId", + "param_type": "string | undefined", + "is_optional": true, + "description": "当前选中的feed ID" + }, + { + "name": "onFeedPressed", + "param_type": "(feedId: string) => void", + "is_optional": false, + "description": "feed项点击回调" + }, + { + "name": "onSelectToday", + "param_type": "() => void", + "is_optional": false, + "description": "选择今日内容回调" + }, + { + "name": "onSelectWeekend", + "param_type": "() => void", + "is_optional": false, + "description": "选择周末内容回调" + }, + { + "name": "isTodaySelected", + "param_type": "boolean", + "is_optional": false, + "description": "今日筛选是否激活" + }, + { + "name": "isWeekendSelected", + "param_type": "boolean", + "is_optional": false, + "description": "周末筛选是否激活" + }, + { + "name": "onSelectFavorite", + "param_type": "() => void", + "is_optional": false, + "description": "选择收藏内容回调" + }, + { + "name": "isFavoriteSelected", + "param_type": "boolean", + "is_optional": false, + "description": "收藏筛选是否激活" + }, + { + "name": "onSelectUnread", + "param_type": "() => void", + "is_optional": false, + "description": "选择未读内容回调" + }, + { + "name": "isUnreadSelected", + "param_type": "boolean", + "is_optional": false, + "description": "未读筛选是否激活" + } + ], + "return_type": null, + "description": "Feeds列表组件的props类型,包含筛选状态和交互回调" + }, + { + "name": "SearchBarProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "SearchStoreType", + "is_optional": false, + "description": "搜索功能的状态store" + }, + { + "name": "articles_store", + "param_type": "ListStoreType", + "is_optional": false, + "description": "文章列表的状态store" + } + ], + "return_type": null, + "description": "搜索栏组件的props类型,需要访问搜索和文章列表两个store" + }, + { + "name": "ArticleReaderProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "articleId", + "param_type": "number", + "is_optional": false, + "description": "要阅读的文章ID" + }, + { + "name": "store", + "param_type": "ReaderStoreType", + "is_optional": false, + "description": "阅读器状态管理store" + } + ], + "return_type": null, + "description": "文章阅读器组件的props类型" + }, + { + "name": "ArticlesGroup", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "name", + "param_type": "string", + "is_optional": false, + "description": "文章分组名称" + }, + { + "name": "articles", + "param_type": "Article[]", + "is_optional": false, + "description": "该分组下的文章数组" + } + ], + "return_type": null, + "description": "文章分组的数据结构,用于组织文章列表" + }, + { + "name": "ArticlesListProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "ListStoreType", + "is_optional": false, + "description": "文章列表状态管理store" + }, + { + "name": "markAsRead", + "param_type": "(articleId: number) => Promise", + "is_optional": false, + "description": "标记文章为已读的异步函数" + }, + { + "name": "isFilterActived", + "param_type": "boolean", + "is_optional": false, + "description": "过滤器是否激活" + }, + { + "name": "isFeedSpecified", + "param_type": "boolean", + "is_optional": false, + "description": "是否指定了特定feed" + }, + { + "name": "selectedArticle", + "param_type": "Article | null", + "is_optional": true, + "description": "当前选中的文章" + }, + { + "name": "onArticlePressed", + "param_type": "(article: Article) => void", + "is_optional": false, + "description": "文章项点击回调" + } + ], + "return_type": null, + "description": "文章列表组件的props类型,包含状态store和用户交互处理" + }, + { + "name": "FooterProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "tasksStore", + "param_type": "TasksStoreType", + "is_optional": false, + "description": "任务状态管理store" + } + ], + "return_type": null, + "description": "页脚组件的props类型" + }, + { + "name": "AISpriteProps", + "interface_type": "interface", + "visibility": "exported", + "parameters": [ + { + "name": "store", + "param_type": "AISpriteStore", + "is_optional": false, + "description": "AI精灵状态管理store" + } + ], + "return_type": null, + "description": "AI精灵组件的props类型" + }, + { + "name": "ArticleReadMode", + "interface_type": "type", + "visibility": "exported", + "parameters": [], + "return_type": "'optimized' | 'melted' | 'original'", + "description": "文章阅读模式的三种可选值" + } + ], + "dependencies": [ + { + "name": "Article", + "path": "$lib/types/article", + "is_external": false, + "line_number": 1, + "dependency_type": "type_import", + "version": null + }, + { + "name": "SearchStoreType", + "path": "../stores/articles/search/index.svelte", + "is_external": false, + "line_number": 2, + "dependency_type": "type_import", + "version": null + }, + { + "name": "ListStoreType", + "path": "../stores/articles/list/index.svelte", + "is_external": false, + "line_number": 3, + "dependency_type": "type_import", + "version": null + }, + { + "name": "TasksStoreType", + "path": "../stores/tasks.svelte", + "is_external": false, + "line_number": 4, + "dependency_type": "type_import", + "version": null + }, + { + "name": "FeedsStoreType", + "path": "../stores/feeds.svelte", + "is_external": false, + "line_number": 5, + "dependency_type": "type_import", + "version": null + }, + { + "name": "ReaderStoreType", + "path": "../stores/reader.svelte", + "is_external": false, + "line_number": 6, + "dependency_type": "type_import", + "version": null + }, + { + "name": "AISpriteStore", + "path": "../stores/sprite.svelte", + "is_external": false, + "line_number": 7, + "dependency_type": "type_import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 66, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 7.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758801086, + "prompt_hash": "f6d899c0803ef1ddcfe74878756a3492", + "token_usage": { + "input_tokens": 825, + "output_tokens": 2042, + "total_tokens": 2867 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f72a93fbe97082e68bc29a0346bce434.json b/.litho/cache/ai_code_insight/f72a93fbe97082e68bc29a0346bce434.json new file mode 100644 index 0000000..32d68d4 --- /dev/null +++ b/.litho/cache/ai_code_insight/f72a93fbe97082e68bc29a0346bce434.json @@ -0,0 +1,67 @@ +{ + "data": { + "code_dossier": { + "name": "ReaderBlankIndicator.svelte", + "file_path": "app/src/routes/main/widgets/ReaderBlankIndicator.svelte", + "source_summary": "", + "code_purpose": "widget", + "importance_score": 0.8, + "description": "一个Svelte前端UI组件,用于在阅读器为空时显示提示信息。", + "functions": [], + "interfaces": [ + "i18n $_" + ] + }, + "detailed_description": "该组件是一个轻量级的Svelte UI组件,用于在阅读器内容为空时向用户提供视觉提示。它通过使用svelte-i18n库实现国际化文本渲染,展示四条依次排列的提示语句,引导用户理解当前状态。布局采用Flexbox垂直居中,并设置默认光标样式以表明其不可交互性。", + "responsibilities": [ + "在阅读器无内容时展示空白状态提示", + "支持多语言环境下的提示文本渲染", + "提供清晰的用户体验引导", + "保持简洁美观的UI布局结构" + ], + "interfaces": [ + { + "name": "$_", + "interface_type": "function", + "visibility": "external", + "parameters": [ + { + "name": "key", + "param_type": "string", + "is_optional": false, + "description": "国际化键值" + } + ], + "return_type": "string", + "description": "来自svelte-i18n的翻译函数,用于动态获取本地化字符串" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": 2, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 12, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.5, + "cohesion_score": 0.95 + } + }, + "timestamp": 1759024539, + "prompt_hash": "f72a93fbe97082e68bc29a0346bce434", + "token_usage": { + "input_tokens": 529, + "output_tokens": 516, + "total_tokens": 1045 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/f84775b81c7535e2266878815ef17842.json b/.litho/cache/ai_code_insight/f84775b81c7535e2266878815ef17842.json new file mode 100644 index 0000000..7843786 --- /dev/null +++ b/.litho/cache/ai_code_insight/f84775b81c7535e2266878815ef17842.json @@ -0,0 +1,38 @@ +{ + "data": { + "code_dossier": { + "name": "lib.rs", + "file_path": "crates/intelligent/src/lib.rs", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": null, + "functions": [], + "interfaces": [] + }, + "detailed_description": "该组件是一个Rust库的根模块,主要作用是组织和导出子模块`article_processor`。它本身不包含具体实现,而是作为功能模块的聚合点,用于将文章处理相关的功能封装并暴露给外部使用。这种设计符合Rust的模块系统最佳实践,便于代码组织和访问控制。", + "responsibilities": [ + "作为intelligent crate的根模块入口", + "组织和导出内部功能模块(article_processor)", + "提供清晰的模块边界和命名空间管理" + ], + "interfaces": [], + "dependencies": [], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 1, + "number_of_functions": 0, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 0.0, + "cohesion_score": 1.0 + } + }, + "timestamp": 1758805869, + "prompt_hash": "f84775b81c7535e2266878815ef17842", + "token_usage": { + "input_tokens": 417, + "output_tokens": 326, + "total_tokens": 743 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/fa50fd7e1714af56ef04d55902cc97b2.json b/.litho/cache/ai_code_insight/fa50fd7e1714af56ef04d55902cc97b2.json new file mode 100644 index 0000000..1c4b453 --- /dev/null +++ b/.litho/cache/ai_code_insight/fa50fd7e1714af56ef04d55902cc97b2.json @@ -0,0 +1,51 @@ +{ + "data": { + "code_dossier": { + "name": "index.ts", + "file_path": "app/src/lib/windows/index.ts", + "source_summary": "", + "code_purpose": "entry", + "importance_score": 0.8, + "description": "该文件是窗口模块的入口,负责导出窗口相关的功能,当前仅导出打开设置窗口的功能。", + "functions": [ + "openSettings" + ], + "interfaces": [] + }, + "detailed_description": "该组件作为窗口模块的公共入口文件,通过重新导出从 './settings' 模块导入的 open 函数,提供统一的访问接口。它简化了外部模块对窗口操作函数的引用路径,符合模块化设计中的聚合模式。", + "responsibilities": [ + "作为窗口模块的公共API入口", + "聚合并重新导出窗口相关功能", + "简化外部模块的导入路径", + "维护模块间依赖关系的清晰性" + ], + "interfaces": [], + "dependencies": [ + { + "name": "./settings", + "path": "app/src/lib/windows/settings", + "is_external": false, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 1.0, + "lines_of_code": 3, + "number_of_functions": 1, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.9 + } + }, + "timestamp": 1759024457, + "prompt_hash": "fa50fd7e1714af56ef04d55902cc97b2", + "token_usage": { + "input_tokens": 429, + "output_tokens": 397, + "total_tokens": 826 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/fa738e2eab71707900520d6be67b42e3.json b/.litho/cache/ai_code_insight/fa738e2eab71707900520d6be67b42e3.json new file mode 100644 index 0000000..95e8377 --- /dev/null +++ b/.litho/cache/ai_code_insight/fa738e2eab71707900520d6be67b42e3.json @@ -0,0 +1,121 @@ +{ + "data": { + "code_dossier": { + "name": "mod.rs", + "file_path": "crates/scrap/src/rss/mod.rs", + "code_purpose": "specificfeature", + "importance_score": 0.8, + "description": null, + "functions": [ + "fetch" + ], + "interfaces": [ + "IFetcher" + ] + }, + "detailed_description": "该组件实现了RSS内容抓取器(RSSFetcher),用于从指定的RSS feed URL中获取文章列表。其核心逻辑是:首先通过reqwest发起HTTP请求获取RSS XML内容,然后使用rss库解析Channel结构;接着遍历每个item,提取标题、链接和摘要信息;最后调用article_reader模块对每篇文章的正文内容进行深度读取与清洗,并构造包含完整信息的Article对象集合返回。整个过程支持异步处理,且具备基础错误处理机制。", + "responsibilities": [ + "实现RSS源的内容抓取逻辑", + "解析RSS XML数据并提取文章元信息", + "协调调用article_reader模块获取文章正文内容", + "构建并返回标准化的文章对象列表", + "处理缺失URL等基本输入验证异常" + ], + "interfaces": [ + { + "name": "IFetcher", + "interface_type": "trait", + "visibility": "public", + "parameters": [], + "return_type": null, + "description": "定义了通用内容抓取接口,RSSFetcher作为其实现提供RSS协议支持" + }, + { + "name": "fetch", + "interface_type": "method", + "visibility": "public", + "parameters": [ + { + "name": "_app_handle", + "param_type": "Option>", + "is_optional": true, + "description": null + }, + { + "name": "llm_section", + "param_type": "&LLMSection", + "is_optional": false, + "description": null + }, + { + "name": "ftd", + "param_type": "FeedTargetDescription", + "is_optional": false, + "description": null + } + ], + "return_type": "anyhow::Result>", + "description": "执行RSS抓取主流程,返回文章列表结果" + } + ], + "dependencies": [ + { + "name": "crate::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "is_external": false, + "line_number": 1, + "dependency_type": "trait", + "version": null + }, + { + "name": "rss::Channel", + "path": null, + "is_external": true, + "line_number": 2, + "dependency_type": "struct", + "version": null + }, + { + "name": "tauri::{AppHandle, Runtime}", + "path": null, + "is_external": true, + "line_number": 3, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::{Article, FeedTargetDescription, LLMSection}", + "path": "crates/scrap/src/types.rs", + "is_external": false, + "line_number": 4, + "dependency_type": "struct", + "version": null + }, + { + "name": "crate::article_reader", + "path": "crates/scrap/src/article_reader.rs", + "is_external": false, + "line_number": 5, + "dependency_type": "module", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 5.0, + "lines_of_code": 54, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 0.714, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805414, + "prompt_hash": "fa738e2eab71707900520d6be67b42e3", + "token_usage": { + "input_tokens": 2214, + "output_tokens": 815, + "total_tokens": 3029 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/fa7fea178035c6ef43a756cd3c73b949.json b/.litho/cache/ai_code_insight/fa7fea178035c6ef43a756cd3c73b949.json new file mode 100644 index 0000000..50c0af0 --- /dev/null +++ b/.litho/cache/ai_code_insight/fa7fea178035c6ef43a756cd3c73b949.json @@ -0,0 +1,100 @@ +{ + "data": { + "code_dossier": { + "name": "purge.rs", + "file_path": "crates/intelligent/src/article_processor/purge.rs", + "source_summary": "", + "code_purpose": "specificfeature", + "importance_score": 0.6, + "description": "实现文章内容清理的LLM处理器,通过预设系统提示和用户指令模板调用大模型完成文本净化任务。", + "functions": [ + "new_processor" + ], + "interfaces": [ + "IPresetArticleLLMProcessor" + ] + }, + "detailed_description": "该组件实现了IPresetArticleLLMProcessor接口,专门用于构建一个基于大语言模型的文章净化处理器。它通过加载两个外部提示文件(purge_sys.prompt和purge_suffix.prompt)作为系统提示和用户指令后缀,并配置适当的AI目标选项(如上下文长度为8192),来初始化ArticleLLMProcessor实例。其主要业务逻辑是在文章处理流程中执行内容清理操作,去除无关或冗余信息,提升后续处理的质量。", + "responsibilities": [ + "实现文章净化功能的LLM处理器创建逻辑", + "管理并加载用于内容清理的系统级和用户级提示模板", + "配置适合内容清理任务的大模型参数选项", + "遵循预设处理器接口规范完成实例化流程" + ], + "interfaces": [ + { + "name": "IPresetArticleLLMProcessor", + "interface_type": "trait", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "指定大模型服务的区域配置" + } + ], + "return_type": "anyhow::Result", + "description": "预设文章LLM处理器接口,定义了如何根据LLMSection创建处理器的标准方法。" + }, + { + "name": "new_processor", + "interface_type": "function", + "visibility": "public", + "parameters": [ + { + "name": "llm_section", + "param_type": "LLMSection", + "is_optional": false, + "description": "LLM服务区域配置" + } + ], + "return_type": "anyhow::Result", + "description": "创建一个新的文章净化处理器实例" + } + ], + "dependencies": [ + { + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "is_external": false, + "line_number": 1, + "dependency_type": "struct", + "version": null + }, + { + "name": "types::LLMSection", + "path": "types", + "is_external": false, + "line_number": 2, + "dependency_type": "type", + "version": null + }, + { + "name": "crate::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crate::article_processor::llm_processor", + "is_external": false, + "line_number": 4, + "dependency_type": "trait", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 2.0, + "lines_of_code": 19, + "number_of_functions": 1, + "number_of_classes": 1, + "depth_of_inheritance": 0, + "coupling_factor": 3.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1759024606, + "prompt_hash": "fa7fea178035c6ef43a756cd3c73b949", + "token_usage": { + "input_tokens": 601, + "output_tokens": 858, + "total_tokens": 1459 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/fc2b6b03438671e65dd4c18db50c2fd7.json b/.litho/cache/ai_code_insight/fc2b6b03438671e65dd4c18db50c2fd7.json new file mode 100644 index 0000000..d10d40b --- /dev/null +++ b/.litho/cache/ai_code_insight/fc2b6b03438671e65dd4c18db50c2fd7.json @@ -0,0 +1,69 @@ +{ + "data": { + "code_dossier": { + "name": "dom.ts", + "file_path": "app/src/lib/utils/dom.ts", + "code_purpose": "util", + "importance_score": 0.6, + "description": "提供DOM操作相关的工具函数,用于禁用右键菜单和观察元素可见性状态", + "functions": [ + "disableContextMenu", + "observeVisiblity" + ], + "interfaces": [ + "ObserveVisiblityOption" + ] + }, + "detailed_description": "该组件包含两个核心工具函数:disableContextMenu用于在浏览器环境中禁用指定节点的右键上下文菜单(但允许输入框等表单元素保留该功能),observeVisiblity用于通过IntersectionObserver API监听元素是否进入视口并执行回调。两个函数均返回包含destroy方法的对象,支持资源清理。代码具有良好的封装性和可复用性,专为Svelte等前端框架设计。", + "responsibilities": [ + "禁用非输入元素的右键上下文菜单", + "通过IntersectionObserver监听DOM元素可见性变化", + "提供可销毁的观察者模式实现以避免内存泄漏", + "在非浏览器环境(如SSR)中安全降级" + ], + "interfaces": [ + { + "name": "ObserveVisiblityOption", + "interface_type": "type", + "visibility": "exported", + "parameters": [ + { + "name": "callback", + "param_type": "(v: boolean) => void", + "is_optional": false, + "description": "当元素可见性状态改变时调用的回调函数" + } + ], + "return_type": null, + "description": "observeVisiblity函数的配置选项类型" + } + ], + "dependencies": [ + { + "name": "$app/environment", + "path": "$app/environment", + "is_external": true, + "line_number": 1, + "dependency_type": "import", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 4.0, + "lines_of_code": 46, + "number_of_functions": 2, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 1.0, + "cohesion_score": 0.85 + } + }, + "timestamp": 1758805991, + "prompt_hash": "fc2b6b03438671e65dd4c18db50c2fd7", + "token_usage": { + "input_tokens": 634, + "output_tokens": 593, + "total_tokens": 1227 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_insight/fd389f16b8f148c2bcb087f672dfb2c3.json b/.litho/cache/ai_code_insight/fd389f16b8f148c2bcb087f672dfb2c3.json new file mode 100644 index 0000000..e2198c2 --- /dev/null +++ b/.litho/cache/ai_code_insight/fd389f16b8f148c2bcb087f672dfb2c3.json @@ -0,0 +1,362 @@ +{ + "data": { + "code_dossier": { + "name": "FeedsList.svelte", + "file_path": "app/src/routes/main/widgets/FeedsList.svelte", + "code_purpose": "widget", + "importance_score": 1.0, + "description": "Svelte组件,用于渲染和管理订阅源列表,支持分组展开、上下文菜单、状态选择等功能。", + "functions": [ + "createRefreshFeedsAction", + "createFeedPackageMenus", + "createFeedMenus", + "toggleExpand", + "expandGroup", + "onAddFeedPressed" + ], + "interfaces": [ + "listSection", + "listSectionWithAction", + "listItem", + "listItemInner", + "listGroupItem" + ] + }, + "detailed_description": "该组件实现了一个完整的订阅源管理界面,包含多个功能区域:应用标题区、常用功能快捷入口(今日、本周、收藏等)、订阅分组列表及其内部的订阅项。每个分组支持展开/折叠操作,并通过上下文菜单提供创建、编辑、删除等交互行为。所有UI文本均支持国际化。组件通过props接收状态和回调函数,保持了良好的解耦性。使用Svelte的状态绑定机制($state)管理展开状态,并集成Tauri插件实现原生对话框提示。", + "responsibilities": [ + "渲染多层级的订阅源列表结构", + "处理用户与订阅分组及条目的交互逻辑", + "管理分组展开/折叠状态", + "集成上下文菜单以支持增删改操作", + "协调国际化文本显示" + ], + "interfaces": [ + { + "name": "listSection", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": "显示的标题文本" + } + ], + "return_type": null, + "description": "渲染一个无操作的标题区块" + }, + { + "name": "listSectionWithAction", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "onclick", + "param_type": "Function", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "渲染带右侧图标的可点击标题区块" + }, + { + "name": "listItem", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "onclick", + "param_type": "Function", + "is_optional": false, + "description": null + }, + { + "name": "stateSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "menus", + "param_type": "Array", + "is_optional": true, + "description": null + } + ], + "return_type": null, + "description": "通用列表项渲染器,可选地包装上下文菜单" + }, + { + "name": "listItemInner", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "stateSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "实际的内容展示单元" + }, + { + "name": "listGroupItem", + "interface_type": "snippet", + "visibility": "private", + "parameters": [ + { + "name": "text", + "param_type": "string", + "is_optional": false, + "description": null + }, + { + "name": "IconRender", + "param_type": "Component", + "is_optional": false, + "description": null + }, + { + "name": "onclick", + "param_type": "Function", + "is_optional": false, + "description": null + }, + { + "name": "stateSelected", + "param_type": "boolean", + "is_optional": false, + "description": null + }, + { + "name": "menus", + "param_type": "Array", + "is_optional": false, + "description": null + } + ], + "return_type": null, + "description": "专用于分组项的渲染模板,强制包含上下文菜单" + } + ], + "dependencies": [ + { + "name": "svelte-i18n", + "path": "svelte-i18n", + "is_external": true, + "line_number": null, + "dependency_type": "i18n", + "version": null + }, + { + "name": "@tauri-apps/plugin-dialog", + "path": "@tauri-apps/plugin-dialog", + "is_external": true, + "line_number": null, + "dependency_type": "plugin", + "version": null + }, + { + "name": "$lib/widgets/ContextMenuProvider.svelte", + "path": "$lib/widgets/ContextMenuProvider.svelte", + "is_external": false, + "line_number": null, + "dependency_type": "component", + "version": null + }, + { + "name": "lucide-svelte/icons/plus", + "path": "lucide-svelte/icons/plus", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/folder", + "path": "lucide-svelte/icons/folder", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/folder-open", + "path": "lucide-svelte/icons/folder-open", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/circle-plus", + "path": "lucide-svelte/icons/circle-plus", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/package", + "path": "lucide-svelte/icons/package", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/newspaper", + "path": "lucide-svelte/icons/newspaper", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/settings", + "path": "lucide-svelte/icons/settings", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/globe", + "path": "lucide-svelte/icons/globe", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/file-heart", + "path": "lucide-svelte/icons/file-heart", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "lucide-svelte/icons/eye-off", + "path": "lucide-svelte/icons/eye-off", + "is_external": true, + "line_number": null, + "dependency_type": "icon", + "version": null + }, + { + "name": "./types", + "path": "./types", + "is_external": false, + "line_number": null, + "dependency_type": "type", + "version": null + }, + { + "name": "../stores/loading.svelte", + "path": "../stores/loading.svelte", + "is_external": false, + "line_number": null, + "dependency_type": "store", + "version": null + }, + { + "name": "$lib/windows/index", + "path": "$lib/windows/index", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "is_external": false, + "line_number": null, + "dependency_type": "type", + "version": null + }, + { + "name": "$lib/windows/lite-edit", + "path": "$lib/windows/lite-edit", + "is_external": false, + "line_number": null, + "dependency_type": "module", + "version": null + }, + { + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "is_external": false, + "line_number": null, + "dependency_type": "utility", + "version": null + }, + { + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "is_external": false, + "line_number": null, + "dependency_type": "utility", + "version": null + } + ], + "complexity_metrics": { + "cyclomatic_complexity": 6.0, + "lines_of_code": 263, + "number_of_functions": 6, + "number_of_classes": 0, + "depth_of_inheritance": 0, + "coupling_factor": 19.0, + "cohesion_score": 0.75 + } + }, + "timestamp": 1758801067, + "prompt_hash": "fd389f16b8f148c2bcb087f672dfb2c3", + "token_usage": { + "input_tokens": 2265, + "output_tokens": 1935, + "total_tokens": 4200 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/097defe81d5298e1842d3fa7c2196dab.json b/.litho/cache/ai_code_purpose/097defe81d5298e1842d3fa7c2196dab.json new file mode 100644 index 0000000..678f3e6 --- /dev/null +++ b/.litho/cache/ai_code_purpose/097defe81d5298e1842d3fa7c2196dab.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于article_processor目录下,名为purge.rs,实现了一个用于处理文章内容的特定功能组件。代码中定义了Purge结构体并实现了IPresetArticleLLMProcessor接口,主要用于创建一个带有特定系统提示和用户提示命令的ArticleLLMProcessor实例。其核心职责是为文章处理流程提供预设的LLM处理器配置,属于实现特定逻辑功能的组件,而非通用工具或模型定义。" + }, + "timestamp": 1758800886, + "prompt_hash": "097defe81d5298e1842d3fa7c2196dab", + "token_usage": { + "input_tokens": 389, + "output_tokens": 216, + "total_tokens": 605 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/0d3de532a250fcc7b15c32e9594b1cf7.json b/.litho/cache/ai_code_purpose/0d3de532a250fcc7b15c32e9594b1cf7.json new file mode 100644 index 0000000..c0f2745 --- /dev/null +++ b/.litho/cache/ai_code_purpose/0d3de532a250fcc7b15c32e9594b1cf7.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`providers`目录下,文件名为`llm_ollama.rs`,实现了与Ollama LLM模型交互的特定功能。代码中定义了请求和响应结构体、以及`OllamaCompletionService`结构体及其方法,专注于完成Ollama模型的补全服务。此类功能属于实现特定业务逻辑的功能模块,而非通用工具或模型定义,因此归类为'specificfeature'。" + }, + "timestamp": 1758800684, + "prompt_hash": "0d3de532a250fcc7b15c32e9594b1cf7", + "token_usage": { + "input_tokens": 462, + "output_tokens": 183, + "total_tokens": 645 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/0e1c0d14f3d82a9a019a861dc0b3c27a.json b/.litho/cache/ai_code_purpose/0e1c0d14f3d82a9a019a861dc0b3c27a.json new file mode 100644 index 0000000..f812bce --- /dev/null +++ b/.litho/cache/ai_code_purpose/0e1c0d14f3d82a9a019a861dc0b3c27a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.85, + "reasoning": "该文件位于crates/recorder/src/目录下,文件名为lib.rs,是Rust项目中的库模块入口。文件内容显示其导出了多个模块(article_recorder_service、entity、path等),且包含一个私有模块operator,表明这是一个封装了特定功能逻辑的组件。结合路径中的'recorder'名称,可推断此库负责记录相关功能,属于实现特定业务逻辑的功能模块,因此归类为specificfeature。" + }, + "timestamp": 1758800919, + "prompt_hash": "0e1c0d14f3d82a9a019a861dc0b3c27a", + "token_usage": { + "input_tokens": 226, + "output_tokens": 202, + "total_tokens": 428 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/0fd6b783fc38cc85f045cead6c0b1895.json b/.litho/cache/ai_code_purpose/0fd6b783fc38cc85f045cead6c0b1895.json new file mode 100644 index 0000000..aece2bd --- /dev/null +++ b/.litho/cache/ai_code_purpose/0fd6b783fc38cc85f045cead6c0b1895.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`src/search/`目录下,定义了一个搜索功能的模块,包含多个子模块(如baidu、bing等)和一个枚举类型`ScrapProviderEnums`,实现了`IProvider`和`IFetcher`两个trait。其主要职责是聚合不同搜索引擎的实现并提供统一的搜索与抓取接口,属于实现特定业务逻辑的功能组件,因此归类为'specificfeature'。" + }, + "timestamp": 1758800788, + "prompt_hash": "0fd6b783fc38cc85f045cead6c0b1895", + "token_usage": { + "input_tokens": 458, + "output_tokens": 179, + "total_tokens": 637 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/123aea93baa3f2422fd0263711da45d6.json b/.litho/cache/ai_code_purpose/123aea93baa3f2422fd0263711da45d6.json new file mode 100644 index 0000000..3995931 --- /dev/null +++ b/.litho/cache/ai_code_purpose/123aea93baa3f2422fd0263711da45d6.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件位于i18n/locales目录下,文件名为zh.json,内容为中文语言的键值对配置,包含产品名称、菜单项、提示文本等UI文案。此类文件通常用于多语言国际化配置,属于配置文件范畴。" + }, + "timestamp": 1758800968, + "prompt_hash": "123aea93baa3f2422fd0263711da45d6", + "token_usage": { + "input_tokens": 646, + "output_tokens": 120, + "total_tokens": 766 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/14db9ebb6b6d5b78dcf4abe4f8b2d537.json b/.litho/cache/ai_code_purpose/14db9ebb6b6d5b78dcf4abe4f8b2d537.json new file mode 100644 index 0000000..dd335e0 --- /dev/null +++ b/.litho/cache/ai_code_purpose/14db9ebb6b6d5b78dcf4abe4f8b2d537.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件定义了一个任务初始化器(TaskInitializer)和一个初始化任务结构体(InitTask),主要用于管理异步任务的启动、状态跟踪和性能统计。文件位于startup目录下,表明其职责与系统启动过程中的任务初始化相关。代码中包含异步函数、状态枚举和性能计时逻辑,具有明确的特定功能实现特征,因此归类为'specificfeature'。" + }, + "timestamp": 1758800713, + "prompt_hash": "14db9ebb6b6d5b78dcf4abe4f8b2d537", + "token_usage": { + "input_tokens": 460, + "output_tokens": 202, + "total_tokens": 662 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/16d73c4d0ebf315247bfdf668082a859.json b/.litho/cache/ai_code_purpose/16d73c4d0ebf315247bfdf668082a859.json new file mode 100644 index 0000000..a10d937 --- /dev/null +++ b/.litho/cache/ai_code_purpose/16d73c4d0ebf315247bfdf668082a859.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于 `providers` 目录下,文件名为 `llm_glm.rs`,表明其与特定的 LLM(大语言模型)提供商 GLM 相关。代码中定义了 `GLMCompletionService` 结构体并实现了 `CompletionService` trait,用于封装 GLM 模型的补全服务逻辑。它复用了 OpenAI 类似的实现(`OpenAILikeCompletionService`),但针对 GLM 配置进行了适配。这属于实现特定功能逻辑的组件,而非通用工具、模型定义或配置文件。因此,归类为 'specificfeature' 最为合适。" + }, + "timestamp": 1758800690, + "prompt_hash": "16d73c4d0ebf315247bfdf668082a859", + "token_usage": { + "input_tokens": 460, + "output_tokens": 227, + "total_tokens": 687 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/1775842716fe5c8e3c17b18c97c0e67e.json b/.litho/cache/ai_code_purpose/1775842716fe5c8e3c17b18c97c0e67e.json new file mode 100644 index 0000000..36460a6 --- /dev/null +++ b/.litho/cache/ai_code_purpose/1775842716fe5c8e3c17b18c97c0e67e.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件位于`crates/recorder/src/path.rs`,主要职责是处理与文件路径相关的操作,如构建、确保目录存在等。文件中定义了多个公共函数用于获取应用数据目录下的数据库文件或子目录路径,并包含辅助函数来创建必要的目录结构。这些功能属于典型的工具类代码,不涉及UI、接口控制、业务逻辑实现或数据模型定义,因此归类为'util'(工具类的代码)。" + }, + "timestamp": 1758800811, + "prompt_hash": "1775842716fe5c8e3c17b18c97c0e67e", + "token_usage": { + "input_tokens": 583, + "output_tokens": 220, + "total_tokens": 803 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/18c58c159b16a49a9bca374812886197.json b/.litho/cache/ai_code_purpose/18c58c159b16a49a9bca374812886197.json new file mode 100644 index 0000000..71af1af --- /dev/null +++ b/.litho/cache/ai_code_purpose/18c58c159b16a49a9bca374812886197.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.85, + "reasoning": "文件路径为crates/llm/src/lib.rs,位于一个名为llm的crate中,通常表示与语言模型相关的功能。文件内容导出了mod llm_agent和providers,其中llm_agent模块很可能实现了基于LLM的智能Agent功能。同时,存在connector模块,可能用于连接不同LLM服务,进一步支持了这是一个Agent组件的判断。文件名为lib.rs,是Rust库的入口,整体结构表明该文件组织的是与LLM Agent相关的核心逻辑。" + }, + "timestamp": 1758800866, + "prompt_hash": "18c58c159b16a49a9bca374812886197", + "token_usage": { + "input_tokens": 218, + "output_tokens": 213, + "total_tokens": 431 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/1b4710821771eafb5053a0e2344c824a.json b/.litho/cache/ai_code_purpose/1b4710821771eafb5053a0e2344c824a.json new file mode 100644 index 0000000..e479c21 --- /dev/null +++ b/.litho/cache/ai_code_purpose/1b4710821771eafb5053a0e2344c824a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "api", + "confidence": 0.85, + "reasoning": "文件位于 `crates/feed_api_rs/src/` 路径下,表明这是一个 Rust 的 crate,且项目名称包含 'api',暗示其为 API 相关模块。文件名为 `lib.rs`,是 Rust 库的入口文件。内容中通过 `pub mod` 导出了多个模块,如 `application_context`、`features`、`startup` 等,结构清晰,符合后端 API 服务的组织方式。无 UI 或前端相关特征,因此判断为后端 API 接口定义或实现组件。" + }, + "timestamp": 1758800873, + "prompt_hash": "1b4710821771eafb5053a0e2344c824a", + "token_usage": { + "input_tokens": 226, + "output_tokens": 190, + "total_tokens": 416 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/2325899079672d681cc027a09435dbde.json b/.litho/cache/ai_code_purpose/2325899079672d681cc027a09435dbde.json new file mode 100644 index 0000000..c9a1bc2 --- /dev/null +++ b/.litho/cache/ai_code_purpose/2325899079672d681cc027a09435dbde.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件位于 Tauri 项目的 src-tauri 目录下,文件名为 build.rs,是 Rust 项目中常见的构建脚本。其内容仅包含调用 tauri_build::build(),用于在编译时生成必要的绑定和配置信息。此类文件通常用于构建流程的配置和代码生成,不包含业务逻辑或可执行入口,因此最符合 'config' 类型。" + }, + "timestamp": 1758800935, + "prompt_hash": "2325899079672d681cc027a09435dbde", + "token_usage": { + "input_tokens": 216, + "output_tokens": 171, + "total_tokens": 387 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/273dbb27b9cba520d7fb67e400bbdf14.json b/.litho/cache/ai_code_purpose/273dbb27b9cba520d7fb67e400bbdf14.json new file mode 100644 index 0000000..a1f28e7 --- /dev/null +++ b/.litho/cache/ai_code_purpose/273dbb27b9cba520d7fb67e400bbdf14.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.9, + "reasoning": "该文件位于startup目录下,文件名为init_user_profile.rs,内容主要实现用户配置的初始化逻辑,包括读取或创建默认的用户配置文件(如TOML格式),并提供同步到存储的功能。其职责是处理特定的初始化业务逻辑,属于特定功能模块,而非通用工具或模型定义。因此归类为'specificfeature'。" + }, + "timestamp": 1758800703, + "prompt_hash": "273dbb27b9cba520d7fb67e400bbdf14", + "token_usage": { + "input_tokens": 467, + "output_tokens": 179, + "total_tokens": 646 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/29d001d6ae21fd5e4077ef6b404f0ab5.json b/.litho/cache/ai_code_purpose/29d001d6ae21fd5e4077ef6b404f0ab5.json new file mode 100644 index 0000000..2ef8c8e --- /dev/null +++ b/.litho/cache/ai_code_purpose/29d001d6ae21fd5e4077ef6b404f0ab5.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件定义了结构体 `AITargetOption` 和 trait `CompletionService`,主要用于描述数据模型和接口契约。文件位于 `providers` 目录下的 `types.rs`,典型用于定义类型。`AITargetOption` 实现了 `Serialize` 和 `Deserialize`,表明其作为数据传输对象使用,符合模型(model)的特征。因此判断为 'model' 类型组件。" + }, + "timestamp": 1758800858, + "prompt_hash": "29d001d6ae21fd5e4077ef6b404f0ab5", + "token_usage": { + "input_tokens": 413, + "output_tokens": 160, + "total_tokens": 573 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/2b146e8c900a427832d0f40b2fe82d4a.json b/.litho/cache/ai_code_purpose/2b146e8c900a427832d0f40b2fe82d4a.json new file mode 100644 index 0000000..367aafe --- /dev/null +++ b/.litho/cache/ai_code_purpose/2b146e8c900a427832d0f40b2fe82d4a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "controller", + "confidence": 0.95, + "reasoning": "该文件位于 `src/commands.rs`,属于 Tauri 插件的一部分。文件中定义了多个使用 `#[tauri::command]` 宏标记的异步函数(如 `add_feeds_package`、`remove_feeds_package`),这些函数用于暴露 Rust 后端功能给前端调用,符合 Tauri 中 Controller 或命令处理层的典型特征。同时,它依赖 `State` 管理应用状态,并与业务逻辑模块(如 `features_api`)交互,进一步表明其作为后端接口控制器的角色。" + }, + "timestamp": 1758800827, + "prompt_hash": "2b146e8c900a427832d0f40b2fe82d4a", + "token_usage": { + "input_tokens": 463, + "output_tokens": 208, + "total_tokens": 671 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/2b3a1a43f1a8ee478955d04ec6356bab.json b/.litho/cache/ai_code_purpose/2b3a1a43f1a8ee478955d04ec6356bab.json new file mode 100644 index 0000000..8ff492b --- /dev/null +++ b/.litho/cache/ai_code_purpose/2b3a1a43f1a8ee478955d04ec6356bab.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.98, + "reasoning": "该文件是一个Tauri应用的配置文件(tauri.conf.json),位于src-tauri目录下,属于Rust/Tauri项目的标准配置结构。文件以JSON格式定义了应用的元信息(如名称、版本、标识符)、构建指令(dev和build命令、前端资源路径)、窗口配置、安全策略和打包设置等,不包含任何可执行逻辑或业务代码,完全符合配置文件的特征。" + }, + "timestamp": 1758800928, + "prompt_hash": "2b3a1a43f1a8ee478955d04ec6356bab", + "token_usage": { + "input_tokens": 470, + "output_tokens": 188, + "total_tokens": 658 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/318c6a8e2773b044da69465616cceed8.json b/.litho/cache/ai_code_purpose/318c6a8e2773b044da69465616cceed8.json new file mode 100644 index 0000000..cf4e926 --- /dev/null +++ b/.litho/cache/ai_code_purpose/318c6a8e2773b044da69465616cceed8.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "该文件位于Tauri框架的src目录下,文件名为lib.rs,表明这是一个Rust库模块。代码中定义了多个模块(mod),并使用Tauri插件系统初始化各种功能,如自动启动、对话框、剪贴板管理等。`run`函数作为入口点配置Tauri应用,并集成后台任务(如feeds定时更新)和系统托盘功能。结合其职责——协调后台服务、插件管理和系统交互,符合'智能Agent'的特征,负责自动化和系统级任务调度。" + }, + "timestamp": 1758800834, + "prompt_hash": "318c6a8e2773b044da69465616cceed8", + "token_usage": { + "input_tokens": 457, + "output_tokens": 230, + "total_tokens": 687 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/35179b3e23902ccd7f8d54200802ee54.json b/.litho/cache/ai_code_purpose/35179b3e23902ccd7f8d54200802ee54.json new file mode 100644 index 0000000..a5420e4 --- /dev/null +++ b/.litho/cache/ai_code_purpose/35179b3e23902ccd7f8d54200802ee54.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "database", + "confidence": 0.95, + "reasoning": "该文件位于recorder模块的src目录下,文件名为operator.rs,主要职责是操作数据库。代码中使用了sea_orm进行数据库连接、表创建、数据查询等操作,且包含ArticleRecord实体的操作逻辑。其核心功能围绕数据库的初始化、表的创建和数据访问展开,因此属于数据库组件。" + }, + "timestamp": 1758800805, + "prompt_hash": "35179b3e23902ccd7f8d54200802ee54", + "token_usage": { + "input_tokens": 460, + "output_tokens": 166, + "total_tokens": 626 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/3a6bec24c23c07d8c04bbd99c42b99df.json b/.litho/cache/ai_code_purpose/3a6bec24c23c07d8c04bbd99c42b99df.json new file mode 100644 index 0000000..ac8e90c --- /dev/null +++ b/.litho/cache/ai_code_purpose/3a6bec24c23c07d8c04bbd99c42b99df.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.9, + "reasoning": "该文件定义了一个结构体 `HybridRuntimeState`,其中包含一个字段 `features_api`,类型为 `FeaturesAPIImpl`。从内容上看,它主要用于组织和管理运行时状态数据,符合数据模型的特征。文件路径中的 `state.rs` 也暗示了其作为状态模型的角色。因此,判断其主要用途是作为数据类型或模型。" + }, + "timestamp": 1758800922, + "prompt_hash": "3a6bec24c23c07d8c04bbd99c42b99df", + "token_usage": { + "input_tokens": 244, + "output_tokens": 171, + "total_tokens": 415 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/3d9fd2b019fc832a84e546524d91dfff.json b/.litho/cache/ai_code_purpose/3d9fd2b019fc832a84e546524d91dfff.json new file mode 100644 index 0000000..e435e91 --- /dev/null +++ b/.litho/cache/ai_code_purpose/3d9fd2b019fc832a84e546524d91dfff.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.9, + "reasoning": "该文件位于 `crates/scrap/src/lib.rs`,是一个 Rust 项目的库入口文件。文件通过 `mod` 和 `pub mod` 导出多个模块(如 rss、search、simulator 等),表明其职责是组织和封装与网页抓取(scrap)相关的特定功能模块。文件本身不包含具体实现,而是作为功能模块的聚合点,因此归类为实现特定逻辑功能的组件。" + }, + "timestamp": 1758800906, + "prompt_hash": "3d9fd2b019fc832a84e546524d91dfff", + "token_usage": { + "input_tokens": 230, + "output_tokens": 178, + "total_tokens": 408 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/49240ec2be1c3ffee157e6a72f441c5c.json b/.litho/cache/ai_code_purpose/49240ec2be1c3ffee157e6a72f441c5c.json new file mode 100644 index 0000000..429bfe8 --- /dev/null +++ b/.litho/cache/ai_code_purpose/49240ec2be1c3ffee157e6a72f441c5c.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`article_processor/optimizer.rs`,属于文章处理流程中的优化模块。它实现了`IPresetArticleLLMProcessor` trait,用于构建基于LLM的文章优化处理器,包含系统提示和用户提示模板的引入,并设置了特定的AI生成参数(如temperature=0.1),表明其职责是实现文章内容的智能优化逻辑。因此,属于实现特定业务逻辑的功能组件。" + }, + "timestamp": 1758800900, + "prompt_hash": "49240ec2be1c3ffee157e6a72f441c5c", + "token_usage": { + "input_tokens": 398, + "output_tokens": 193, + "total_tokens": 591 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/49ec0252c0f95e6952dcf2cba0e1a4d0.json b/.litho/cache/ai_code_purpose/49ec0252c0f95e6952dcf2cba0e1a4d0.json new file mode 100644 index 0000000..c19cebf --- /dev/null +++ b/.litho/cache/ai_code_purpose/49ec0252c0f95e6952dcf2cba0e1a4d0.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件位于 `src/daemon/locks.rs`,文件名包含 'locks',表明其与锁机制相关。内容中定义了一个常量 `LOCK_FEEDS_SCHEDULE_UPDATE` 和一个函数 `get_lock_path`,用于生成锁文件的路径。该功能属于辅助性工具逻辑,主要用于管理守护进程中的文件锁路径,不涉及核心业务逻辑或接口定义,因此归类为工具类代码(util)。" + }, + "timestamp": 1758800951, + "prompt_hash": "49ec0252c0f95e6952dcf2cba0e1a4d0", + "token_usage": { + "input_tokens": 272, + "output_tokens": 183, + "total_tokens": 455 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/4bda361559de7be9c9b7ab8807319ccb.json b/.litho/cache/ai_code_purpose/4bda361559de7be9c9b7ab8807319ccb.json new file mode 100644 index 0000000..bc519dc --- /dev/null +++ b/.litho/cache/ai_code_purpose/4bda361559de7be9c9b7ab8807319ccb.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件位于 `src-tauri/capabilities/` 目录下,文件名为 `default.json`,内容是一个 JSON 格式的配置文件,定义了应用的 capability(能力)策略,包括窗口权限和各种系统功能权限(如窗口管理、剪贴板、自动启动等)。此类文件在 Tauri 框架中用于声明应用的安全能力和运行时权限,属于典型的配置文件。因此,其组件类型为 'config'。" + }, + "timestamp": 1758800930, + "prompt_hash": "4bda361559de7be9c9b7ab8807319ccb", + "token_usage": { + "input_tokens": 462, + "output_tokens": 193, + "total_tokens": 655 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/4c4d178b545c7872b02ce5f4f064c001.json b/.litho/cache/ai_code_purpose/4c4d178b545c7872b02ce5f4f064c001.json new file mode 100644 index 0000000..83fab72 --- /dev/null +++ b/.litho/cache/ai_code_purpose/4c4d178b545c7872b02ce5f4f064c001.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件位于`src/connector.rs`,文件名中的'connector'暗示其负责连接或网络请求相关功能。代码内容主要定义了一个`ClientOption`结构体和一个创建`ClientBuilder`的函数,使用了`reqwest`库来构建HTTP客户端,设置了各种请求头和超时选项。这些特征表明它是一个工具类组件,用于封装和配置HTTP客户端,供其他部分代码调用以执行网络请求。因此,将其归类为'util'(工具类的代码)是合理的。" + }, + "timestamp": 1758800802, + "prompt_hash": "4c4d178b545c7872b02ce5f4f064c001", + "token_usage": { + "input_tokens": 459, + "output_tokens": 231, + "total_tokens": 690 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/4ff01c896ec936f373a1fcd0ba1aeece.json b/.litho/cache/ai_code_purpose/4ff01c896ec936f373a1fcd0ba1aeece.json new file mode 100644 index 0000000..3b223e0 --- /dev/null +++ b/.litho/cache/ai_code_purpose/4ff01c896ec936f373a1fcd0ba1aeece.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "该文件位于`providers`目录下,文件名为`llm_platform.rs`,实现了`PlatformAgentService`结构体并为其定义了`new`方法和`CompletionService` trait的实现,表明其负责与LLM平台进行交互。代码中包含请求参数构造、HTTP客户端调用等逻辑,符合智能Agent的特征,即封装外部AI服务调用。因此判断为智能Agent组件。" + }, + "timestamp": 1758800681, + "prompt_hash": "4ff01c896ec936f373a1fcd0ba1aeece", + "token_usage": { + "input_tokens": 468, + "output_tokens": 171, + "total_tokens": 639 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5402b0393b2da56718bcb87175fd6b97.json b/.litho/cache/ai_code_purpose/5402b0393b2da56718bcb87175fd6b97.json new file mode 100644 index 0000000..37e5404 --- /dev/null +++ b/.litho/cache/ai_code_purpose/5402b0393b2da56718bcb87175fd6b97.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于 `crates/scrap/src/rss/` 目录下,文件名为 `mod.rs`,表明它是 RSS 模块的实现部分。代码中定义了一个 `RSSFetcher` 结构体并实现了 `IFetcher` trait,主要用于从 RSS 链接抓取内容并解析为 `Article` 对象列表。其核心功能是实现特定的数据抓取逻辑,属于具体业务功能的实现,因此归类为 'specificfeature'。" + }, + "timestamp": 1758800781, + "prompt_hash": "5402b0393b2da56718bcb87175fd6b97", + "token_usage": { + "input_tokens": 457, + "output_tokens": 180, + "total_tokens": 637 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5705e81e6a13d23bdf131d5208700925.json b/.litho/cache/ai_code_purpose/5705e81e6a13d23bdf131d5208700925.json new file mode 100644 index 0000000..3fe6c6b --- /dev/null +++ b/.litho/cache/ai_code_purpose/5705e81e6a13d23bdf131d5208700925.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "api", + "confidence": 0.9, + "reasoning": "该文件位于 `src/scrap_host.rs`,属于 Tauri 插件的一部分,主要功能是通过创建一个隐藏的 Webview 窗口从指定 URL 抓取文本内容。文件中定义了 `scrap_text_by_url` 异步函数,用于处理网页内容抓取逻辑,并与 Tauri 的运行时和 Webview 系统交互。虽然涉及 UI 组件(WebviewWindow),但其本质是封装了一个用于内容抓取的接口,供其他模块调用,因此更符合 'api' 类型而非 'page' 或 'widget'。此外,文件使用了 Tauri 和 Tokio 的异步运行时机制,表明其作为后端接口或插件 API 的角色。" + }, + "timestamp": 1758800818, + "prompt_hash": "5705e81e6a13d23bdf131d5208700925", + "token_usage": { + "input_tokens": 464, + "output_tokens": 268, + "total_tokens": 732 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5895e48f0a7812b87c864c6ebc37eb25.json b/.litho/cache/ai_code_purpose/5895e48f0a7812b87c864c6ebc37eb25.json new file mode 100644 index 0000000..60b0e98 --- /dev/null +++ b/.litho/cache/ai_code_purpose/5895e48f0a7812b87c864c6ebc37eb25.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件定义了一个名为IArticleProcessor的trait,用于处理文章的责任链模式。文件位于src/article_processor目录下,且文件名为types.rs,表明其与文章处理的核心逻辑相关。内容上主要是定义了处理文章的接口,属于实现特定业务逻辑的功能组件,因此归类为specificfeature。" + }, + "timestamp": 1758800889, + "prompt_hash": "5895e48f0a7812b87c864c6ebc37eb25", + "token_usage": { + "input_tokens": 405, + "output_tokens": 165, + "total_tokens": 570 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/58be7221e9b2f703305e937726df5ba5.json b/.litho/cache/ai_code_purpose/58be7221e9b2f703305e937726df5ba5.json new file mode 100644 index 0000000..0c2acad --- /dev/null +++ b/.litho/cache/ai_code_purpose/58be7221e9b2f703305e937726df5ba5.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件定义了一个名为ElementSelector的trait,并为scraper库中的ElementRef类型实现了扩展方法。这些方法提供了方便的选择器功能,如提取文本和属性值。文件位于src/search目录下,表明它与搜索或数据提取相关。代码主要是对现有类型的扩展,提供实用功能,因此归类为工具类代码(util)。" + }, + "timestamp": 1758800795, + "prompt_hash": "58be7221e9b2f703305e937726df5ba5", + "token_usage": { + "input_tokens": 466, + "output_tokens": 177, + "total_tokens": 643 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5a477c1cc59409b5c794f317aa69b2fe.json b/.litho/cache/ai_code_purpose/5a477c1cc59409b5c794f317aa69b2fe.json new file mode 100644 index 0000000..368a1e6 --- /dev/null +++ b/.litho/cache/ai_code_purpose/5a477c1cc59409b5c794f317aa69b2fe.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件位于`crates/types/src/lib.rs`路径下,文件名是`lib.rs`,符合Rust中定义共享类型库的常见模式。文件内容主要包含多个使用`#[derive(Serialize, Deserialize, Clone)]`的结构体(如Article、LLMInstructOption、AppConfigLogSection),这些结构体用于数据建模和序列化,属于典型的数据模型定义。此外,该模块导出了`llm_endpoint`等子模块,也表明其作为类型集合的作用。无业务逻辑或控制流代码,因此最可能的用途是定义数据模型(model)。" + }, + "timestamp": 1758800678, + "prompt_hash": "5a477c1cc59409b5c794f317aa69b2fe", + "token_usage": { + "input_tokens": 530, + "output_tokens": 236, + "total_tokens": 766 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5a8658c4d3d8b64a36641a8ff25719e2.json b/.litho/cache/ai_code_purpose/5a8658c4d3d8b64a36641a8ff25719e2.json new file mode 100644 index 0000000..e57bb72 --- /dev/null +++ b/.litho/cache/ai_code_purpose/5a8658c4d3d8b64a36641a8ff25719e2.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.85, + "reasoning": "文件位于src目录下的monitor.rs,文件名暗示其功能与监控相关。代码内容显示其调用sentry初始化,用于错误跟踪和监控,属于实现特定功能逻辑的组件。无UI、路由或模型定义,排除页面、控制器或模型等类型。因此归类为特定功能实现组件。" + }, + "timestamp": 1758800945, + "prompt_hash": "5a8658c4d3d8b64a36641a8ff25719e2", + "token_usage": { + "input_tokens": 277, + "output_tokens": 158, + "total_tokens": 435 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5e099f29fa916518c41c52c5baae8821.json b/.litho/cache/ai_code_purpose/5e099f29fa916518c41c52c5baae8821.json new file mode 100644 index 0000000..42ce99c --- /dev/null +++ b/.litho/cache/ai_code_purpose/5e099f29fa916518c41c52c5baae8821.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "other", + "confidence": 0.7, + "reasoning": "该文件位于 `src/daemon` 目录下,文件名为 `mod.rs`,是 Rust 模块的典型组织方式。其内容仅包含对其他模块(如 args、feeds_update、launcher、locks)的声明,未包含具体实现逻辑。这表明它是一个模块容器或入口,用于组织守护进程(daemon)相关的子模块。由于不直接对应常见类别如 controller、util 或 model,归类为 'other' 更为合适,但具有中等置信度。" + }, + "timestamp": 1758800955, + "prompt_hash": "5e099f29fa916518c41c52c5baae8821", + "token_usage": { + "input_tokens": 232, + "output_tokens": 196, + "total_tokens": 428 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/5f7e3b5c901a987186729247cac909e4.json b/.litho/cache/ai_code_purpose/5f7e3b5c901a987186729247cac909e4.json new file mode 100644 index 0000000..9cbf8fa --- /dev/null +++ b/.litho/cache/ai_code_purpose/5f7e3b5c901a987186729247cac909e4.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "该文件名为llm_agent.rs,位于llm模块下,定义了一个CompletionAgent结构体,用于代理LLM生成服务。其内部通过枚举封装了多种LLM提供商的实现(如Ollama、Mistral、GLM等),并通过new方法根据配置创建实例,具有典型的智能Agent特征:抽象多个服务提供者并统一调用接口。因此判断为智能Agent组件。" + }, + "timestamp": 1758800696, + "prompt_hash": "5f7e3b5c901a987186729247cac909e4", + "token_usage": { + "input_tokens": 491, + "output_tokens": 174, + "total_tokens": 665 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/632dd5134101a9ed5bb92ec9f1031e44.json b/.litho/cache/ai_code_purpose/632dd5134101a9ed5bb92ec9f1031e44.json new file mode 100644 index 0000000..4da9bd1 --- /dev/null +++ b/.litho/cache/ai_code_purpose/632dd5134101a9ed5bb92ec9f1031e44.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`article_processor`模块目录下,文件名为`mod.rs`,这是Rust语言中常见的模块组织方式。文件内容仅包含多个子模块的声明(如`llm_processor`、`types`、`optimizer`等),表明它是一个功能聚合模块,用于组织与文章处理相关的特定功能组件。这些子模块名称暗示了其职责集中在文章的处理、优化和转换上,属于实现特定业务逻辑的功能模块,因此归类为`specificfeature`。" + }, + "timestamp": 1758800892, + "prompt_hash": "632dd5134101a9ed5bb92ec9f1031e44", + "token_usage": { + "input_tokens": 238, + "output_tokens": 224, + "total_tokens": 462 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/64d5fa70b3b666913c583675e596ecb1.json b/.litho/cache/ai_code_purpose/64d5fa70b3b666913c583675e596ecb1.json new file mode 100644 index 0000000..95c9eb1 --- /dev/null +++ b/.litho/cache/ai_code_purpose/64d5fa70b3b666913c583675e596ecb1.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "widget", + "confidence": 0.85, + "reasoning": "该文件位于src-tauri目录下,文件名为tray.rs,主要功能是创建系统托盘图标和菜单。代码使用了Tauri框架的tray和menu模块,构建了包含多个菜单项的托盘图标,这些菜单项用于控制主窗口显示、显示网络信息、关于窗口和退出程序等操作。这种负责UI交互组件的功能符合前端UI组件(widget)的特征,尽管是在Tauri后端代码中实现,但其本质是用户界面的交互元素。" + }, + "timestamp": 1758800837, + "prompt_hash": "64d5fa70b3b666913c583675e596ecb1", + "token_usage": { + "input_tokens": 476, + "output_tokens": 226, + "total_tokens": 702 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/66e16f2552351b6d3866d42b3e20934d.json b/.litho/cache/ai_code_purpose/66e16f2552351b6d3866d42b3e20934d.json new file mode 100644 index 0000000..8eec648 --- /dev/null +++ b/.litho/cache/ai_code_purpose/66e16f2552351b6d3866d42b3e20934d.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "该文件位于`daemon`目录下,文件名为`feeds_update.rs`,且代码中实现了`launch_feeds_schedule_update`函数,用于启动一个定时更新任务。它使用了锁机制防止重复运行,并通过异步运行时执行`schedule_loop`循环,表明这是一个后台常驻的智能Agent,负责定期更新feeds数据。结合路径、命名和逻辑特征,判断为智能Agent组件。" + }, + "timestamp": 1758800843, + "prompt_hash": "66e16f2552351b6d3866d42b3e20934d", + "token_usage": { + "input_tokens": 475, + "output_tokens": 184, + "total_tokens": 659 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/6d47234a8b70bbb1f4119477aaf511a2.json b/.litho/cache/ai_code_purpose/6d47234a8b70bbb1f4119477aaf511a2.json new file mode 100644 index 0000000..b687500 --- /dev/null +++ b/.litho/cache/ai_code_purpose/6d47234a8b70bbb1f4119477aaf511a2.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件位于src/daemon目录下,文件名为args.rs,内容是一个常量字符串定义DAEMON_FEEDS_SCHEDULE_UPDATE,看起来是用于命令行参数或配置项。这种常量定义通常用于配置或参数传递,结合其路径和简单的内容结构,判断为配置类组件。" + }, + "timestamp": 1758800957, + "prompt_hash": "6d47234a8b70bbb1f4119477aaf511a2", + "token_usage": { + "input_tokens": 227, + "output_tokens": 143, + "total_tokens": 370 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/7605cd98b380f133edcc17fc3b294e7a.json b/.litho/cache/ai_code_purpose/7605cd98b380f133edcc17fc3b294e7a.json new file mode 100644 index 0000000..44b2fbd --- /dev/null +++ b/.litho/cache/ai_code_purpose/7605cd98b380f133edcc17fc3b294e7a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件定义了一个枚举类型 LoadingStatus,包含 Loading、Completed 和 Error 三种状态,用于表示加载状态。文件路径位于 `/types/` 目录下,且文件名为 `loading.ts`,表明其用途是定义类型。内容上仅导出一个枚举,无任何业务逻辑或函数实现,符合数据模型或类型定义的特征。因此,该文件的组件类型为 'model'。" + }, + "timestamp": 1758800966, + "prompt_hash": "7605cd98b380f133edcc17fc3b294e7a", + "token_usage": { + "input_tokens": 228, + "output_tokens": 182, + "total_tokens": 410 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/78cac1c6ec5031395ca95490235a3444.json b/.litho/cache/ai_code_purpose/78cac1c6ec5031395ca95490235a3444.json new file mode 100644 index 0000000..a7aebd9 --- /dev/null +++ b/.litho/cache/ai_code_purpose/78cac1c6ec5031395ca95490235a3444.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件包含多个常量定义,主要用于存储窗口标签、URL和标题等配置信息。文件名'constrant.rs'(尽管拼写可能有误,应为'constant')以及其内容均为不可变的常量值,符合配置文件的特征。这些常量被用于应用程序的不同窗口设置,属于典型的配置用途。" + }, + "timestamp": 1758800942, + "prompt_hash": "78cac1c6ec5031395ca95490235a3444", + "token_usage": { + "input_tokens": 349, + "output_tokens": 162, + "total_tokens": 511 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/98902b51cbe78a05b212a687edb32e22.json b/.litho/cache/ai_code_purpose/98902b51cbe78a05b212a687edb32e22.json new file mode 100644 index 0000000..7bd6943 --- /dev/null +++ b/.litho/cache/ai_code_purpose/98902b51cbe78a05b212a687edb32e22.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "api", + "confidence": 0.9, + "reasoning": "文件位于 `crates/feed_api_rs/src/features/` 目录下,且名为 `mod.rs`,这是 Rust 项目中常见的模块组织方式。文件内容仅包含两个模块的公开导入:`api` 和 `impl_default`,表明该文件主要用于组织和导出与 API 功能相关的子模块,因此其主要用途是作为 API 模块的聚合点。" + }, + "timestamp": 1758800875, + "prompt_hash": "98902b51cbe78a05b212a687edb32e22", + "token_usage": { + "input_tokens": 218, + "output_tokens": 156, + "total_tokens": 374 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/9a211bd03c2447463cfa968edc582890.json b/.litho/cache/ai_code_purpose/9a211bd03c2447463cfa968edc582890.json new file mode 100644 index 0000000..fd5605c --- /dev/null +++ b/.litho/cache/ai_code_purpose/9a211bd03c2447463cfa968edc582890.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "controller", + "confidence": 0.85, + "reasoning": "该文件位于 `windows` 目录下,文件名为 `lite-edit.ts`,结合内容中定义了多个用于打开窗口并处理反馈数据的函数(如 `openFeedPackageCreateWindow` 和 `openFeedPackageEditWindow`),这些函数封装了窗口打开逻辑并与前端页面通信,具有明显的控制层特征。虽然涉及 UI 窗口操作,但不直接渲染界面,而是协调数据流动和窗口行为,因此更符合后端接口或 Controller 的角色,而非纯页面或组件。" + }, + "timestamp": 1758800854, + "prompt_hash": "9a211bd03c2447463cfa968edc582890", + "token_usage": { + "input_tokens": 473, + "output_tokens": 226, + "total_tokens": 699 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/9a37a53461e999713d57dd6ef8766e44.json b/.litho/cache/ai_code_purpose/9a37a53461e999713d57dd6ef8766e44.json new file mode 100644 index 0000000..f5403f8 --- /dev/null +++ b/.litho/cache/ai_code_purpose/9a37a53461e999713d57dd6ef8766e44.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "该文件位于`providers`目录下,文件名为`llm_mistral.rs`,实现了一个基于Mistral AI的Agent服务。代码中定义了`MistralQinoAgentService`结构体及其方法,用于构建与Mistral API交互的服务实例,并依赖于`OpenAILikeCompletionService`进行请求处理。结合路径、命名和逻辑功能,此组件属于智能Agent类型,负责调用外部LLM模型完成任务。" + }, + "timestamp": 1758800693, + "prompt_hash": "9a37a53461e999713d57dd6ef8766e44", + "token_usage": { + "input_tokens": 462, + "output_tokens": 179, + "total_tokens": 641 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/9ba614ee49edd569bdf7c6dfbceeefe1.json b/.litho/cache/ai_code_purpose/9ba614ee49edd569bdf7c6dfbceeefe1.json new file mode 100644 index 0000000..106c61e --- /dev/null +++ b/.litho/cache/ai_code_purpose/9ba614ee49edd569bdf7c6dfbceeefe1.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.9, + "reasoning": "该文件位于`crates/ollama/src/lib.rs`,是一个Rust库模块,主要实现了与Ollama程序交互的功能,如安装、启动、获取版本信息等。文件中定义了枚举类型`ProgramStatus`和结构体`Information`用于状态管理,并通过`tokio::process::Command`调用外部命令与Ollama进行通信。其职责是封装对Ollama的特定功能操作,属于实现特定业务逻辑的功能模块,因此归类为'specificfeature'。" + }, + "timestamp": 1758800830, + "prompt_hash": "9ba614ee49edd569bdf7c6dfbceeefe1", + "token_usage": { + "input_tokens": 457, + "output_tokens": 205, + "total_tokens": 662 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/9e0bf564d0b1fc181ced505838d99b31.json b/.litho/cache/ai_code_purpose/9e0bf564d0b1fc181ced505838d99b31.json new file mode 100644 index 0000000..ea5aaf1 --- /dev/null +++ b/.litho/cache/ai_code_purpose/9e0bf564d0b1fc181ced505838d99b31.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "根据文件路径`crates/intelligent/src/article_processor/assistant.rs`和内容分析,该文件定义了一个名为`Assistant`的结构体,该结构体封装了一个`CompletionAgent`,用于处理与LLM(大语言模型)的交互。文件中包含`new`构造函数和`chat`异步方法,表明其职责是作为智能Agent处理聊天请求。此外,使用了系统提示(SYSTEM_PROMPT)和用户提示命令,进一步证实了这是一个智能Agent组件,专门用于文章处理场景下的对话交互。" + }, + "timestamp": 1758800769, + "prompt_hash": "9e0bf564d0b1fc181ced505838d99b31", + "token_usage": { + "input_tokens": 467, + "output_tokens": 233, + "total_tokens": 700 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/a10e75ecf5bfadbf456e8ec506e81331.json b/.litho/cache/ai_code_purpose/a10e75ecf5bfadbf456e8ec506e81331.json new file mode 100644 index 0000000..520322b --- /dev/null +++ b/.litho/cache/ai_code_purpose/a10e75ecf5bfadbf456e8ec506e81331.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件是一个Rust项目的Cargo.toml配置文件,位于Tauri项目结构中(src-tauri目录下)。其主要作用是定义项目的依赖、构建配置和元信息,不包含实际的业务逻辑或功能实现。文件内容以配置项为主,如package、dependencies、build-dependencies等,符合典型的项目配置文件特征。因此,该文件的组件类型为'config'。" + }, + "timestamp": 1758800924, + "prompt_hash": "a10e75ecf5bfadbf456e8ec506e81331", + "token_usage": { + "input_tokens": 476, + "output_tokens": 179, + "total_tokens": 655 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/a1ff22ac5975af17b39ade5399053f31.json b/.litho/cache/ai_code_purpose/a1ff22ac5975af17b39ade5399053f31.json new file mode 100644 index 0000000..86cef23 --- /dev/null +++ b/.litho/cache/ai_code_purpose/a1ff22ac5975af17b39ade5399053f31.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件位于src/startup目录下,文件名为types.rs,主要定义了枚举类型Status和结构体TaskDump。这些类型用于表示任务的状态和转储信息,属于数据模型的定义。文件中没有业务逻辑实现、接口定义或配置内容,纯粹是数据结构的声明,因此最符合'model'类型。" + }, + "timestamp": 1758800878, + "prompt_hash": "a1ff22ac5975af17b39ade5399053f31", + "token_usage": { + "input_tokens": 261, + "output_tokens": 160, + "total_tokens": 421 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/a32ef042760431c435329ff28c4bcd28.json b/.litho/cache/ai_code_purpose/a32ef042760431c435329ff28c4bcd28.json new file mode 100644 index 0000000..70c37bc --- /dev/null +++ b/.litho/cache/ai_code_purpose/a32ef042760431c435329ff28c4bcd28.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "api", + "confidence": 0.95, + "reasoning": "该文件位于`hybrid-apis/feed/`目录下,文件名为`impl.ts`,表明是某种API的实现。内容中定义了一个类`FeaturesAPIImpl`,实现了`FeaturesAPI`接口,其中每个方法都通过`call`函数调用底层Tauri原生接口,属于典型的前后端或跨层接口定义与实现。此类文件主要用于封装与底层通信的API,符合'api'类型特征。" + }, + "timestamp": 1758800847, + "prompt_hash": "a32ef042760431c435329ff28c4bcd28", + "token_usage": { + "input_tokens": 460, + "output_tokens": 176, + "total_tokens": 636 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/a3c2ccb43834dd7723e9c73445ce2083.json b/.litho/cache/ai_code_purpose/a3c2ccb43834dd7723e9c73445ce2083.json new file mode 100644 index 0000000..513a5a1 --- /dev/null +++ b/.litho/cache/ai_code_purpose/a3c2ccb43834dd7723e9c73445ce2083.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "router", + "confidence": 0.85, + "reasoning": "该文件位于`providers`目录下,文件名为`mod.rs`,是Rust项目中常见的模块组织方式。文件内容主要是对不同LLM提供者的模块进行组织和导出(如llm_mistral、llm_ollama等),起到了路由和聚合子模块的作用,符合模块路由器的特征。因此判断为'router'类型,置信度较高。" + }, + "timestamp": 1758800861, + "prompt_hash": "a3c2ccb43834dd7723e9c73445ce2083", + "token_usage": { + "input_tokens": 247, + "output_tokens": 160, + "total_tokens": 407 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/a7c1dba5939d94410984b9591372618f.json b/.litho/cache/ai_code_purpose/a7c1dba5939d94410984b9591372618f.json new file mode 100644 index 0000000..016f0b0 --- /dev/null +++ b/.litho/cache/ai_code_purpose/a7c1dba5939d94410984b9591372618f.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "agent", + "confidence": 0.95, + "reasoning": "该文件定义了一个基于LLM(大语言模型)的文章处理器`ArticleLLMProcessor`,其核心功能是通过`CompletionAgent`与生成式AI进行交互,处理文章内容。文件路径中的`llm_processor`和文件名`llm_processor.rs`均表明其职责与LLM处理相关。此外,该结构体实现了`IArticleProcessor` trait,用于异步处理文章,并结合`IPresetArticleLLMProcessor` trait创建预设处理器实例,具有典型的智能Agent特征:封装AI交互逻辑、接收指令、生成输出。因此,该组件属于智能Agent类型。" + }, + "timestamp": 1758800774, + "prompt_hash": "a7c1dba5939d94410984b9591372618f", + "token_usage": { + "input_tokens": 540, + "output_tokens": 247, + "total_tokens": 787 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/a983f3e4ffc8701b751af22384f85f8a.json b/.litho/cache/ai_code_purpose/a983f3e4ffc8701b751af22384f85f8a.json new file mode 100644 index 0000000..55bc952 --- /dev/null +++ b/.litho/cache/ai_code_purpose/a983f3e4ffc8701b751af22384f85f8a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于recorder模块的src目录下,文件名为article_recorder_service.rs,表明其职责与文章记录服务相关。代码中定义了ArticleRecorderService结构体及其方法,包含initialize、update_content等操作,主要处理文章内容的更新和记录管理,涉及数据库模型的操作(如Model转换为ActiveModel),并与Operator组件协作完成数据持久化。这些特征表明它实现了特定业务逻辑功能,属于具体功能实现类组件而非通用工具或配置。因此归类为specificfeature。" + }, + "timestamp": 1758800808, + "prompt_hash": "a983f3e4ffc8701b751af22384f85f8a", + "token_usage": { + "input_tokens": 468, + "output_tokens": 251, + "total_tokens": 719 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/abe106b9401c1f583351133273952e6c.json b/.litho/cache/ai_code_purpose/abe106b9401c1f583351133273952e6c.json new file mode 100644 index 0000000..4b57e34 --- /dev/null +++ b/.litho/cache/ai_code_purpose/abe106b9401c1f583351133273952e6c.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`startup`目录下,文件名为`init_llm.rs`,表明其职责是在系统启动时初始化LLM(大语言模型)相关组件。代码内容中定义了一个异步函数`call`,用于根据配置检查Ollama程序的安装和运行状态,并进行相应的处理(如启动Ollama服务)。它不属于通用工具、模型定义或路由等类别,而是实现特定启动逻辑的功能模块,因此归类为'specificfeature'。" + }, + "timestamp": 1758800706, + "prompt_hash": "abe106b9401c1f583351133273952e6c", + "token_usage": { + "input_tokens": 511, + "output_tokens": 214, + "total_tokens": 725 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/af61ea36d053150cda1923eb32e8accf.json b/.litho/cache/ai_code_purpose/af61ea36d053150cda1923eb32e8accf.json new file mode 100644 index 0000000..e7f6645 --- /dev/null +++ b/.litho/cache/ai_code_purpose/af61ea36d053150cda1923eb32e8accf.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于 `src/search/` 目录下,文件名为 `baidu.rs`,表明其职责与百度搜索功能相关。代码中定义了 `Provider` 结构体,包含用于解析百度搜索结果的各类选择器(如标题、链接、日期等),并使用了网络请求(reqwest)、HTML 解析(scraper)和日志记录等功能,体现出对特定搜索功能的实现。结合其依赖项和业务逻辑,此文件主要用于实现从百度抓取和解析搜索结果的具体功能,属于处理特定逻辑的功能模块。" + }, + "timestamp": 1758800792, + "prompt_hash": "af61ea36d053150cda1923eb32e8accf", + "token_usage": { + "input_tokens": 559, + "output_tokens": 249, + "total_tokens": 808 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/b2fd859f2a8bec1ef5b463e1f7a9b48b.json b/.litho/cache/ai_code_purpose/b2fd859f2a8bec1ef5b463e1f7a9b48b.json new file mode 100644 index 0000000..513ab60 --- /dev/null +++ b/.litho/cache/ai_code_purpose/b2fd859f2a8bec1ef5b463e1f7a9b48b.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.85, + "reasoning": "该文件定义了一个名为IProvider的trait以及使用了Article类型,这表明它主要负责定义数据结构和接口契约。文件位于search目录下的types.rs,通常这样的命名约定意味着它是用来定义类型的地方。此外,没有实现具体的业务逻辑,而是提供了异步方法签名,说明其作为模型或接口定义的角色。因此,判断此文件的主要目的是作为模型(model)。" + }, + "timestamp": 1758800910, + "prompt_hash": "b2fd859f2a8bec1ef5b463e1f7a9b48b", + "token_usage": { + "input_tokens": 276, + "output_tokens": 214, + "total_tokens": 490 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/b3364aedd016a4fff2a617096444d766.json b/.litho/cache/ai_code_purpose/b3364aedd016a4fff2a617096444d766.json new file mode 100644 index 0000000..d0e31bd --- /dev/null +++ b/.litho/cache/ai_code_purpose/b3364aedd016a4fff2a617096444d766.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "middleware", + "confidence": 0.95, + "reasoning": "该文件位于 `app/src/` 目录下,文件名为 `hooks.client.ts`,具有典型的 SvelteKit 客户端 hooks 特征。内容中调用了 `Sentry.init` 进行错误监控初始化,并通过 `handleErrorWithSentry` 导出错误处理函数,用于全局异常捕获和上报。这种在请求处理链中拦截并处理错误的机制,符合中间件(middleware)的定义。此外,Sentry 的集成通常属于应用级的横切关注点,进一步支持其作为中间件的角色。" + }, + "timestamp": 1758800961, + "prompt_hash": "b3364aedd016a4fff2a617096444d766", + "token_usage": { + "input_tokens": 411, + "output_tokens": 222, + "total_tokens": 633 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/b3d59ce958b066a149ec27eee1fda487.json b/.litho/cache/ai_code_purpose/b3d59ce958b066a149ec27eee1fda487.json new file mode 100644 index 0000000..9df891a --- /dev/null +++ b/.litho/cache/ai_code_purpose/b3d59ce958b066a149ec27eee1fda487.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.9, + "reasoning": "该文件定义了类型和 trait,特别是 `IFetcher` trait 和相关的类型导入(如 Article, LLMSection, FeedTargetDescription),表明其主要作用是定义数据结构和接口契约。文件路径中的 `types.rs` 也强烈暗示这是类型定义文件,符合 'model' 类别的特征。" + }, + "timestamp": 1758800903, + "prompt_hash": "b3d59ce958b066a149ec27eee1fda487", + "token_usage": { + "input_tokens": 294, + "output_tokens": 137, + "total_tokens": 431 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/c3b026c384fb05ff33443c38e9a98ea3.json b/.litho/cache/ai_code_purpose/c3b026c384fb05ff33443c38e9a98ea3.json new file mode 100644 index 0000000..364b3fd --- /dev/null +++ b/.litho/cache/ai_code_purpose/c3b026c384fb05ff33443c38e9a98ea3.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`features`目录下,文件名为`impl_default.rs`,表明其职责是实现某一组默认的功能特性。从导入的模块来看,涉及文章处理(article_processor)、爬取(scrap)、记录(recorder)、LLM处理等,属于具体的业务逻辑实现。同时,该文件很可能实现了某个trait的默认行为或作为核心功能链的一环,符合'specificfeature'即'用于处理实现特定逻辑功能'的定义。综合路径、命名和依赖关系,判断为特定功能实现组件。" + }, + "timestamp": 1758800699, + "prompt_hash": "c3b026c384fb05ff33443c38e9a98ea3", + "token_usage": { + "input_tokens": 465, + "output_tokens": 240, + "total_tokens": 705 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/c3b49164d58333890fe66d84766e71fa.json b/.litho/cache/ai_code_purpose/c3b49164d58333890fe66d84766e71fa.json new file mode 100644 index 0000000..095a379 --- /dev/null +++ b/.litho/cache/ai_code_purpose/c3b49164d58333890fe66d84766e71fa.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.85, + "reasoning": "该文件位于src/lib.rs,是Rust项目的库入口文件。文件内容显示它定义了一个模块article_processor,表明这个库可能专注于处理文章相关的功能。作为lib.rs,它通常用于组织和导出多个模块,实现特定的业务功能而非通用工具或配置。因此,判断为实现特定逻辑功能的组件。" + }, + "timestamp": 1758800881, + "prompt_hash": "c3b49164d58333890fe66d84766e71fa", + "token_usage": { + "input_tokens": 214, + "output_tokens": 174, + "total_tokens": 388 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/c3e0a4bb91564316a491223c00cb8584.json b/.litho/cache/ai_code_purpose/c3e0a4bb91564316a491223c00cb8584.json new file mode 100644 index 0000000..49a76c8 --- /dev/null +++ b/.litho/cache/ai_code_purpose/c3e0a4bb91564316a491223c00cb8584.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.9, + "reasoning": "该文件位于 `src/article_reader.rs`,文件名和路径表明其职责是读取文章内容。代码中定义了异步函数 `read` 和 `read_inner`,用于获取并处理网页 HTML 内容,结合了网络请求(reqwest)、HTML 解析(scraper)、日志记录(spdlog)以及与 LLM 组件的交互,属于实现特定业务逻辑的功能模块,即从指定 URL 读取文章并进行初步处理,因此归类为 'specificfeature'。" + }, + "timestamp": 1758800778, + "prompt_hash": "c3e0a4bb91564316a491223c00cb8584", + "token_usage": { + "input_tokens": 462, + "output_tokens": 198, + "total_tokens": 660 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/cbe52c9246be9f721ff1750f557e7a45.json b/.litho/cache/ai_code_purpose/cbe52c9246be9f721ff1750f557e7a45.json new file mode 100644 index 0000000..f0130db --- /dev/null +++ b/.litho/cache/ai_code_purpose/cbe52c9246be9f721ff1750f557e7a45.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "api", + "confidence": 0.95, + "reasoning": "该文件位于 `crates/tauri-plugin-feed-api/src/lib.rs`,路径中包含 'api',表明其与接口相关。文件内容中通过 `tauri::generate_handler!` 导出了大量命令函数(如 add_feed、get_app_config、update_feed_contents 等),这些是典型的 Tauri 插件 API 接口处理函数。同时,文件定义了插件初始化逻辑 `init` 并使用 `TauriPlugin`,说明它是为前端或其他后端模块提供功能调用的接口层。因此,该文件主要职责是暴露 API 接口,属于 'api' 类型。" + }, + "timestamp": 1758800823, + "prompt_hash": "cbe52c9246be9f721ff1750f557e7a45", + "token_usage": { + "input_tokens": 460, + "output_tokens": 223, + "total_tokens": 683 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/d091d7c7c7324cf800b5d4eecf908d2b.json b/.litho/cache/ai_code_purpose/d091d7c7c7324cf800b5d4eecf908d2b.json new file mode 100644 index 0000000..c4389fc --- /dev/null +++ b/.litho/cache/ai_code_purpose/d091d7c7c7324cf800b5d4eecf908d2b.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于 `src/search/bing.rs`,文件名和路径表明其与搜索引擎 'bing' 相关。代码中定义了一个 `Provider` 结构体并实现了搜索功能相关的逻辑,导入了网络请求(reqwest)、HTML 解析(scraper)、日志等模块,并使用了项目内部的搜索相关工具和类型。整体实现的是针对 Bing 搜索结果的抓取和处理功能,属于实现特定业务逻辑的功能模块,因此归类为 'specificfeature'。" + }, + "timestamp": 1758800784, + "prompt_hash": "d091d7c7c7324cf800b5d4eecf908d2b", + "token_usage": { + "input_tokens": 459, + "output_tokens": 217, + "total_tokens": 676 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/d3317fa8ea14c31e7e3e3b5156a01dc6.json b/.litho/cache/ai_code_purpose/d3317fa8ea14c31e7e3e3b5156a01dc6.json new file mode 100644 index 0000000..c0e6227 --- /dev/null +++ b/.litho/cache/ai_code_purpose/d3317fa8ea14c31e7e3e3b5156a01dc6.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`article_processor`目录下,名为`melt.rs`,实现了一个用于处理文章的LLM(大语言模型)处理器。它通过实现`IPresetArticleLLMProcessor` trait来创建一个具有特定系统提示和用户提示的`ArticleLLMProcessor`实例,主要用于执行特定的文本处理逻辑(如'melt'操作)。其核心职责是封装与LLM交互的特定业务逻辑,属于实现特定功能的组件,而非通用工具、模型定义或配置等。" + }, + "timestamp": 1758800897, + "prompt_hash": "d3317fa8ea14c31e7e3e3b5156a01dc6", + "token_usage": { + "input_tokens": 389, + "output_tokens": 220, + "total_tokens": 609 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/d71d85c9ab38bfc245e28e6360ab937a.json b/.litho/cache/ai_code_purpose/d71d85c9ab38bfc245e28e6360ab937a.json new file mode 100644 index 0000000..d6d7aae --- /dev/null +++ b/.litho/cache/ai_code_purpose/d71d85c9ab38bfc245e28e6360ab937a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件位于src/entity目录下,文件名为article_record.rs,且内容中定义了一个带有DeriveEntityModel属性的Model结构体,使用了sea_orm的数据库映射特性。这些特征表明这是一个数据模型定义文件,用于表示数据库中的文章记录实体,因此属于'model'类型。" + }, + "timestamp": 1758800913, + "prompt_hash": "d71d85c9ab38bfc245e28e6360ab937a", + "token_usage": { + "input_tokens": 460, + "output_tokens": 151, + "total_tokens": 611 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/d914663c2996e3aab2bb46cbbe2ec563.json b/.litho/cache/ai_code_purpose/d914663c2996e3aab2bb46cbbe2ec563.json new file mode 100644 index 0000000..8285b4c --- /dev/null +++ b/.litho/cache/ai_code_purpose/d914663c2996e3aab2bb46cbbe2ec563.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件是一个JSON格式的国际化语言配置文件,位于locales目录下,文件名为en.json,表示英文语言包。文件内容包含大量UI界面的文本标签和提示信息,用于多语言支持。这种结构和内容特征表明它是一个典型的配置文件,用于存储应用程序的国际化文本配置。" + }, + "timestamp": 1758800971, + "prompt_hash": "d914663c2996e3aab2bb46cbbe2ec563", + "token_usage": { + "input_tokens": 459, + "output_tokens": 170, + "total_tokens": 629 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/d9e7cb6fd9854789cb10cec0906fdc92.json b/.litho/cache/ai_code_purpose/d9e7cb6fd9854789cb10cec0906fdc92.json new file mode 100644 index 0000000..8631d91 --- /dev/null +++ b/.litho/cache/ai_code_purpose/d9e7cb6fd9854789cb10cec0906fdc92.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "middleware", + "confidence": 0.95, + "reasoning": "该文件位于 `hooks.server.ts`,属于 SvelteKit 框架的服务器端 hooks,用于处理请求生命周期中的逻辑。文件导出了 `handle` 和 `handleError`,这是典型的中间件入口点。代码中使用了 `sequence` 组合多个 handle 函数,并设置了 Sentry 错误监控和国际化语言解析,这些都是典型的中间件行为。因此,该文件的主要作用是作为请求处理链中的一环,符合 'middleware' 的定义。" + }, + "timestamp": 1758800974, + "prompt_hash": "d9e7cb6fd9854789cb10cec0906fdc92", + "token_usage": { + "input_tokens": 447, + "output_tokens": 212, + "total_tokens": 659 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/df3b261b0e3dc6a3edeacb261030b5fd.json b/.litho/cache/ai_code_purpose/df3b261b0e3dc6a3edeacb261030b5fd.json new file mode 100644 index 0000000..81df81f --- /dev/null +++ b/.litho/cache/ai_code_purpose/df3b261b0e3dc6a3edeacb261030b5fd.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.9, + "reasoning": "该文件位于`src/simulator.rs`,文件名和路径表明其功能与模拟或抓取操作相关。代码中定义了`scrap_text_by_url`异步函数,用于通过URL抓取文本内容,并使用Tauri框架创建Webview窗口进行页面加载和交互,属于实现特定业务逻辑的功能模块。导入的模块如tauri、tokio等也支持异步操作和GUI窗口管理,进一步表明这是实现具体功能的组件而非通用工具或配置。" + }, + "timestamp": 1758800799, + "prompt_hash": "df3b261b0e3dc6a3edeacb261030b5fd", + "token_usage": { + "input_tokens": 459, + "output_tokens": 220, + "total_tokens": 679 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/e4347ad25a998685f7704566b0f5575b.json b/.litho/cache/ai_code_purpose/e4347ad25a998685f7704566b0f5575b.json new file mode 100644 index 0000000..2363231 --- /dev/null +++ b/.litho/cache/ai_code_purpose/e4347ad25a998685f7704566b0f5575b.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件位于 `types.ts`,文件名表明其主要定义类型。内容中包含多个 type 定义,如 LLMSection、AppConfig、FeedTargetDescription 等,均为数据结构的类型声明,用于描述应用配置、文章模型、订阅源等数据形态。无函数实现或业务逻辑,符合 'model' 类型即数据模型或类型定义的特征。路径 `lib/hybrid-apis/feed/` 也暗示其为 API 层的数据结构定义。" + }, + "timestamp": 1758800851, + "prompt_hash": "e4347ad25a998685f7704566b0f5575b", + "token_usage": { + "input_tokens": 460, + "output_tokens": 194, + "total_tokens": 654 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/e4cdfef0c9056558802d1ee87b85163c.json b/.litho/cache/ai_code_purpose/e4cdfef0c9056558802d1ee87b85163c.json new file mode 100644 index 0000000..c9bd9c0 --- /dev/null +++ b/.litho/cache/ai_code_purpose/e4cdfef0c9056558802d1ee87b85163c.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于 `app/src-tauri/src/daemon/` 路径下,文件名为 `launcher.rs`,表明其职责与守护进程(daemon)的启动逻辑相关。代码中定义了 `launch` 和 `launch_ignore_error` 函数,用于通过文件锁机制控制守护进程的启动,避免重复运行。使用了 `fslock` 进行进程锁管理,并通过 `Command` 启动外部进程,体现了特定的业务逻辑——确保守护进程单实例运行。因此,此文件属于实现特定功能逻辑的组件,而非通用工具、模型或配置。" + }, + "timestamp": 1758800840, + "prompt_hash": "e4cdfef0c9056558802d1ee87b85163c", + "token_usage": { + "input_tokens": 461, + "output_tokens": 244, + "total_tokens": 705 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/e8053d69434776f5128217a6a96f3bc7.json b/.litho/cache/ai_code_purpose/e8053d69434776f5128217a6a96f3bc7.json new file mode 100644 index 0000000..cc8ba12 --- /dev/null +++ b/.litho/cache/ai_code_purpose/e8053d69434776f5128217a6a96f3bc7.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "specificfeature", + "confidence": 0.95, + "reasoning": "该文件位于`providers`目录下,文件名包含`openaibase_like`,表明其与LLM提供商相关。代码定义了请求和响应结构体(如RequestParameters、Message、Response等),并实现了OpenAILikeCompletionService,用于处理与OpenAI兼容的LLM服务的补全请求。这属于实现特定功能逻辑的组件,而非通用工具或模型定义,因此归类为特定功能实现(specificfeature)。" + }, + "timestamp": 1758800686, + "prompt_hash": "e8053d69434776f5128217a6a96f3bc7", + "token_usage": { + "input_tokens": 466, + "output_tokens": 187, + "total_tokens": 653 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/ef9beb60ca0c7e71b0c874fe000dfa8f.json b/.litho/cache/ai_code_purpose/ef9beb60ca0c7e71b0c874fe000dfa8f.json new file mode 100644 index 0000000..73d2a4a --- /dev/null +++ b/.litho/cache/ai_code_purpose/ef9beb60ca0c7e71b0c874fe000dfa8f.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件位于crates/llm/src目录下,文件名为connector.rs,主要功能是创建一个配置好的reqwest::Client实例。代码内容显示它封装了HTTP客户端的创建逻辑,设置了超时、GZIP和Deflate等选项,属于工具类的功能。此类功能通常被其他模块复用,符合'util'(工具类代码)的定义。" + }, + "timestamp": 1758800869, + "prompt_hash": "ef9beb60ca0c7e71b0c874fe000dfa8f", + "token_usage": { + "input_tokens": 272, + "output_tokens": 160, + "total_tokens": 432 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/f19e6f3ff8a57e87758c2762c2584aeb.json b/.litho/cache/ai_code_purpose/f19e6f3ff8a57e87758c2762c2584aeb.json new file mode 100644 index 0000000..e65a3a9 --- /dev/null +++ b/.litho/cache/ai_code_purpose/f19e6f3ff8a57e87758c2762c2584aeb.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "config", + "confidence": 0.95, + "reasoning": "该文件位于 `src-tauri/gen/schemas/` 路径下,文件名为 `capabilities.json`,内容是一个 JSON 格式的配置对象,定义了不同 capability 的权限和窗口访问控制。这种结构通常用于 Tauri 框架中声明应用的安全策略和权限配置,属于典型的配置文件。无任何函数、类或业务逻辑代码,符合 'config' 类型的特征。" + }, + "timestamp": 1758800938, + "prompt_hash": "f19e6f3ff8a57e87758c2762c2584aeb", + "token_usage": { + "input_tokens": 464, + "output_tokens": 177, + "total_tokens": 641 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/f3cdaa7099cf2f26f4176196cad175eb.json b/.litho/cache/ai_code_purpose/f3cdaa7099cf2f26f4176196cad175eb.json new file mode 100644 index 0000000..bb519c2 --- /dev/null +++ b/.litho/cache/ai_code_purpose/f3cdaa7099cf2f26f4176196cad175eb.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件位于src目录下,文件名为env.rs,主要功能是通过环境变量和命令行参数判断当前是否为守护进程模式。代码结构简单,只包含一个工具函数is_daemon,用于返回布尔值判断运行模式,不涉及UI、路由、模型定义或接口暴露,符合工具类代码特征。因此归类为'util'(工具类的代码)。" + }, + "timestamp": 1758800948, + "prompt_hash": "f3cdaa7099cf2f26f4176196cad175eb", + "token_usage": { + "input_tokens": 257, + "output_tokens": 180, + "total_tokens": 437 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/f5e2f65d5437fc2b003325d963984f47.json b/.litho/cache/ai_code_purpose/f5e2f65d5437fc2b003325d963984f47.json new file mode 100644 index 0000000..cc6741e --- /dev/null +++ b/.litho/cache/ai_code_purpose/f5e2f65d5437fc2b003325d963984f47.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.9, + "reasoning": "文件路径为 `crates/recorder/src/entity/`,其中 `entity` 通常表示数据实体或模型。文件名为 `mod.rs`,是 Rust 项目中常见的模块定义文件。内容仅包含对 `article_record` 模块的公开导入,表明该文件用于组织和导出与实体相关的模块,符合数据模型组织的典型模式。因此判断其用途为定义数据类型或模型。" + }, + "timestamp": 1758800916, + "prompt_hash": "f5e2f65d5437fc2b003325d963984f47", + "token_usage": { + "input_tokens": 214, + "output_tokens": 182, + "total_tokens": 396 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/f814d2cefa80e6fd9e53e11e7ff79670.json b/.litho/cache/ai_code_purpose/f814d2cefa80e6fd9e53e11e7ff79670.json new file mode 100644 index 0000000..3edfb3f --- /dev/null +++ b/.litho/cache/ai_code_purpose/f814d2cefa80e6fd9e53e11e7ff79670.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "model", + "confidence": 0.95, + "reasoning": "该文件定义了一个名为Article的接口,包含文章的各种属性,如id、title、发布时间等,并通过export type导出。文件位于types目录下,且文件名article.ts表明其为类型定义文件。此类文件通常用于定义数据结构或模型,供其他模块引用,因此属于模型(model)类别。" + }, + "timestamp": 1758800964, + "prompt_hash": "f814d2cefa80e6fd9e53e11e7ff79670", + "token_usage": { + "input_tokens": 284, + "output_tokens": 158, + "total_tokens": 442 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_code_purpose/fbd6308127aea68e1a7c15f2ef01ed7a.json b/.litho/cache/ai_code_purpose/fbd6308127aea68e1a7c15f2ef01ed7a.json new file mode 100644 index 0000000..d19dd8e --- /dev/null +++ b/.litho/cache/ai_code_purpose/fbd6308127aea68e1a7c15f2ef01ed7a.json @@ -0,0 +1,15 @@ +{ + "data": { + "code_purpose": "util", + "confidence": 0.95, + "reasoning": "该文件位于startup目录下,文件名为init_logger.rs,主要功能是初始化日志系统。代码内容显示它配置了日志记录器的格式、级别和输出类型,属于工具类的功能。虽然在启动目录中,但其具体职责是提供日志配置的通用功能,因此归类为工具类(util)而非启动入口(entry)。" + }, + "timestamp": 1758800710, + "prompt_hash": "fbd6308127aea68e1a7c15f2ef01ed7a", + "token_usage": { + "input_tokens": 464, + "output_tokens": 171, + "total_tokens": 635 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_relationships_insights/0b584104c12da43080b2423eac392021.json b/.litho/cache/ai_relationships_insights/0b584104c12da43080b2423eac392021.json new file mode 100644 index 0000000..2f36941 --- /dev/null +++ b/.litho/cache/ai_relationships_insights/0b584104c12da43080b2423eac392021.json @@ -0,0 +1,165 @@ +{ + "data": { + "core_dependencies": [ + { + "from": "UI Layer", + "to": "Store & State Management", + "dependency_type": "Import", + "importance": 5, + "description": "UI组件通过导入Svelte stores进行状态管理" + }, + { + "from": "UI Layer", + "to": "API & Service Layer", + "dependency_type": "FunctionCall", + "importance": 5, + "description": "UI通过hybrid-apis调用后端服务" + }, + { + "from": "Store & State Management", + "to": "API & Service Layer", + "dependency_type": "FunctionCall", + "importance": 5, + "description": "Stores调用API实现数据获取和同步" + }, + { + "from": "API & Service Layer", + "to": "Business Logic & Core Features", + "dependency_type": "FunctionCall", + "importance": 5, + "description": "API层调用核心业务逻辑处理请求" + }, + { + "from": "Business Logic & Core Features", + "to": "Data Access & Utilities", + "dependency_type": "Composition", + "importance": 5, + "description": "核心功能组合使用数据访问和工具类" + }, + { + "from": "Business Logic & Core Features", + "to": "External Integrations & Plugins", + "dependency_type": "Module", + "importance": 4, + "description": "核心逻辑依赖Tauri插件系统进行原生功能调用" + }, + { + "from": "UI Layer", + "to": "External Integrations & Plugins", + "dependency_type": "Import", + "importance": 3, + "description": "部分UI组件直接调用Tauri API实现桌面功能" + }, + { + "from": "Store & State Management", + "to": "Data Access & Utilities", + "dependency_type": "DataFlow", + "importance": 4, + "description": "状态存储与持久化数据之间的数据流" + } + ], + "architecture_layers": [ + { + "name": "UI Layer", + "components": [ + "+page.svelte", + "ArticlesList.svelte", + "AISpritePanel.svelte", + "FeedsList.svelte", + "ArticleReader.svelte", + "Footer.svelte", + "SearchBar.svelte", + "EmbedWebView.svelte", + "ContextMenuProvider.svelte", + "Markdown.svelte", + "ArticleRenderWidget.svelte", + "ReaderBlankIndicator.svelte", + "FeedsPanel.svelte", + "FeedEditPanel.svelte", + "FeedPackageEditPanel.svelte" + ], + "level": 1 + }, + { + "name": "Store & State Management", + "components": [ + "index.svelte.ts", + "reader.svelte.ts", + "sprite.svelte.ts", + "feeds.svelte.ts", + "tasks.svelte.ts", + "loading.svelte.ts", + "toast.ts", + "context.ts" + ], + "level": 2 + }, + { + "name": "API & Service Layer", + "components": [ + "impl.ts", + "api.ts", + "types.ts", + "index.ts", + "lite-edit.ts", + "tray.rs", + "commands.rs", + "feeds_update.rs" + ], + "level": 3 + }, + { + "name": "Business Logic & Core Features", + "components": [ + "impl_default.rs", + "llm_agent.rs", + "article_reader.rs", + "init_app_config.rs", + "init_user_profile.rs", + "init_llm.rs" + ], + "level": 4 + }, + { + "name": "Data Access & Utilities", + "components": [ + "operator.rs", + "article_recorder_service.rs", + "path.rs", + "connector.rs", + "utils.rs", + "selector_extensions.rs" + ], + "level": 5 + }, + { + "name": "External Integrations & Plugins", + "components": [ + "lib.rs", + "scrap_host.rs", + "main.rs", + "launcher.rs" + ], + "level": 6 + } + ], + "key_insights": [ + "项目采用分层架构,从前端UI到后端核心逻辑有清晰的层次划分", + "Svelte stores作为状态管理核心,在UI和业务逻辑之间起到桥梁作用", + "存在明显的前后端分离设计,通过hybrid-apis进行通信", + "Tauri框架被广泛用于桌面应用集成,提供原生功能支持", + "智能Agent(LLM)相关组件集中在crates/llm目录,形成独立的功能模块", + "数据持久化通过SeaORM实现,与业务逻辑保持良好解耦", + "国际化(svelte-i18n)和UI库(@skeletonlabs/skeleton-svelte)被多处UI组件依赖", + "建议进一步规范化API层与业务逻辑层的接口定义,增强可维护性" + ] + }, + "timestamp": 1759024752, + "prompt_hash": "0b584104c12da43080b2423eac392021", + "token_usage": { + "input_tokens": 14077, + "output_tokens": 1026, + "total_tokens": 15103 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/ai_relationships_insights/9f3352e1846cace30f6f23d4c5ec30fa.json b/.litho/cache/ai_relationships_insights/9f3352e1846cace30f6f23d4c5ec30fa.json new file mode 100644 index 0000000..b6f3d0e --- /dev/null +++ b/.litho/cache/ai_relationships_insights/9f3352e1846cace30f6f23d4c5ec30fa.json @@ -0,0 +1,134 @@ +{ + "data": { + "core_dependencies": [ + { + "from": "UI Layer", + "to": "Store & State Management", + "dependency_type": "Import", + "importance": 5, + "description": "UI components import stores for state management" + }, + { + "from": "Store & State Management", + "to": "API & Service Layer", + "dependency_type": "FunctionCall", + "importance": 5, + "description": "Stores call API implementations to fetch/update data" + }, + { + "from": "API & Service Layer", + "to": "Business Logic & Agents", + "dependency_type": "Composition", + "importance": 5, + "description": "API layer composes business logic agents as implementation" + }, + { + "from": "Business Logic & Agents", + "to": "Data Access & Utilities", + "dependency_type": "FunctionCall", + "importance": 4, + "description": "Agents call data access services and utilities" + }, + { + "from": "Business Logic & Agents", + "to": "External Integrations", + "dependency_type": "Module", + "importance": 5, + "description": "Business logic integrates with external crates for scraping, recording, AI processing" + }, + { + "from": "Data Access & Utilities", + "to": "Database", + "dependency_type": "DataFlow", + "importance": 4, + "description": "Data operators flow data to/from database entities" + } + ], + "architecture_layers": [ + { + "name": "UI Layer", + "components": [ + "+page.svelte", + "ArticlesList.svelte", + "AISpritePanel.svelte", + "FeedsList.svelte", + "ArticleReader.svelte", + "Footer.svelte", + "SearchBar.svelte", + "ReaderBlankIndicator.svelte" + ], + "level": 0 + }, + { + "name": "Store & State Management", + "components": [ + "index.svelte.ts", + "reader.svelte.ts", + "sprite.svelte.ts", + "feeds.svelte.ts", + "tasks.svelte.ts", + "loading.svelte.ts", + "toast.ts" + ], + "level": 1 + }, + { + "name": "API & Service Layer", + "components": [ + "impl.ts", + "api.ts", + "commands.rs", + "featuresApi" + ], + "level": 2 + }, + { + "name": "Business Logic & Agents", + "components": [ + "impl_default.rs", + "llm_agent.rs", + "assistant.rs", + "llm_processor.rs", + "article_reader.rs" + ], + "level": 3 + }, + { + "name": "Data Access & Utilities", + "components": [ + "operator.rs", + "article_recorder_service.rs", + "connector.rs", + "utils.rs", + "path.rs" + ], + "level": 4 + }, + { + "name": "External Integrations", + "components": [ + "crates/ollama", + "crates/scrap", + "crates/recorder", + "crates/intelligent" + ], + "level": 5 + } + ], + "key_insights": [ + "项目采用分层架构,从前端UI到后端业务逻辑清晰分离", + "存在强依赖链:UI -> Stores -> API -> Business Logic -> Data Access", + "智能Agent(LLM)集成在业务逻辑层,通过统一API暴露给前端", + "外部服务(scrap, recorder, ollama)通过Rust crates集成,提供稳定接口", + "建议进一步解耦UI与Store,考虑使用依赖注入模式" + ] + }, + "timestamp": 1758806061, + "prompt_hash": "9f3352e1846cace30f6f23d4c5ec30fa", + "token_usage": { + "input_tokens": 14040, + "output_tokens": 663, + "total_tokens": 14703 + }, + "model_name": null +} \ No newline at end of file diff --git a/.litho/cache/structure/81ce170d34aadf59b5341dea337be584.json b/.litho/cache/structure/81ce170d34aadf59b5341dea337be584.json new file mode 100644 index 0000000..6d844a1 --- /dev/null +++ b/.litho/cache/structure/81ce170d34aadf59b5341dea337be584.json @@ -0,0 +1,2682 @@ +{ + "data": { + "project_name": "saga-reader", + "root_path": ".", + "directories": [ + { + "path": "./crates/types/src", + "name": "src", + "file_count": 2, + "subdirectory_count": 0, + "total_size": 12335, + "importance_score": 0.4 + }, + { + "path": "./crates/types", + "name": "types", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 330, + "importance_score": 0.0 + }, + { + "path": "./crates/llm/src/providers", + "name": "providers", + "file_count": 7, + "subdirectory_count": 0, + "total_size": 8713, + "importance_score": 0.2 + }, + { + "path": "./crates/llm/src", + "name": "src", + "file_count": 3, + "subdirectory_count": 1, + "total_size": 3704, + "importance_score": 0.4 + }, + { + "path": "./crates/llm", + "name": "llm", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 557, + "importance_score": 0.0 + }, + { + "path": "./crates/feed_api_rs/src/features", + "name": "features", + "file_count": 3, + "subdirectory_count": 0, + "total_size": 25894, + "importance_score": 0.0 + }, + { + "path": "./crates/feed_api_rs/src/startup", + "name": "startup", + "file_count": 7, + "subdirectory_count": 0, + "total_size": 12867, + "importance_score": 0.2 + }, + { + "path": "./crates/feed_api_rs/src", + "name": "src", + "file_count": 3, + "subdirectory_count": 2, + "total_size": 1698, + "importance_score": 0.4 + }, + { + "path": "./crates/feed_api_rs", + "name": "feed_api_rs", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 795, + "importance_score": 0.0 + }, + { + "path": "./crates/intelligent/src/article_processor/prompts/depreciated", + "name": "depreciated", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 1734, + "importance_score": 0.0 + }, + { + "path": "./crates/intelligent/src/article_processor/prompts", + "name": "prompts", + "file_count": 11, + "subdirectory_count": 1, + "total_size": 12215, + "importance_score": 0.2 + }, + { + "path": "./crates/intelligent/src/article_processor", + "name": "article_processor", + "file_count": 7, + "subdirectory_count": 1, + "total_size": 6466, + "importance_score": 0.2 + }, + { + "path": "./crates/intelligent/src", + "name": "src", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 27, + "importance_score": 0.4 + }, + { + "path": "./crates/intelligent", + "name": "intelligent", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 582, + "importance_score": 0.0 + }, + { + "path": "./crates/scrap/src/rss", + "name": "rss", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 1922, + "importance_score": 0.0 + }, + { + "path": "./crates/scrap/src/search", + "name": "search", + "file_count": 6, + "subdirectory_count": 0, + "total_size": 17506, + "importance_score": 0.2 + }, + { + "path": "./crates/scrap/src", + "name": "src", + "file_count": 5, + "subdirectory_count": 2, + "total_size": 10293, + "importance_score": 0.4 + }, + { + "path": "./crates/scrap", + "name": "scrap", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 630, + "importance_score": 0.0 + }, + { + "path": "./crates/recorder/src/entity", + "name": "entity", + "file_count": 2, + "subdirectory_count": 0, + "total_size": 930, + "importance_score": 0.0 + }, + { + "path": "./crates/recorder/src", + "name": "src", + "file_count": 4, + "subdirectory_count": 1, + "total_size": 12772, + "importance_score": 0.4 + }, + { + "path": "./crates/recorder", + "name": "recorder", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 482, + "importance_score": 0.0 + }, + { + "path": "./crates/tauri-plugin-feed-api/permissions/schemas", + "name": "schemas", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 24397, + "importance_score": 0.0 + }, + { + "path": "./crates/tauri-plugin-feed-api/permissions/autogenerated/commands", + "name": "commands", + "file_count": 24, + "subdirectory_count": 0, + "total_size": 10596, + "importance_score": 0.2 + }, + { + "path": "./crates/tauri-plugin-feed-api/permissions/autogenerated", + "name": "autogenerated", + "file_count": 0, + "subdirectory_count": 1, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./crates/tauri-plugin-feed-api/permissions", + "name": "permissions", + "file_count": 1, + "subdirectory_count": 2, + "total_size": 782, + "importance_score": 0.0 + }, + { + "path": "./crates/tauri-plugin-feed-api/guest-js", + "name": "guest-js", + "file_count": 5, + "subdirectory_count": 0, + "total_size": 3947, + "importance_score": 0.0 + }, + { + "path": "./crates/tauri-plugin-feed-api/src", + "name": "src", + "file_count": 4, + "subdirectory_count": 0, + "total_size": 13818, + "importance_score": 0.4 + }, + { + "path": "./crates/tauri-plugin-feed-api", + "name": "tauri-plugin-feed-api", + "file_count": 6, + "subdirectory_count": 3, + "total_size": 16527, + "importance_score": 0.30000000000000004 + }, + { + "path": "./crates/ollama/src", + "name": "src", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 4209, + "importance_score": 0.4 + }, + { + "path": "./crates/ollama", + "name": "ollama", + "file_count": 1, + "subdirectory_count": 1, + "total_size": 495, + "importance_score": 0.0 + }, + { + "path": "./crates", + "name": "crates", + "file_count": 0, + "subdirectory_count": 8, + "total_size": 0, + "importance_score": 0.1 + }, + { + "path": "./app/static", + "name": "static", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/capabilities", + "name": "capabilities", + "file_count": 3, + "subdirectory_count": 0, + "total_size": 1560, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/gen/schemas", + "name": "schemas", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 1415, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/gen", + "name": "gen", + "file_count": 0, + "subdirectory_count": 1, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/ios", + "name": "ios", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/android/mipmap-mdpi", + "name": "mipmap-mdpi", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/android/mipmap-hdpi", + "name": "mipmap-hdpi", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/android/mipmap-xxxhdpi", + "name": "mipmap-xxxhdpi", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/android/mipmap-xxhdpi", + "name": "mipmap-xxhdpi", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/android/mipmap-xhdpi", + "name": "mipmap-xhdpi", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/icons/android", + "name": "android", + "file_count": 0, + "subdirectory_count": 5, + "total_size": 0, + "importance_score": 0.1 + }, + { + "path": "./app/src-tauri/icons", + "name": "icons", + "file_count": 0, + "subdirectory_count": 2, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/src/plugins", + "name": "plugins", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/src/daemon", + "name": "daemon", + "file_count": 5, + "subdirectory_count": 0, + "total_size": 4116, + "importance_score": 0.0 + }, + { + "path": "./app/src-tauri/src", + "name": "src", + "file_count": 6, + "subdirectory_count": 2, + "total_size": 7925, + "importance_score": 0.6000000000000001 + }, + { + "path": "./app/src-tauri", + "name": "src-tauri", + "file_count": 4, + "subdirectory_count": 4, + "total_size": 2918, + "importance_score": 0.1 + }, + { + "path": "./app/src/lib/types", + "name": "types", + "file_count": 2, + "subdirectory_count": 0, + "total_size": 382, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/hybrid-apis/feed", + "name": "feed", + "file_count": 3, + "subdirectory_count": 0, + "total_size": 7633, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/hybrid-apis/tauri-regular", + "name": "tauri-regular", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 360, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/hybrid-apis", + "name": "hybrid-apis", + "file_count": 0, + "subdirectory_count": 2, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/utils", + "name": "utils", + "file_count": 4, + "subdirectory_count": 0, + "total_size": 2145, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/windows", + "name": "windows", + "file_count": 4, + "subdirectory_count": 0, + "total_size": 4218, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/i18n/locales", + "name": "locales", + "file_count": 2, + "subdirectory_count": 0, + "total_size": 14916, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/i18n", + "name": "i18n", + "file_count": 2, + "subdirectory_count": 1, + "total_size": 594, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/themes", + "name": "themes", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 746, + "importance_score": 0.0 + }, + { + "path": "./app/src/lib/widgets", + "name": "widgets", + "file_count": 7, + "subdirectory_count": 0, + "total_size": 12005, + "importance_score": 0.2 + }, + { + "path": "./app/src/lib", + "name": "lib", + "file_count": 1, + "subdirectory_count": 7, + "total_size": 75, + "importance_score": 0.5 + }, + { + "path": "./app/src/routes/settings", + "name": "settings", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 22127, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/feedsPackage/create_or_edit", + "name": "create_or_edit", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 2731, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/feedsPackage", + "name": "feedsPackage", + "file_count": 0, + "subdirectory_count": 1, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/about", + "name": "about", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 1336, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/feeds/create_or_edit", + "name": "create_or_edit", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 4813, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/feeds", + "name": "feeds", + "file_count": 0, + "subdirectory_count": 1, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/main/stores/articles/search", + "name": "search", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 408, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/main/stores/articles/list", + "name": "list", + "file_count": 1, + "subdirectory_count": 0, + "total_size": 6966, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/main/stores/articles", + "name": "articles", + "file_count": 1, + "subdirectory_count": 2, + "total_size": 357, + "importance_score": 0.0 + }, + { + "path": "./app/src/routes/main/stores", + "name": "stores", + "file_count": 8, + "subdirectory_count": 1, + "total_size": 15061, + "importance_score": 0.2 + }, + { + "path": "./app/src/routes/main/widgets", + "name": "widgets", + "file_count": 11, + "subdirectory_count": 0, + "total_size": 27346, + "importance_score": 0.2 + }, + { + "path": "./app/src/routes/main", + "name": "main", + "file_count": 1, + "subdirectory_count": 2, + "total_size": 2771, + "importance_score": 0.3 + }, + { + "path": "./app/src/routes", + "name": "routes", + "file_count": 3, + "subdirectory_count": 5, + "total_size": 903, + "importance_score": 0.1 + }, + { + "path": "./app/src", + "name": "src", + "file_count": 5, + "subdirectory_count": 2, + "total_size": 2850, + "importance_score": 0.4 + }, + { + "path": "./app", + "name": "app", + "file_count": 6, + "subdirectory_count": 3, + "total_size": 5708, + "importance_score": 0.30000000000000004 + }, + { + "path": "./docs/assets", + "name": "assets", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./docs", + "name": "docs", + "file_count": 0, + "subdirectory_count": 1, + "total_size": 0, + "importance_score": 0.0 + }, + { + "path": "./packages", + "name": "packages", + "file_count": 0, + "subdirectory_count": 0, + "total_size": 0, + "importance_score": 0.0 + } + ], + "files": [ + { + "path": "Cargo.toml", + "name": "Cargo.toml", + "size": 1201, + "extension": "toml", + "is_core": false, + "importance_score": 0.30000000000000004, + "complexity_score": 0.0, + "last_modified": "1756044895" + }, + { + "path": "crates/types/Cargo.toml", + "name": "Cargo.toml", + "size": 330, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049931" + }, + { + "path": "crates/types/src/llm_endpoint.rs", + "name": "llm_endpoint.rs", + "size": 1597, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/types/src/lib.rs", + "name": "lib.rs", + "size": 10738, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756048292" + }, + { + "path": "crates/llm/Cargo.toml", + "name": "Cargo.toml", + "size": 557, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049963" + }, + { + "path": "crates/llm/src/providers/llm_platform.rs", + "name": "llm_platform.rs", + "size": 1129, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756046059" + }, + { + "path": "crates/llm/src/providers/types.rs", + "name": "types.rs", + "size": 771, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/llm/src/providers/llm_ollama.rs", + "name": "llm_ollama.rs", + "size": 1820, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/llm/src/providers/llm_openaibase_like.rs", + "name": "llm_openaibase_like.rs", + "size": 2214, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756046064" + }, + { + "path": "crates/llm/src/providers/mod.rs", + "name": "mod.rs", + "size": 158, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1748160186" + }, + { + "path": "crates/llm/src/providers/llm_glm.rs", + "name": "llm_glm.rs", + "size": 1114, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756046039" + }, + { + "path": "crates/llm/src/providers/llm_mistral.rs", + "name": "llm_mistral.rs", + "size": 1507, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756046045" + }, + { + "path": "crates/llm/src/lib.rs", + "name": "lib.rs", + "size": 53, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/llm/src/llm_agent.rs", + "name": "llm_agent.rs", + "size": 3395, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1748160186" + }, + { + "path": "crates/llm/src/connector.rs", + "name": "connector.rs", + "size": 256, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/Cargo.toml", + "name": "Cargo.toml", + "size": 795, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049949" + }, + { + "path": "crates/feed_api_rs/src/lib.rs", + "name": "lib.rs", + "size": 75, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1756044802" + }, + { + "path": "crates/feed_api_rs/src/application_context.rs", + "name": "application_context.rs", + "size": 758, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/features/impl_default.rs", + "name": "impl_default.rs", + "size": 21236, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756049381" + }, + { + "path": "crates/feed_api_rs/src/features/mod.rs", + "name": "mod.rs", + "size": 35, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/features/api.rs", + "name": "api.rs", + "size": 4623, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746611300" + }, + { + "path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "name": "init_user_profile.rs", + "size": 1762, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/startup/init_llm.rs", + "name": "init_llm.rs", + "size": 1558, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1747033140" + }, + { + "path": "crates/feed_api_rs/src/startup/types.rs", + "name": "types.rs", + "size": 205, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/startup/init_logger.rs", + "name": "init_logger.rs", + "size": 2795, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/startup/task.rs", + "name": "task.rs", + "size": 1785, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/startup/mod.rs", + "name": "mod.rs", + "size": 2259, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "name": "init_app_config.rs", + "size": 2503, + "extension": "rs", + "is_core": true, + "importance_score": 0.9000000000000001, + "complexity_score": 0.0, + "last_modified": "1756049376" + }, + { + "path": "crates/feed_api_rs/src/utils.rs", + "name": "utils.rs", + "size": 865, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1756048251" + }, + { + "path": "crates/intelligent/Cargo.toml", + "name": "Cargo.toml", + "size": 582, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049945" + }, + { + "path": "crates/intelligent/src/lib.rs", + "name": "lib.rs", + "size": 27, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/purge.rs", + "name": "purge.rs", + "size": 707, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/types.rs", + "name": "types.rs", + "size": 574, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "crates/intelligent/src/article_processor/assistant.rs", + "name": "assistant.rs", + "size": 1512, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/mod.rs", + "name": "mod.rs", + "size": 105, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/assistant_sys.prompt", + "name": "assistant_sys.prompt", + "size": 748, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/optimizer_suffix.prompt", + "name": "optimizer_suffix.prompt", + "size": 0, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/purge_suffix.prompt", + "name": "purge_suffix.prompt", + "size": 105, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/optimizer_sys.prompt", + "name": "optimizer_sys.prompt", + "size": 7011, + "extension": "prompt", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1749522898" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/melt_suffix.prompt", + "name": "melt_suffix.prompt", + "size": 668, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/melt_sys.prompt", + "name": "melt_sys.prompt", + "size": 1096, + "extension": "prompt", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/melt_prefix.prompt", + "name": "melt_prefix.prompt", + "size": 0, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/purge_prefix.prompt", + "name": "purge_prefix.prompt", + "size": 0, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/depreciated/optimizer_sys.to-markdown.prompt", + "name": "optimizer_sys.to-markdown.prompt", + "size": 1734, + "extension": "prompt", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1749378812" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/optimizer_prefix.prompt", + "name": "optimizer_prefix.prompt", + "size": 0, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/purge_sys.prompt", + "name": "purge_sys.prompt", + "size": 2503, + "extension": "prompt", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "crates/intelligent/src/article_processor/prompts/assistant_suffix.prompt", + "name": "assistant_suffix.prompt", + "size": 84, + "extension": "prompt", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/melt.rs", + "name": "melt.rs", + "size": 706, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/intelligent/src/article_processor/llm_processor.rs", + "name": "llm_processor.rs", + "size": 2130, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "crates/intelligent/src/article_processor/optimizer.rs", + "name": "optimizer.rs", + "size": 732, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/scrap/Cargo.toml", + "name": "Cargo.toml", + "size": 630, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049943" + }, + { + "path": "crates/scrap/src/types.rs", + "name": "types.rs", + "size": 348, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1756047734" + }, + { + "path": "crates/scrap/src/article_reader.rs", + "name": "article_reader.rs", + "size": 4784, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/scrap/src/lib.rs", + "name": "lib.rs", + "size": 98, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1747534282" + }, + { + "path": "crates/scrap/src/rss/mod.rs", + "name": "mod.rs", + "size": 1922, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1747534282" + }, + { + "path": "crates/scrap/src/search/bing.rs", + "name": "bing.rs", + "size": 4816, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746611300" + }, + { + "path": "crates/scrap/src/search/types.rs", + "name": "types.rs", + "size": 271, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746611300" + }, + { + "path": "crates/scrap/src/search/mod.rs", + "name": "mod.rs", + "size": 1418, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "crates/scrap/src/search/baidu.rs", + "name": "baidu.rs", + "size": 6964, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746611300" + }, + { + "path": "crates/scrap/src/search/selector_extensions.rs", + "name": "selector_extensions.rs", + "size": 2309, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/scrap/src/search/utils.rs", + "name": "utils.rs", + "size": 1728, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/scrap/src/simulator.rs", + "name": "simulator.rs", + "size": 3078, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1756046069" + }, + { + "path": "crates/scrap/src/connector.rs", + "name": "connector.rs", + "size": 1985, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/recorder/Cargo.toml", + "name": "Cargo.toml", + "size": 482, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049920" + }, + { + "path": "crates/recorder/src/operator.rs", + "name": "operator.rs", + "size": 5046, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/recorder/src/entity/article_record.rs", + "name": "article_record.rs", + "size": 906, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/recorder/src/entity/mod.rs", + "name": "mod.rs", + "size": 24, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/recorder/src/lib.rs", + "name": "lib.rs", + "size": 78, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/recorder/src/article_recorder_service.rs", + "name": "article_recorder_service.rs", + "size": 5978, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/recorder/src/path.rs", + "name": "path.rs", + "size": 1670, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/Cargo.toml", + "name": "Cargo.toml", + "size": 569, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049952" + }, + { + "path": "crates/tauri-plugin-feed-api/bun.lockb", + "name": "bun.lockb", + "size": 13593, + "extension": "lockb", + "is_core": false, + "importance_score": 0.2, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/build.rs", + "name": "build.rs", + "size": 763, + "extension": "rs", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/default.toml", + "name": "default.toml", + "size": 782, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/schemas/schema.json", + "name": "schema.json", + "size": 24397, + "extension": "json", + "is_core": false, + "importance_score": 0.30000000000000004, + "complexity_score": 0.0, + "last_modified": "1746611300" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/download_ollama.toml", + "name": "download_ollama.toml", + "size": 431, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/change_feed_data.toml", + "name": "change_feed_data.toml", + "size": 437, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/update_article_by_source.toml", + "name": "update_article_by_source.toml", + "size": 485, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/query_by_id.toml", + "name": "query_by_id.toml", + "size": 407, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/remove_feeds_package.toml", + "name": "remove_feeds_package.toml", + "size": 461, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/set_app_config.toml", + "name": "set_app_config.toml", + "size": 425, + "extension": "toml", + "is_core": false, + "importance_score": 0.2, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/get_feeds_by_package.toml", + "name": "get_feeds_by_package.toml", + "size": 461, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/search_contents_by_keyword.toml", + "name": "search_contents_by_keyword.toml", + "size": 497, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/chat_with_article_assistant.toml", + "name": "chat_with_article_assistant.toml", + "size": 503, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/set_favorite.toml", + "name": "set_favorite.toml", + "size": 413, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/get_ollama_status.toml", + "name": "get_ollama_status.toml", + "size": 443, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/read_feed_contents.toml", + "name": "read_feed_contents.toml", + "size": 449, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/add_feeds_package.toml", + "name": "add_feeds_package.toml", + "size": 443, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/rename_feeds_package.toml", + "name": "rename_feeds_package.toml", + "size": 461, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/add_feed.toml", + "name": "add_feed.toml", + "size": 389, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/scrap_text_by_url.toml", + "name": "scrap_text_by_url.toml", + "size": 443, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/open_article_external.toml", + "name": "open_article_external.toml", + "size": 467, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/rename_feed.toml", + "name": "rename_feed.toml", + "size": 407, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/remove_feed.toml", + "name": "remove_feed.toml", + "size": 407, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/get_app_config.toml", + "name": "get_app_config.toml", + "size": 425, + "extension": "toml", + "is_core": false, + "importance_score": 0.2, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/mark_as_read.toml", + "name": "mark_as_read.toml", + "size": 413, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/get_feeds_packages.toml", + "name": "get_feeds_packages.toml", + "size": 449, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/update_feed_contents.toml", + "name": "update_feed_contents.toml", + "size": 461, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/permissions/autogenerated/commands/launch_ollama.toml", + "name": "launch_ollama.toml", + "size": 419, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/rollup.config.js", + "name": "rollup.config.js", + "size": 678, + "extension": "js", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/package.json", + "name": "package.json", + "size": 616, + "extension": "json", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1750908903" + }, + { + "path": "crates/tauri-plugin-feed-api/guest-js/impl.ts", + "name": "impl.ts", + "size": 1911, + "extension": "ts", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/guest-js/api.ts", + "name": "api.ts", + "size": 1085, + "extension": "ts", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/guest-js/types.ts", + "name": "types.ts", + "size": 520, + "extension": "ts", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/guest-js/tauri-regular.ts", + "name": "tauri-regular.ts", + "size": 360, + "extension": "ts", + "is_core": false, + "importance_score": 0.3, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/guest-js/index.ts", + "name": "index.ts", + "size": 71, + "extension": "ts", + "is_core": false, + "importance_score": 0.5, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "crates/tauri-plugin-feed-api/tsconfig.json", + "name": "tsconfig.json", + "size": 308, + "extension": "json", + "is_core": false, + "importance_score": 0.2, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/src/scrap_host.rs", + "name": "scrap_host.rs", + "size": 1888, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539482" + }, + { + "path": "crates/tauri-plugin-feed-api/src/lib.rs", + "name": "lib.rs", + "size": 2727, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "crates/tauri-plugin-feed-api/src/commands.rs", + "name": "commands.rs", + "size": 9071, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746611300" + }, + { + "path": "crates/tauri-plugin-feed-api/src/state.rs", + "name": "state.rs", + "size": 132, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "crates/ollama/Cargo.toml", + "name": "Cargo.toml", + "size": 495, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756049939" + }, + { + "path": "crates/ollama/src/lib.rs", + "name": "lib.rs", + "size": 4209, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1747033486" + }, + { + "path": "app/svelte.config.js", + "name": "svelte.config.js", + "size": 457, + "extension": "js", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/tailwind.config.js", + "name": "tailwind.config.js", + "size": 275, + "extension": "js", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1747534282" + }, + { + "path": "app/package.json", + "name": "package.json", + "size": 2404, + "extension": "json", + "is_core": false, + "importance_score": 0.30000000000000004, + "complexity_score": 0.0, + "last_modified": "1756049886" + }, + { + "path": "app/src-tauri/Cargo.toml", + "name": "Cargo.toml", + "size": 1455, + "extension": "toml", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1756049908" + }, + { + "path": "app/src-tauri/tauri.conf.json", + "name": "tauri.conf.json", + "size": 1424, + "extension": "json", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1756049987" + }, + { + "path": "app/src-tauri/capabilities/scrap_host.json", + "name": "scrap_host.json", + "size": 304, + "extension": "json", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1746790923" + }, + { + "path": "app/src-tauri/capabilities/default.json", + "name": "default.json", + "size": 1070, + "extension": "json", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1747534282" + }, + { + "path": "app/src-tauri/capabilities/desktop.json", + "name": "desktop.json", + "size": 186, + "extension": "json", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/build.rs", + "name": "build.rs", + "size": 39, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/gen/schemas/capabilities.json", + "name": "capabilities.json", + "size": 1415, + "extension": "json", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1747533460" + }, + { + "path": "app/src-tauri/feeds_schedule_update.lock", + "name": "feeds_schedule_update.lock", + "size": 0, + "extension": "lock", + "is_core": false, + "importance_score": 0.35, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/constrant.rs", + "name": "constrant.rs", + "size": 530, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/monitor.rs", + "name": "monitor.rs", + "size": 277, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/env.rs", + "name": "env.rs", + "size": 203, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "app/src-tauri/src/lib.rs", + "name": "lib.rs", + "size": 2245, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1753080598" + }, + { + "path": "app/src-tauri/src/tray.rs", + "name": "tray.rs", + "size": 4457, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1751253184" + }, + { + "path": "app/src-tauri/src/daemon/locks.rs", + "name": "locks.rs", + "size": 254, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/daemon/mod.rs", + "name": "mod.rs", + "size": 97, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/daemon/launcher.rs", + "name": "launcher.rs", + "size": 1311, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/daemon/args.rs", + "name": "args.rs", + "size": 74, + "extension": "rs", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src-tauri/src/daemon/feeds_update.rs", + "name": "feeds_update.rs", + "size": 2380, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1753238070" + }, + { + "path": "app/src-tauri/src/main.rs", + "name": "main.rs", + "size": 213, + "extension": "rs", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "app/tsconfig.json", + "name": "tsconfig.json", + "size": 675, + "extension": "json", + "is_core": false, + "importance_score": 0.2, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/eslint.config.js", + "name": "eslint.config.js", + "size": 649, + "extension": "js", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/vite.config.ts", + "name": "vite.config.ts", + "size": 1248, + "extension": "ts", + "is_core": true, + "importance_score": 0.6000000000000001, + "complexity_score": 0.0, + "last_modified": "1749940617" + }, + { + "path": "app/src/app.d.ts", + "name": "app.d.ts", + "size": 269, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/app.css", + "name": "app.css", + "size": 336, + "extension": "css", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1747534282" + }, + { + "path": "app/src/hooks.client.ts", + "name": "hooks.client.ts", + "size": 813, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1749471456" + }, + { + "path": "app/src/lib/types/article.ts", + "name": "article.ts", + "size": 303, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/types/loading.ts", + "name": "loading.ts", + "size": 79, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/hybrid-apis/feed/impl.ts", + "name": "impl.ts", + "size": 4179, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/hybrid-apis/feed/api.ts", + "name": "api.ts", + "size": 1798, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/hybrid-apis/feed/types.ts", + "name": "types.ts", + "size": 1656, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "app/src/lib/hybrid-apis/tauri-regular/index.ts", + "name": "index.ts", + "size": 360, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/utils/dom.ts", + "name": "dom.ts", + "size": 935, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/utils/date.ts", + "name": "date.ts", + "size": 344, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/utils/text.ts", + "name": "text.ts", + "size": 781, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1749378735" + }, + { + "path": "app/src/lib/utils/id.ts", + "name": "id.ts", + "size": 85, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/index.ts", + "name": "index.ts", + "size": 75, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/windows/settings.ts", + "name": "settings.ts", + "size": 276, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1750239955" + }, + { + "path": "app/src/lib/windows/utils.ts", + "name": "utils.ts", + "size": 1234, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1747289383" + }, + { + "path": "app/src/lib/windows/index.ts", + "name": "index.ts", + "size": 77, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/windows/lite-edit.ts", + "name": "lite-edit.ts", + "size": 2631, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/i18n/locales/zh.json", + "name": "zh.json", + "size": 7233, + "extension": "json", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "app/src/lib/i18n/locales/en.json", + "name": "en.json", + "size": 7683, + "extension": "json", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1753755466" + }, + { + "path": "app/src/lib/i18n/settings.ts", + "name": "settings.ts", + "size": 280, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/i18n/index.ts", + "name": "index.ts", + "size": 314, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/themes/index.ts", + "name": "index.ts", + "size": 746, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1750995484" + }, + { + "path": "app/src/lib/widgets/SaveOperatePanel.svelte", + "name": "SaveOperatePanel.svelte", + "size": 612, + "extension": "svelte", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/widgets/EmbedWebView.svelte", + "name": "EmbedWebView.svelte", + "size": 1946, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1749474312" + }, + { + "path": "app/src/lib/widgets/ContextMenuProvider.svelte", + "name": "ContextMenuProvider.svelte", + "size": 3708, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/lib/widgets/types.ts", + "name": "types.ts", + "size": 343, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1749371475" + }, + { + "path": "app/src/lib/widgets/Markdown.svelte", + "name": "Markdown.svelte", + "size": 3522, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1749524268" + }, + { + "path": "app/src/lib/widgets/ArticleRenderWidget.svelte", + "name": "ArticleRenderWidget.svelte", + "size": 1460, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1749447306" + }, + { + "path": "app/src/lib/widgets/MarkdownImg.svelte", + "name": "MarkdownImg.svelte", + "size": 414, + "extension": "svelte", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/app.html", + "name": "app.html", + "size": 474, + "extension": "html", + "is_core": false, + "importance_score": 0.4, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/hooks.server.ts", + "name": "hooks.server.ts", + "size": 958, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1749471451" + }, + { + "path": "app/src/routes/+layout.ts", + "name": "+layout.ts", + "size": 359, + "extension": "ts", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/settings/+page.svelte", + "name": "+page.svelte", + "size": 22127, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1753755667" + }, + { + "path": "app/src/routes/+page.svelte", + "name": "+page.svelte", + "size": 0, + "extension": "svelte", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/feedsPackage/create_or_edit/+page.svelte", + "name": "+page.svelte", + "size": 2731, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/about/+page.svelte", + "name": "+page.svelte", + "size": 1336, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1747033140" + }, + { + "path": "app/src/routes/feeds/create_or_edit/+page.svelte", + "name": "+page.svelte", + "size": 4813, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/+page.svelte", + "name": "+page.svelte", + "size": 2771, + "extension": "svelte", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/stores/toast.ts", + "name": "toast.ts", + "size": 251, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746586818" + }, + { + "path": "app/src/routes/main/stores/articles/search/index.svelte.ts", + "name": "index.svelte.ts", + "size": 408, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/stores/articles/index.svelte.ts", + "name": "index.svelte.ts", + "size": 357, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/stores/articles/list/index.svelte.ts", + "name": "index.svelte.ts", + "size": 6966, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "app/src/routes/main/stores/reader.svelte.ts", + "name": "reader.svelte.ts", + "size": 1264, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746761762" + }, + { + "path": "app/src/routes/main/stores/context.ts", + "name": "context.ts", + "size": 171, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/stores/sprite.svelte.ts", + "name": "sprite.svelte.ts", + "size": 2057, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/stores/feeds.svelte.ts", + "name": "feeds.svelte.ts", + "size": 2523, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/stores/index.svelte.ts", + "name": "index.svelte.ts", + "size": 5512, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1749940929" + }, + { + "path": "app/src/routes/main/stores/tasks.svelte.ts", + "name": "tasks.svelte.ts", + "size": 2321, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1749298509" + }, + { + "path": "app/src/routes/main/stores/loading.svelte.ts", + "name": "loading.svelte.ts", + "size": 962, + "extension": "ts", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/ArticlesList.svelte", + "name": "ArticlesList.svelte", + "size": 4224, + "extension": "svelte", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/ReaderBlankIndicator.svelte", + "name": "ReaderBlankIndicator.svelte", + "size": 441, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746586818" + }, + { + "path": "app/src/routes/main/widgets/AISpritePanel.svelte", + "name": "AISpritePanel.svelte", + "size": 5396, + "extension": "svelte", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1751634265" + }, + { + "path": "app/src/routes/main/widgets/FeedsPanel.svelte", + "name": "FeedsPanel.svelte", + "size": 0, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/FeedEditPanel.svelte", + "name": "FeedEditPanel.svelte", + "size": 0, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/FeedsList.svelte", + "name": "FeedsList.svelte", + "size": 7437, + "extension": "svelte", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1749442319" + }, + { + "path": "app/src/routes/main/widgets/ArticleReader.svelte", + "name": "ArticleReader.svelte", + "size": 4792, + "extension": "svelte", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1749380511" + }, + { + "path": "app/src/routes/main/widgets/types.ts", + "name": "types.ts", + "size": 1697, + "extension": "ts", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/Footer.svelte", + "name": "Footer.svelte", + "size": 2487, + "extension": "svelte", + "is_core": true, + "importance_score": 1.0, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/SearchBar.svelte", + "name": "SearchBar.svelte", + "size": 872, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/main/widgets/FeedPackageEditPanel.svelte", + "name": "FeedPackageEditPanel.svelte", + "size": 0, + "extension": "svelte", + "is_core": true, + "importance_score": 0.8, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "app/src/routes/+layout.svelte", + "name": "+layout.svelte", + "size": 544, + "extension": "svelte", + "is_core": true, + "importance_score": 0.6, + "complexity_score": 0.0, + "last_modified": "1747534282" + }, + { + "path": "LICENSE", + "name": "LICENSE", + "size": 1133, + "extension": null, + "is_core": false, + "importance_score": 0.2, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "bunfig.toml", + "name": "bunfig.toml", + "size": 90, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + }, + { + "path": "package.json", + "name": "package.json", + "size": 596, + "extension": "json", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1756044075" + }, + { + "path": "clippy.toml", + "name": "clippy.toml", + "size": 1, + "extension": "toml", + "is_core": false, + "importance_score": 0.1, + "complexity_score": 0.0, + "last_modified": "1746539481" + } + ], + "total_files": 204, + "total_directories": 76, + "file_types": { + "lock": 1, + "prompt": 12, + "svelte": 23, + "css": 1, + "toml": 37, + "html": 1, + "json": 13, + "rs": 69, + "js": 4, + "lockb": 1, + "ts": 41 + }, + "size_distribution": { + "small": 77, + "tiny": 122, + "medium": 5 + } + }, + "timestamp": 1759026330, + "prompt_hash": "81ce170d34aadf59b5341dea337be584", + "token_usage": null, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/0b91e53dcc6abfb4676dd722cf7fd463.json" "b/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/0b91e53dcc6abfb4676dd722cf7fd463.json" new file mode 100644 index 0000000..6041295 --- /dev/null +++ "b/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/0b91e53dcc6abfb4676dd722cf7fd463.json" @@ -0,0 +1,34 @@ +{ + "data": { + "main_workflow": { + "name": "文章获取与智能处理流程", + "description": "系统启动后自动加载用户订阅源,通过RSS或搜索引擎抓取最新文章内容,利用大语言模型对原始内容进行净化、优化和熔炼等智能处理,并将结果持久化到本地数据库,最后在前端展示给用户。", + "flowchart_mermaid": "graph TD\n A[系统启动] --> B[初始化配置与日志]\n B --> C[加载用户订阅源]\n C --> D[并发抓取RSS/搜索结果]\n D --> E[提取网页正文内容]\n E --> F[LLM三阶段处理: 净化-优化-熔炼]\n F --> G[保存至本地SQLite数据库]\n G --> H[前端状态管理器加载数据]\n H --> I[渲染文章列表界面]" + }, + "other_important_workflows": [ + { + "name": "AI助手对话交互流程", + "description": "用户在AI精灵面板输入问题后,系统结合当前文章内容构造提示词,调用配置的LLM服务生成回复,并将流式响应实时显示在对话界面中。", + "flowchart_mermaid": "graph TD\n A[用户输入问题] --> B[触发AI精灵Store]\n B --> C[Tauri命令桥接至Rust后端]\n C --> D[构造包含上下文的Prompt]\n D --> E[LLM代理调用Ollama/Mistral/GLM等模型]\n E --> F[返回生成的回复文本]\n F --> G[Tauri事件回传前端]\n G --> H[流式渲染AI回复消息]" + }, + { + "name": "文章阅读与状态更新流程", + "description": "用户点击文章条目后,系统加载完整内容并支持多种阅读模式切换;当用户浏览时自动标记为已读,并同步更新数据库中的阅读状态。", + "flowchart_mermaid": "graph TD\n A[用户点击文章] --> B[文章阅读器组件激活]\n B --> C[调用Tauri API获取内容]\n C --> D[展示优化/熔炼/原文三种视图]\n D --> E[滚动过程中自动标记已读]\n E --> F[调用markAsRead接口]\n F --> G[更新数据库记录]\n G --> H[状态Store同步变更]" + }, + { + "name": "后台定时更新流程", + "description": "系统以守护进程方式运行定时任务,周期性检查所有订阅源的更新情况,自动抓取新内容并推送至用户界面。", + "flowchart_mermaid": "graph TD\n A[守护进程启动] --> B[设置定时器]\n B --> C[定期触发更新任务]\n C --> D[遍历所有订阅源]\n D --> E[抓取最新文章列表]\n E --> F[去重并过滤已存在内容]\n F --> G[执行智能内容处理流水线]\n G --> H[存储新文章到数据库]\n H --> I[通知前端刷新UI]" + } + ] + }, + "timestamp": 1758807710, + "prompt_hash": "0b91e53dcc6abfb4676dd722cf7fd463", + "token_usage": { + "input_tokens": 19863, + "output_tokens": 1011, + "total_tokens": 20874 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/96a241c8fb50490541b377f3d4da0e04.json" "b/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/96a241c8fb50490541b377f3d4da0e04.json" new file mode 100644 index 0000000..6e2e5bc --- /dev/null +++ "b/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/96a241c8fb50490541b377f3d4da0e04.json" @@ -0,0 +1,34 @@ +{ + "data": { + "main_workflow": { + "name": "文章智能处理与阅读流程", + "description": "用户选择一篇文章后,系统通过AI模型对内容进行净化、优化和融合处理,最终呈现高质量的可读内容。该流程是系统的核心价值所在,体现了信息聚合与智能增强的结合。", + "flowchart_mermaid": "graph TD\n A[用户点击文章] --> B{文章内容已处理?}\n B -- 否 --> C[启动LLM处理流水线]\n C --> D[Purge: 净化内容]\n D --> E[Optimize: 优化表达]\n E --> F[Melt: 融合洞察]\n F --> G[持久化处理结果]\n G --> H[渲染优化后内容]\n B -- 是 --> H\n H --> I[用户阅读增强内容]\n I --> J{用户提问?}\n J -- 是 --> K[调用AI助手对话]\n K --> L[显示AI回复]\n J -- 否 --> M[结束]" + }, + "other_important_workflows": [ + { + "name": "应用启动初始化流程", + "description": "系统启动时按阶段加载配置、初始化日志、恢复用户状态并准备AI运行环境,确保应用稳定进入就绪状态。", + "flowchart_mermaid": "graph TD\n A[启动应用] --> B[初始化核心配置]\n B --> C[加载或创建默认app_config.toml]\n C --> D[初始化日志系统]\n D --> E[并行初始化用户配置与LLM服务]\n E --> F[读取user_config.toml]\n E --> G[检查Ollama服务状态]\n F --> H[构建主状态Store]\n G --> H\n H --> I[渲染主界面]\n I --> J[进入待命状态]" + }, + { + "name": "订阅源内容更新流程", + "description": "系统定期或手动触发对所有RSS订阅源的内容抓取,并通过智能处理器生成结构化文章记录。", + "flowchart_mermaid": "graph TD\n A[触发更新] --> B[遍历所有FeedsPackage]\n B --> C{获取源类型}\n C -->|RSS| D[RSS模块解析XML]\n C -->|Search| E[搜索引擎爬虫抓取]\n D --> F[提取标题/链接/摘要]\n E --> F\n F --> G[调用ArticleReader获取正文]\n G --> H[启动Purge-Optimize-Melt处理链]\n H --> I[存入数据库]\n I --> J[更新UI文章列表]" + }, + { + "name": "AI助手交互流程", + "description": "用户在阅读过程中向AI精灵提问,系统将问题连同上下文发送至LLM代理,返回结构化回答并展示。", + "flowchart_mermaid": "graph TD\n A[打开AI精灵面板] --> B[输入问题]\n B --> C[构造包含文章上下文的Prompt]\n C --> D[调用LLM代理服务]\n D --> E{选择提供商}\n E -->|Ollama| F[本地模型响应]\n E -->|OpenAI/GLM/Mistral| G[云端API响应]\n F --> H[返回文本结果]\n G --> H\n H --> I[追加到对话历史]\n I --> J[Markdown渲染显示]\n J --> K[等待下一轮输入]" + } + ] + }, + "timestamp": 1759024986, + "prompt_hash": "96a241c8fb50490541b377f3d4da0e04", + "token_usage": { + "input_tokens": 22372, + "output_tokens": 1011, + "total_tokens": 23383 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/c6c26d9cbe960ea4d90bf7c49a5467f0.json" "b/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/c6c26d9cbe960ea4d90bf7c49a5467f0.json" new file mode 100644 index 0000000..99a3660 --- /dev/null +++ "b/.litho/cache/studies_research/\345\267\245\344\275\234\346\265\201\350\260\203\347\240\224\346\212\245\345\221\212/c6c26d9cbe960ea4d90bf7c49a5467f0.json" @@ -0,0 +1,34 @@ +{ + "data": { + "main_workflow": { + "name": "文章智能处理与阅读流程", + "description": "用户选择一篇文章后,系统从数据库或网络抓取原始内容,并通过LLM代理依次执行净化(Purge)、优化(Optimize)和融合(Melt)三个阶段的智能处理,最终将结构化、高质量的内容呈现给用户。该流程是系统的核心价值所在,实现了从原始网页到可读性强的知识内容的转化。", + "flowchart_mermaid": "graph TD\n A[用户点击文章] --> B{文章内容是否存在}\n B -->|否| C[启动内容抓取]\n C --> D[RSS/搜索/直接URL抓取]\n D --> E[提取正文文本]\n B -->|是| F[加载已存档内容]\n E --> G[LLM净化: 去除噪音]\n F --> G\n G --> H[LLM优化: 结构化摘要]\n H --> I[LLM融合: 深度洞察生成]\n I --> J[更新数据库]\n J --> K[前端展示优化后内容]\n K --> L[用户获得智能阅读体验]" + }, + "other_important_workflows": [ + { + "name": "应用启动初始化流程", + "description": "应用程序启动时,首先加载全局配置和日志系统,然后并行初始化用户配置和个人订阅信息,并检查本地AI模型(如Ollama)的运行状态。完成后创建前端状态管理器并渲染主界面,确保用户进入应用即可使用完整功能。", + "flowchart_mermaid": "graph TD\n A[启动应用] --> B[加载app_config.toml]\n B --> C{文件存在?}\n C -->|否| D[创建默认配置]\n C -->|是| E[读取配置]\n D --> F[持久化配置]\n E --> F\n F --> G[初始化日志系统]\n G --> H[加载user_config.toml]\n H --> I{新用户?}\n I -->|是| J[生成默认订阅包]\n I -->|否| K[加载用户数据]\n J --> L[初始化LLM服务]\n K --> L\n L --> M[唤醒Ollama若未运行]\n M --> N[构建全局状态Store]\n N --> O[渲染主界面]" + }, + { + "name": "订阅内容自动更新流程", + "description": "系统定时触发订阅源更新任务,对每个订阅项调用对应的抓取器(RSS或搜索引擎),获取最新的文章列表。对于每篇新文章,启动异步处理管道进行内容提取和AI增强处理,并将结果存储至本地数据库,供后续阅读使用。", + "flowchart_mermaid": "graph TD\n A[定时触发更新] --> B[遍历所有订阅源]\n B --> C{类型=RSS?}\n C -->|是| D[解析RSS XML]\n C -->|否| E[执行Bing/Baidu搜索]\n D --> F[提取标题/链接/摘要]\n E --> F\n F --> G[抓取文章完整正文]\n G --> H[检查是否已存在]\n H -->|否| I[创建新文章记录]\n H -->|是| J[跳过或标记为新]\n I --> K[加入LLM处理队列]\n K --> L[Purge → Optimize → Melt]\n L --> M[持久化处理结果]\n M --> N[通知UI刷新列表]" + }, + { + "name": "AI助手对话交互流程", + "description": "用户在AI精灵面板中输入问题后,系统将当前文章内容与用户提问结合,构造提示词发送至LLM代理。代理根据配置选择具体提供商(如Ollama、GLM等)进行推理,并将生成的回答返回前端展示,支持多轮对话历史维护。", + "flowchart_mermaid": "graph TD\n A[用户打开AI精灵面板] --> B[输入问题并发送]\n B --> C[拼接上下文: 文章内容 + 对话历史]\n C --> D[构造Prompt发送至LLM代理]\n D --> E{选择LLM提供商}\n E --> F[调用Ollama/OpenAI/GLM/Mistral]\n F --> G[接收流式响应]\n G --> H[前端实时渲染回答]\n H --> I[追加到对话历史]\n I --> J[等待下一轮输入]" + } + ] + }, + "timestamp": 1759025329, + "prompt_hash": "c6c26d9cbe960ea4d90bf7c49a5467f0", + "token_usage": { + "input_tokens": 22372, + "output_tokens": 1387, + "total_tokens": 23759 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/AI\350\203\275\345\212\233\351\233\206\346\210\220\345\237\237/05e6bfd706e2703d2ed5aa1ec947ad82.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/AI\350\203\275\345\212\233\351\233\206\346\210\220\345\237\237/05e6bfd706e2703d2ed5aa1ec947ad82.json" new file mode 100644 index 0000000..ac6af30 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/AI\350\203\275\345\212\233\351\233\206\346\210\220\345\237\237/05e6bfd706e2703d2ed5aa1ec947ad82.json" @@ -0,0 +1,26 @@ +{ + "data": { + "domain_name": "AI能力集成域", + "module_name": "LLM代理服务", + "module_description": "实现面向多种LLM提供商的代理模式,屏蔽底层接口差异,提供统一的文本生成能力。通过枚举类型CompletionServiceEnums封装了Ollama、Mistral、Platform、GLM和OpenAI等不同提供商的具体服务实现,并在CompletionAgent结构体中根据配置动态选择实际的服务实例。", + "interaction": "定义了CompletionService trait作为统一接口,各具体实现(如OllamaCompletionService、OpenAILikeCompletionService)均实现此trait。CompletionAgent作为代理层,根据LLMSection中的active_provider_type字段决定使用哪个具体服务实例。系统通过new()方法初始化代理,通过异步completion()方法发送用户输入并获取响应。", + "implementation": "采用Rust语言实现,基于reqwest进行HTTP通信,serde用于序列化/反序列化。核心是CompletionAgent结构体,内部持有CompletionServiceEnums枚举类型的provider字段,该枚举包装了不同LLM提供商的服务实例。通过match表达式在运行时分发调用到具体实现。Ollama和OpenAI兼容服务直接处理API请求,而GLM和Mistral则作为适配层复用OpenAI兼容逻辑。", + "associated_files": [ + "crates/llm/src/llm_agent.rs", + "crates/llm/src/providers/llm_ollama.rs", + "crates/llm/src/providers/llm_openaibase_like.rs", + "crates/llm/src/providers/llm_glm.rs", + "crates/llm/src/providers/llm_mistral.rs" + ], + "flowchart_mermaid": "graph TD\n A[用户请求] --> B{CompletionAgent}\n B --> C[根据active_provider_type选择]\n C --> D[OllamaCompletionService]\n C --> E[MistralQinoAgentService]\n C --> F[GLMCompletionService]\n C --> G[OpenAILikeCompletionService]\n D --> H[发送POST请求到Ollama API]\n E --> I[通过OpenAILike复用逻辑调用Mistral]\n F --> J[转换为OpenAI格式调用]\n G --> K[发送POST请求到OpenAI兼容API]\n H --> L[返回响应]\n I --> L\n J --> L\n K --> L", + "sequence_diagram_mermaid": "sequenceDiagram\n participant User\n participant CompletionAgent\n participant Provider\n participant API\n User->>CompletionAgent: completion(message)\n activate CompletionAgent\n CompletionAgent->>CompletionAgent: 根据active_provider_type匹配服务\n alt Ollama提供者\n CompletionAgent->>Provider: OllamaCompletionService::new()\n Provider->>API: POST /api/generate (Ollama)\n else OpenAI/Mistral/GLM提供者\n CompletionAgent->>Provider: OpenAILikeCompletionService::new()\n Provider->>API: POST /v1/chat/completions\n end\n API-->>Provider: 返回JSON响应\n Provider-->>CompletionAgent: 解析response.content\n CompletionAgent-->>User: 返回文本结果\n deactivate CompletionAgent" + }, + "timestamp": 1759025012, + "prompt_hash": "05e6bfd706e2703d2ed5aa1ec947ad82", + "token_usage": { + "input_tokens": 4421, + "output_tokens": 926, + "total_tokens": 5347 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\345\244\204\347\220\206\345\237\237/0def7ce5bb74891b3843f02402fcf908.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\345\244\204\347\220\206\345\237\237/0def7ce5bb74891b3843f02402fcf908.json" new file mode 100644 index 0000000..1041860 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\345\244\204\347\220\206\345\237\237/0def7ce5bb74891b3843f02402fcf908.json" @@ -0,0 +1,26 @@ +{ + "data": { + "domain_name": "内容处理域", + "module_name": "LLM内容处理器", + "module_description": "该模块利用大语言模型对抓取的文章内容进行智能化处理,包括内容净化、语义优化和信息融合三大核心功能。通过预设的提示模板与LLM交互,实现高质量内容输出。", + "interaction": "定义了IPresetArticleLLMProcessor接口作为统一契约,各处理器(purge/optimizer/melt)实现该接口。通过ArticleLLMProcessor与智能代理服务(CompletionAgent)交互,完成向底层LLM服务的请求转发。", + "implementation": "基于Rust异步生态构建,使用serde进行序列化,reqwest处理HTTP通信。采用策略模式设计,通过枚举类型动态绑定不同LLM提供商。各处理器使用固定提示模板与温度参数控制生成行为:净化(purge)注重完整性,优化(optimizer)强调稳定性(temperature=0.1),熔炼(melt)允许一定创造性(temperature=0.7)。", + "associated_files": [ + "crates/intelligent/src/article_processor/purge.rs", + "crates/intelligent/src/article_processor/optimizer.rs", + "crates/intelligent/src/article_processor/melt.rs", + "crates/llm/src/llm_agent.rs", + "crates/llm/src/providers/llm_openaibase_like.rs" + ], + "flowchart_mermaid": "graph TD\n A[原始文章内容] --> B{选择处理器}\n B --> C[净化处理器]\n B --> D[优化处理器]\n B --> E[熔炼处理器]\n C --> F[调用CompletionAgent]\n D --> F\n E --> F\n F --> G[LLM服务提供商]\n G --> H[返回处理后内容]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant User\n participant ArticleProcessor\n participant CompletionAgent\n participant LLMProvider\n User->>ArticleProcessor: request processing\n ArticleProcessor->>CompletionAgent: build prompt & send request\n CompletionAgent->>LLMProvider: forward via OpenAI-like API\n LLMProvider-->>CompletionAgent: return generated text\n CompletionAgent-->>ArticleProcessor: parsed response\n ArticleProcessor-->>User: return processed article" + }, + "timestamp": 1758807722, + "prompt_hash": "0def7ce5bb74891b3843f02402fcf908", + "token_usage": { + "input_tokens": 2692, + "output_tokens": 684, + "total_tokens": 3376 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\350\216\267\345\217\226\344\270\216\345\244\204\347\220\206\345\237\237/23bbe2a147778a11c13ed9da4020a2ec.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\350\216\267\345\217\226\344\270\216\345\244\204\347\220\206\345\237\237/23bbe2a147778a11c13ed9da4020a2ec.json" new file mode 100644 index 0000000..533a8b2 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\345\206\205\345\256\271\350\216\267\345\217\226\344\270\216\345\244\204\347\220\206\345\237\237/23bbe2a147778a11c13ed9da4020a2ec.json" @@ -0,0 +1,24 @@ +{ + "data": { + "domain_name": "内容获取与处理域", + "module_name": "文章内容处理管道", + "module_description": "构建基于LLM的文章处理流水线,依次执行净化、优化和融合操作。", + "interaction": "定义了IPresetArticleLLMProcessor接口,通过new_processor方法创建具体的LLM处理器实例。各处理器(Purge、Optimizer、Melt)实现该接口并提供不同的提示词和AI参数配置。", + "implementation": "使用Rust语言实现,基于ArticleLLMProcessor核心类,通过加载外部prompt文件构造系统提示和用户指令。Purge模块设置num_ctx=8192用于长文本处理;Optimizer模块设置temperature=0.1保证输出稳定性;Melt模块设置temperature=0.7增加生成多样性。所有模块均封装在intelligent crate中,通过traits进行抽象解耦。", + "associated_files": [ + "crates/intelligent/src/article_processor/purge.rs", + "crates/intelligent/src/article_processor/optimizer.rs", + "crates/intelligent/src/article_processor/melt.rs" + ], + "flowchart_mermaid": "graph TD\n A[原始文章内容] --> B{处理阶段}\n B --> C[Purge模块]\n C -->|去除噪音| D[净化后内容]\n D --> E[Optimizer模块]\n E -->|精细化调整| F[优化后内容]\n F --> G[Melt模块]\n G -->|内容熔合| H[最终高质量内容]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant User\n participant Processor\n participant LLM\n User->>Processor: 请求处理文章\n Processor->>Processor: 创建Purge处理器\n Processor->>LLM: 发送净化请求(temperature=0.1)\n LLM-->>Processor: 返回净化结果\n Processor->>Processor: 创建Optimizer处理器\n Processor->>LLM: 发送优化请求(num_ctx=8192)\n LLM-->>Processor: 返回优化结果\n Processor->>Processor: 创建Melt处理器\n Processor->>LLM: 发送熔合请求(temperature=0.7)\n LLM-->>Processor: 返回最终结果\n Processor-->>User: 返回处理完成的文章" + }, + "timestamp": 1759024999, + "prompt_hash": "23bbe2a147778a11c13ed9da4020a2ec", + "token_usage": { + "input_tokens": 8891, + "output_tokens": 686, + "total_tokens": 9577 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\345\255\230\345\202\250\345\237\237/030b4b030d6c3d49b56031a8216be15f.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\345\255\230\345\202\250\345\237\237/030b4b030d6c3d49b56031a8216be15f.json" new file mode 100644 index 0000000..90689e2 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\345\255\230\345\202\250\345\237\237/030b4b030d6c3d49b56031a8216be15f.json" @@ -0,0 +1,23 @@ +{ + "data": { + "domain_name": "数据存储域", + "module_name": "数据库访问层", + "module_description": "封装对SQLite数据库的CRUD操作,提供类型安全的数据访问接口。", + "interaction": "定义了与文章记录服务之间的接口调用方式,通过依赖注入将Operator实例传递给ArticleRecorderService,支持异步方法调用如insert、update、delete和query。使用SeaORM的QueryFilter进行条件构建,实现按ID、链接、分组等多维度查询。", + "implementation": "基于SeaORM异步ORM框架实现,采用惰性初始化策略,在首次调用时建立数据库连接并自动创建表结构。使用连接池管理数据库连接,提升并发性能。支持分页查询和复杂条件过滤,所有操作均为异步fn,适配Rust异步运行时。核心类型包括DatabaseConnection、Entity、Model等。", + "associated_files": [ + "crates/recorder/src/operator.rs", + "crates/recorder/src/entity/article_record.rs" + ], + "flowchart_mermaid": "graph TD\n A[应用层] --> B[文章记录服务]\n B --> C[数据库访问层]\n C --> D[(SQLite数据库)]\n C --> E[连接池管理]\n C --> F[表结构自动创建]\n B --> G[状态管理]\n B --> H[全文检索]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant App as 应用层\n participant Service as 文章记录服务\n participant Operator as 数据库访问层\n participant DB as SQLite数据库\n\n App->>Service: insert_article(article)\n Service->>Operator: insert(model)\n Operator->>DB: INSERT INTO t_article_record\n DB-->>Operator: 返回结果\n Operator-->>Service: Result\n Service-->>App: ArticleRecordId\n\n App->>Service: search_by_keywords('rust')\n Service->>Operator: find_with_filter()\n Operator->>DB: SELECT ... WHERE title LIKE '%rust%'\n DB-->>Operator: 查询结果集\n Operator-->>Service: Vec\n Service-->>App: Vec" + }, + "timestamp": 1758807734, + "prompt_hash": "030b4b030d6c3d49b56031a8216be15f", + "token_usage": { + "input_tokens": 1197, + "output_tokens": 662, + "total_tokens": 1859 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\237\237/7c432dd8749edd8ce83c5ec9f84db7f8.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\237\237/7c432dd8749edd8ce83c5ec9f84db7f8.json" new file mode 100644 index 0000000..7bee091 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\346\225\260\346\215\256\346\214\201\344\271\205\345\214\226\345\237\237/7c432dd8749edd8ce83c5ec9f84db7f8.json" @@ -0,0 +1,24 @@ +{ + "data": { + "domain_name": "数据持久化域", + "module_name": "文章记录服务", + "module_description": "该模块是文章记录的核心服务层实现,封装了对文章记录的各类数据访问逻辑。它通过依赖 Operator 操作底层数据库,实现了初始化、插入、更新、查询(按分组、收藏、未读、时间范围等)、标记已读、设置收藏、关键词搜索等功能。其主要职责集中在文章记录的生命周期管理与状态变更控制,是连接上层业务逻辑与底层数据存储的关键中介。", + "interaction": "定义接口与交互方式:\n- 通过 `ArticleRecorderService` 结构体暴露公共方法\n- 所有操作均为异步函数,返回 `anyhow::Result` 类型\n- 依赖 `Operator` 组件进行底层数据库操作\n- 使用 SeaORM 的 Model 和 ActiveModel 进行数据映射和操作\n- 支持多种查询条件(ID、分组、收藏状态、阅读状态、时间范围、关键词)\n- 提供资源清理接口 `dispose()`", + "implementation": "技术细节实现:\n- 使用 Rust 异步编程模型(async/await)\n- 基于 SeaORM 框架实现 ORM 操作\n- 数据库为 SQLite,通过 `sqlite://` 协议连接\n- 连接池配置:最大10连接,最小2连接,超时10秒\n- 表结构自动创建机制,在初始化时检查并创建 `t_article_record` 表\n- 路径管理使用 `dirs` crate 获取系统标准路径\n- 文件路径常量定义:`qino_feed.app_data` 目录和 `article_recorder.db` 文件\n- 实现了单例模式的数据库操作器\n- 所有文件操作基于 `std::path::PathBuf`\n- 自动创建缺失的目录结构", + "associated_files": [ + "crates/recorder/src/article_recorder_service.rs", + "crates/recorder/src/operator.rs", + "crates/recorder/src/path.rs" + ], + "flowchart_mermaid": "graph TD\n A[ArticleRecorderService] --> B[Operator]\n B --> C[DatabaseConnection]\n C --> D[(SQLite Database)]\n A --> E[path.rs]\n E --> F[System Paths]\n \n subgraph Data Flow\n G[Business Logic] --> A\n A -->|insert/update/query| B\n B -->|SQL Operations| C\n C -->|File I/O| D\n E -->|Path Resolution| A\n end", + "sequence_diagram_mermaid": "sequenceDiagram\n participant Business as 业务逻辑层\n participant Service as ArticleRecorderService\n participant Operator as Operator\n participant DB as DatabaseConnection\n participant File as path.rs\n \n Business->>Service: initialize()\n Service->>File: get_appdata_articles()\n File-->>Service: 返回数据库路径\n Service->>Operator: initialize()\n Operator->>DB: 创建连接池\n DB-->>Operator: 返回连接实例\n Operator->>DB: create_table_if_not_existed()\n DB-->>Operator: 表创建结果\n Operator-->>Service: 初始化完成\n Service-->>Business: 成功/错误\n \n Business->>Service: insert(records)\n Service->>Operator: query() 检查重复\n alt 存在未读记录\n Operator-->>Service: 返回存在标志\n Service->>Operator: delete() 删除旧记录\n else\n Service->>Operator: insert() 新记录\n end\n Operator-->>Service: 操作结果\n Service-->>Business: 插入数量" + }, + "timestamp": 1759025012, + "prompt_hash": "7c432dd8749edd8ce83c5ec9f84db7f8", + "token_usage": { + "input_tokens": 4738, + "output_tokens": 1107, + "total_tokens": 5845 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/b0366f6699fb5bb1906582413a3ede08.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/b0366f6699fb5bb1906582413a3ede08.json" new file mode 100644 index 0000000..199706f --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/b0366f6699fb5bb1906582413a3ede08.json" @@ -0,0 +1,25 @@ +{ + "data": { + "domain_name": "状态管理域", + "module_name": "全局状态容器", + "module_description": "作为应用的核心状态枢纽,整合多个子store并提供统一访问接口,负责维护当前选中的feed和文章状态,支持feed切换、内容更新调度及自动初始化逻辑。", + "interaction": "通过依赖注入方式与其他子store(如feeds、articles、tasks等)进行交互;对外暴露统一的getter和setter接口供UI组件调用;利用Svelte的$effect实现跨模块状态联动与响应式更新。", + "implementation": "使用Svelte的$state、$derived和$effect构建响应式状态系统;通过createStore函数创建全局共享实例;在初始化时自动刷新feeds并选中今日feed,根据最新文章日期决定是否触发全量更新;采用模块化设计整合多个子store。", + "associated_files": [ + "app/src/routes/main/stores/index.svelte.ts", + "app/src/routes/main/stores/articles/list/index.svelte.ts", + "app/src/routes/main/stores/tasks.svelte.ts", + "app/src/routes/main/stores/articles/search/index.svelte.ts" + ], + "flowchart_mermaid": "graph TD\n A[全局状态容器] --> B[整合 Feeds Store]\n A --> C[整合 Articles Store]\n A --> D[整合 Tasks Store]\n A --> E[整合 Reader Store]\n A --> F[整合 Sprite Store]\n G[初始化加载] --> H[刷新 Feeds]\n H --> I[默认选中今日 Feed]\n I --> J{是否需要全量更新?}\n J -->|是| K[触发全量数据更新]\n J -->|否| L[加载缓存数据]\n A --> M[提供统一访问接口]\n M --> N[feed 切换]\n M --> O[文章获取]\n M --> P[状态派生计算]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant UI\n participant Store as 全局状态容器\n participant TasksStore as Tasks Store\n participant ArticlesStore as Articles Store\n\n UI->>Store: 初始化应用\n Store->>Store: $effect 执行自动初始化\n Store->>Store: 刷新 Feeds 列表\n Store->>Store: 默认选中今日 Feed\n Store->>ArticlesStore: 加载文章列表\n ArticlesStore->>TasksStore: 注册异步加载任务\n TasksStore-->>ArticlesStore: 返回 pending 状态\n ArticlesStore-->>Store: 返回文章数据\n Store-->>UI: 提供聚合状态\n\n UI->>Store: 触发 feed 切换\n Store->>ArticlesStore: 根据新 feed 加载数据\n ArticlesStore->>TasksStore: 添加新任务\n TasksStore-->>ArticlesStore: 更新 loading 状态\n ArticlesStore-->>UI: 流式返回分页数据" + }, + "timestamp": 1758807734, + "prompt_hash": "b0366f6699fb5bb1906582413a3ede08", + "token_usage": { + "input_tokens": 1666, + "output_tokens": 871, + "total_tokens": 2537 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/cb9efdf8e6795c7f0bbfe403c6d6437b.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/cb9efdf8e6795c7f0bbfe403c6d6437b.json" new file mode 100644 index 0000000..1d10a17 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\212\266\346\200\201\347\256\241\347\220\206\345\237\237/cb9efdf8e6795c7f0bbfe403c6d6437b.json" @@ -0,0 +1,26 @@ +{ + "data": { + "domain_name": "状态管理域", + "module_name": "集中式状态存储", + "module_description": "创建和整合多个子store,对外提供统一的状态访问接口,是整个应用的状态中枢。整合feeds、articles、tasks等多个子store,管理当前feed和文章选择状态,并调度定时内容更新任务。", + "interaction": "通过createStore函数创建集中式状态管理器,整合feeds、articles、tasks、reader和sprite等子store。提供setCurrentFeedId、setCurrentArticle等方法供外部调用,使用$state和$derived实现响应式状态管理,通过$effect监听状态变化并触发相应操作。", + "implementation": "采用Svelte的反应式特性($state, $derived, $effect)实现自动更新。通过全局共享的globalSharedScheduleUpdatingFuture确保更新任务不被重复触发。使用工厂模式(create函数)生成具名store实例,符合Svelte stores规范。主要功能包括:当前feed和文章的管理、特定筛选条件的选择逻辑、定时内容更新调度、以及初始化时的数据加载控制。", + "associated_files": [ + "app/src/routes/main/stores/index.svelte.ts", + "app/src/routes/main/stores/articles/list/index.svelte.ts", + "app/src/routes/main/stores/tasks.svelte.ts", + "app/src/routes/main/stores/reader.svelte.ts", + "app/src/routes/main/stores/sprite.svelte.ts" + ], + "flowchart_mermaid": "graph TD\n A[集中式状态存储] --> B[整合子Store]\n B --> C[feeds store]\n B --> D[articles store]\n B --> E[tasks store]\n B --> F[reader store]\n B --> G[sprite store]\n A --> H[提供统一接口]\n H --> I[setCurrentFeedId]\n H --> J[setCurrentArticle]\n H --> K[scheduleUpdate]\n A --> L[响应式管理]\n L --> M[$state]\n L --> N[$derived]\n L --> O[$effect]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant UI\n participant Store as 集中式状态存储\n participant Articles as articles store\n participant Tasks as tasks store\n \n UI->>Store: setCurrentFeedId(feedId)\n Store->>Articles: list.associatedFeedId = feedId\n Store->>Articles: list.refresh(true)\n Articles->>API: read_feed_contents()\n API-->>Articles: 返回数据\n Articles->>Store: 更新groupedArticles\n \n UI->>Store: scheduleUpdate()\n alt 没有正在进行的任务\n Store->>Tasks: addPending(taskId, promise)\n loop 每个feed\n Tasks->>API: update_feed_contents()\n end\n Tasks-->>Store: 所有任务完成\n Store->>Articles: notifyDatasourceUpdated()\n else 有正在进行的任务\n Store->>Tasks: queryPending(taskId)\n Tasks-->>Store: 返回pending任务\n Store->>UI: 复用现有任务\n end" + }, + "timestamp": 1759025001, + "prompt_hash": "cb9efdf8e6795c7f0bbfe403c6d6437b", + "token_usage": { + "input_tokens": 6906, + "output_tokens": 888, + "total_tokens": 7794 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/6e96afdc15ae6c72c2ce76e824e6b44c.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/6e96afdc15ae6c72c2ce76e824e6b44c.json" new file mode 100644 index 0000000..db1d7d5 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/6e96afdc15ae6c72c2ce76e824e6b44c.json" @@ -0,0 +1,23 @@ +{ + "data": { + "domain_name": "用户界面域", + "module_name": "主页面布局", + "module_description": "作为整个主界面的布局容器,负责协调信息源列表、文章列表和内容阅读器等组件,初始化主状态存储并集成全局通知系统。", + "interaction": "通过props向子组件传递store实例和回调函数,接收来自侧边栏导航、文章列表和AI助手面板的事件回调,实现跨模块状态同步。", + "implementation": "使用SvelteKit的+page.svelte路由机制构建主页面,通过createStore初始化全局状态管理,利用Svelte的响应式声明语法($effect)处理副作用逻辑,并采用CSS类预设实现主题化UI设计。", + "associated_files": [ + "app/src/routes/main/+page.svelte", + "app/src/routes/main/stores/index.svelte" + ], + "flowchart_mermaid": "graph TD\n A[主页面布局] --> B[侧边栏导航]\n A --> C[文章列表展示]\n A --> D[内容阅读器]\n A --> E[AI助手面板]\n A --> F[全局Footer]\n A --> G[全局Toaster通知]\n A --> H[状态Store初始化]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant User\n participant MainPage as 主页面布局\n participant FeedsList as 侧边栏导航\n participant ArticlesList as 文章列表\n participant ArticleReader as 内容阅读器\n\n User->>MainPage: 访问/main路由\n MainPage->>MainPage: 初始化createStore()\n MainPage->>FeedsList: 传递feedsStore和回调\n MainPage->>ArticlesList: 传递articlesStore和markAsRead\n MainPage->>ArticleReader: 传递readerStore\n FeedsList->>MainPage: onFeedPressed(feedId)\n ArticlesList->>MainPage: onArticlePressed(article)\n MainPage->>ArticlesList: 更新selectedArticle\n MainPage->>ArticleReader: 显示currentArticle内容" + }, + "timestamp": 1759024994, + "prompt_hash": "6e96afdc15ae6c72c2ce76e824e6b44c", + "token_usage": { + "input_tokens": 8454, + "output_tokens": 616, + "total_tokens": 9070 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/9bda3a2868ba8c9632a6c519b38871e8.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/9bda3a2868ba8c9632a6c519b38871e8.json" new file mode 100644 index 0000000..a8f17bd --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\224\250\346\210\267\347\225\214\351\235\242\345\237\237/9bda3a2868ba8c9632a6c519b38871e8.json" @@ -0,0 +1,26 @@ +{ + "data": { + "domain_name": "用户界面域", + "module_name": "主界面布局", + "module_description": "实现应用的三栏式主布局结构,整合文章列表、阅读器和AI助手面板等核心组件。采用Flexbox实现响应式设计,通过Svelte stores进行全局状态管理,并支持条件渲染控制与多模块集成。", + "interaction": "定义了统一的props接口供子组件使用,包括store状态对象和回调函数;通过createStore初始化主状态并注入到FeedsList、ArticlesList、ArticleReader等子组件;利用Svelte的$state和$effect实现响应式数据流与生命周期控制。", + "implementation": "基于Svelte框架构建,使用Flexbox布局模型实现三栏式响应式UI(左侧订阅列表、中间文章列表、右侧阅读器/AI助手)。通过Svelte Stores进行跨组件状态共享,结合条件渲染展示ArticleReader或空白占位符。集成AI精灵面板和全局通知系统,确保用户交互流畅性与信息反馈及时性。", + "associated_files": [ + "app/src/routes/main/+page.svelte", + "app/src/routes/main/widgets/FeedsList.svelte", + "app/src/routes/main/widgets/ArticlesList.svelte", + "app/src/routes/main/widgets/ArticleReader.svelte", + "app/src/routes/main/widgets/AISpritePanel.svelte" + ], + "flowchart_mermaid": "graph TD\n A[主页面 +page.svelte] --> B[FeedsList 订阅列表]\n A --> C[ArticlesList 文章列表]\n A --> D[ArticleReader 阅读器]\n A --> E[AISpritePanel AI助手]\n F[Svelte Store] --> A\n F --> B\n F --> C\n F --> D\n F --> E\n style A fill:#4CAF50, color:white\n style F fill:#2196F3, color:white", + "sequence_diagram_mermaid": "sequenceDiagram\n participant Page as 主页面\n participant Store as 全局Store\n participant Feeds as FeedsList\n participant Articles as ArticlesList\n participant Reader as ArticleReader\n \n Page->>Store: createStore()\n Page->>Feeds: 传递store与回调\n Page->>Articles: 传递store与onArticlePressed\n Page->>Reader: 传递articleId\n Articles->>Store: $subscribe 获取文章数据\n Articles->>Page: onArticlePressed(article)\n Page->>Reader: 更新articleId\n Reader->>Store: 请求文章内容\n Store-->>Reader: 返回优化/熔炼/原始内容\n \n style Page fill:#4CAF50\n style Store fill:#2196F3" + }, + "timestamp": 1758807726, + "prompt_hash": "9bda3a2868ba8c9632a6c519b38871e8", + "token_usage": { + "input_tokens": 2513, + "output_tokens": 782, + "total_tokens": 3295 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237/f929784062a9f9600134fe6772bd6ee8.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237/f929784062a9f9600134fe6772bd6ee8.json" new file mode 100644 index 0000000..2229356 --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237/f929784062a9f9600134fe6772bd6ee8.json" @@ -0,0 +1,26 @@ +{ + "data": { + "domain_name": "系统启动与配置域", + "module_name": "启动流程管理", + "module_description": "作为应用启动中枢,采用分阶段策略进行初始化:Tiger0_1同步初始化关键配置和日志系统,随后并行初始化用户配置与LLM服务依赖。通过`tokio::join!`实现并发加载以提升启动效率,并具备错误聚合处理机制。", + "interaction": "定义了`ContextHost` trait用于统一管理`ApplicationContext`的生命周期;各子模块通过返回`InitTask`结构参与初始化流程;支持延迟初始化(Tiger2预留接口)体现阶段性启动设计思想。", + "implementation": "使用Rust异步运行时Tokio实现非阻塞I/O操作;采用分阶段初始化策略(Tiger0_1同步、Tiger1并行)优化启动性能;通过`anyhow::Result`进行错误传播与聚合处理;利用`spdlog`实现结构化日志输出。", + "associated_files": [ + "crates/feed_api_rs/src/startup/mod.rs", + "crates/feed_api_rs/src/startup/init_app_config.rs", + "crates/feed_api_rs/src/startup/init_user_profile.rs", + "crates/feed_api_rs/src/startup/init_llm.rs", + "crates/feed_api_rs/src/startup/init_logger.rs" + ], + "flowchart_mermaid": "graph TD\n A[启动流程开始] --> B{是否Debug模式}\n B -->|是| C[启用默认日志]\n B -->|否| D[读取app_config.toml]\n D --> E{文件存在?}\n E -->|否| F[生成默认配置]\n E -->|是| G[解析TOML配置]\n F --> H[持久化到磁盘]\n G --> I[初始化日志系统]\n H --> I\n I --> J[并行初始化]\n J --> K[加载用户配置]\n J --> L[唤醒LLM服务]\n K --> M{成功?}\n L --> N{成功?}\n M -->|否| O[聚合错误退出]\n N -->|否| O\n M -->|是| P[构建ApplicationContext]\n N -->|是| P\n P --> Q[启动完成]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant S as Startup\n participant AC as AppConfig\n participant UC as UserProfile\n participant LL as LLMRuntime\n participant LG as Logger\n \n S->>AC: init_app_config::call()\n AC-->>S: 返回AppConfig\n \n S->>LG: init_logger::call(&app_config)\n LG-->>S: 日志系统就绪\n \n par 并行初始化\n S->>UC: init_user_profile::call()\n S->>LL: init_llm::call(llm_section)\n \n UC-->>S: 返回UserConfig\n LL-->>S: 返回LLM状态\n end\n \n alt 任一失败\n S->>S: 聚合错误并终止\n else 全部成功\n S->>S: 构建ApplicationContext\n end" + }, + "timestamp": 1759025041, + "prompt_hash": "f929784062a9f9600134fe6772bd6ee8", + "token_usage": { + "input_tokens": 4972, + "output_tokens": 853, + "total_tokens": 5825 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\351\233\206\346\210\220\345\237\237/aff4d36feb00eb3ad43b48f8091c1ee3.json" "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\351\233\206\346\210\220\345\237\237/aff4d36feb00eb3ad43b48f8091c1ee3.json" new file mode 100644 index 0000000..02c1d6b --- /dev/null +++ "b/.litho/cache/studies_research/\346\240\270\345\277\203\346\250\241\345\235\227\344\270\216\347\273\204\344\273\266\350\260\203\347\240\224\346\212\245\345\221\212/\347\263\273\347\273\237\351\233\206\346\210\220\345\237\237/aff4d36feb00eb3ad43b48f8091c1ee3.json" @@ -0,0 +1,23 @@ +{ + "data": { + "domain_name": "系统集成域", + "module_name": "启动初始化", + "module_description": "协调应用启动时的各项初始化任务,包括配置加载和服务准备。", + "interaction": "通过InitTask封装初始化流程,实现Tiger0(同步)和Tiger1(并发)两阶段初始化策略;Tiger0完成核心配置与日志系统设置,Tiger1并行执行用户配置加载和LLM服务检测等任务。", + "implementation": "使用tokio::join!实现init_user_profile和init_llm的并发初始化以提升性能;通过ContextHost trait管理ApplicationContext生命周期;配置文件采用TOML格式进行序列化与反序列化,并在缺失时生成默认配置写入磁盘。", + "associated_files": [ + "crates/feed_api_rs/src/startup/mod.rs", + "crates/feed_api_rs/src/startup/init_app_config.rs" + ], + "flowchart_mermaid": "graph TD\n A[应用启动] --> B{配置文件存在?}\n B -->|是| C[加载app_config.toml]\n B -->|否| D[生成默认配置]\n C & D --> E[反序列化为AppConfig]\n E --> F[写入磁盘sync_to]\n F --> G[Tiger0: 同步初始化核心配置与日志]\n G --> H[Tiger1: 并发初始化用户配置与LLM服务]\n H --> I[启动完成]", + "sequence_diagram_mermaid": "sequenceDiagram\n participant Frontend\n participant Startup\n participant AppConfig\n participant LLMService\n\n Startup->>AppConfig: load_or_default()\n alt 配置文件存在\n AppConfig-->>Startup: 返回已加载的配置\n else 默认配置\n AppConfig->>AppConfig: generate_default()\n AppConfig->>Disk: sync_to(app_config.toml)\n AppConfig-->>Startup: 返回默认配置\n end\n Startup->>Startup: init_context_host()\n Startup->>Startup: Tiger0.init_core_config()\n Startup->>Startup: Tiger0.init_logging()\n par 并发初始化\n Startup->>Startup: init_user_profile()\n Startup->>LLMService: init_llm()\n end\n Startup-->>Frontend: launch complete" + }, + "timestamp": 1758807799, + "prompt_hash": "aff4d36feb00eb3ad43b48f8091c1ee3", + "token_usage": { + "input_tokens": 2297, + "output_tokens": 659, + "total_tokens": 2956 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/21d4878ee02b3c82a86a034c67fe3094.json" "b/.litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/21d4878ee02b3c82a86a034c67fe3094.json" new file mode 100644 index 0000000..811a6c8 --- /dev/null +++ "b/.litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/21d4878ee02b3c82a86a034c67fe3094.json" @@ -0,0 +1,102 @@ +{ + "data": { + "project_name": "saga-reader", + "project_description": "一个基于Tauri框架的桌面端信息聚合与智能阅读应用,支持RSS订阅、搜索引擎抓取,并集成大语言模型进行内容优化、熔炼和AI对话。", + "project_type": "FullStackApp", + "business_value": "为用户提供一站式的高质量信息获取与智能阅读体验,通过LLM技术提升内容可读性和交互性,帮助用户高效处理海量网络信息。", + "target_users": [ + { + "name": "知识工作者", + "description": "需要持续获取行业资讯、技术文章的专业人士", + "needs": [ + "高效的信息聚合", + "智能内容摘要与提炼", + "跨平台同步阅读进度" + ] + }, + { + "name": "研究人员", + "description": "需要追踪特定领域最新动态的学术或市场研究人员", + "needs": [ + "精准的内容搜索与过滤", + "文献级内容保存", + "AI辅助分析能力" + ] + }, + { + "name": "技术爱好者", + "description": "关注前沿科技、喜欢尝试新工具的极客用户", + "needs": [ + "本地化数据存储", + "可扩展的插件架构", + "Ollama等本地AI模型集成" + ] + } + ], + "external_systems": [ + { + "name": "RSS Feeds", + "description": "第三方网站提供的RSS订阅源,作为主要内容获取渠道", + "interaction_type": "内容抓取" + }, + { + "name": "Bing Search", + "description": "必应搜索引擎,用于补充无法通过RSS获取的内容", + "interaction_type": "网页爬取" + }, + { + "name": "Baidu Search", + "description": "百度搜索引擎,主要面向中文内容的补充抓取", + "interaction_type": "网页爬取" + }, + { + "name": "Ollama", + "description": "本地大语言模型运行时,提供文本生成和理解能力", + "interaction_type": "API调用" + }, + { + "name": "Zhipu AI (GLM)", + "description": "智谱AI的GLM系列大模型,作为云端LLM选项之一", + "interaction_type": "API调用" + }, + { + "name": "Mistral AI", + "description": "Mistral平台提供的大语言模型服务", + "interaction_type": "API调用" + }, + { + "name": "OpenAI-compatible APIs", + "description": "兼容OpenAI API格式的第三方大模型服务", + "interaction_type": "API调用" + } + ], + "system_boundary": { + "scope": "全栈桌面应用程序,包含前端UI、后端服务、本地数据库及系统集成", + "included_components": [ + "Svelte前端界面", + "Tauri原生桥接层", + "Rust后端业务逻辑", + "SQLite本地数据库", + "LLM代理与适配器", + "内容抓取引擎", + "定时任务调度器", + "系统托盘与守护进程" + ], + "excluded_components": [ + "外部RSS源的内容生产", + "搜索引擎的索引构建", + "LLM模型的训练过程", + "云同步服务(当前仅支持本地存储)" + ] + }, + "confidence_score": 0.95 + }, + "timestamp": 1758806079, + "prompt_hash": "21d4878ee02b3c82a86a034c67fe3094", + "token_usage": { + "input_tokens": 15769, + "output_tokens": 994, + "total_tokens": 16763 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/86a3f8c5e4af6a75b2ca3186877a1ed7.json" "b/.litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/86a3f8c5e4af6a75b2ca3186877a1ed7.json" new file mode 100644 index 0000000..859ea68 --- /dev/null +++ "b/.litho/cache/studies_research/\351\241\271\347\233\256\346\246\202\350\247\210\350\260\203\347\240\224\346\212\245\345\221\212/86a3f8c5e4af6a75b2ca3186877a1ed7.json" @@ -0,0 +1,95 @@ +{ + "data": { + "project_name": "saga-reader", + "project_description": "一个基于Tauri框架的桌面端信息聚合与智能阅读应用,支持RSS订阅管理、网页内容抓取、本地AI模型集成(如Ollama)以及通过大语言模型对文章进行净化、优化和融合处理。", + "project_type": "FullStackApp", + "business_value": "为用户提供一站式的深度内容阅读体验,结合自动化信息聚合与AI智能处理能力,帮助用户高效获取、筛选和理解互联网上的高质量信息,提升知识吸收效率。", + "target_users": [ + { + "name": "知识工作者", + "description": "需要持续学习和跟踪行业动态的专业人士,如研究员、工程师、产品经理等。", + "needs": [ + "高效的信息源聚合", + "去除干扰内容的纯净阅读模式", + "智能摘要与内容提炼", + "本地化AI处理保障隐私" + ] + }, + { + "name": "技术爱好者", + "description": "关注前沿技术和开源项目的开发者或极客用户。", + "needs": [ + "支持自定义爬虫规则", + "可扩展的插件架构", + "本地运行的大语言模型集成", + "跨平台桌面应用体验" + ] + } + ], + "external_systems": [ + { + "name": "Ollama", + "description": "本地大语言模型运行时,用于执行文章内容的净化、优化和融合等AI任务。", + "interaction_type": "HTTP API 调用与进程控制" + }, + { + "name": "OpenAI", + "description": "云端大语言模型服务,作为可选的AI能力提供者之一。", + "interaction_type": "RESTful API 调用" + }, + { + "name": "GLM (智谱AI)", + "description": "国产大语言模型服务,支持中文语境下的智能处理。", + "interaction_type": "RESTful API 调用" + }, + { + "name": "Mistral AI", + "description": "国际先进的开源大语言模型提供商,提供高性能推理服务。", + "interaction_type": "RESTful API 调用" + }, + { + "name": "Bing Search", + "description": "用于关键词搜索的内容抓取来源之一。", + "interaction_type": "HTML 爬取与解析" + }, + { + "name": "Baidu Search", + "description": "中文搜索引擎,作为中文内容检索的主要数据源。", + "interaction_type": "HTML 爬取与解析" + }, + { + "name": "RSS Feeds", + "description": "用户订阅的各类博客、新闻网站等内容源。", + "interaction_type": "RSS XML 解析" + } + ], + "system_boundary": { + "scope": "完整的桌面端信息聚合与智能阅读系统", + "included_components": [ + "RSS订阅管理(增删改查)", + "网页内容智能抓取(支持JavaScript渲染)", + "基于LLM的文章内容处理管道(Purge, Optimize, Melt)", + "本地Ollama模型的启停与状态管理", + "多语言支持与主题切换", + "系统托盘与守护进程机制", + "前端SvelteKit界面与后端Rust逻辑的Tauri桥接" + ], + "excluded_components": [ + "第三方AI模型的训练与维护", + "搜索引擎的索引构建", + "云同步服务(当前仅支持本地存储)", + "社交分享功能", + "浏览器插件集成" + ] + }, + "confidence_score": 0.95 + }, + "timestamp": 1759024770, + "prompt_hash": "86a3f8c5e4af6a75b2ca3186877a1ed7", + "token_usage": { + "input_tokens": 15609, + "output_tokens": 1117, + "total_tokens": 16726 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/65390a58cc330d06fba7bd2cdb86164c.json" "b/.litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/65390a58cc330d06fba7bd2cdb86164c.json" new file mode 100644 index 0000000..471f002 --- /dev/null +++ "b/.litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/65390a58cc330d06fba7bd2cdb86164c.json" @@ -0,0 +1,452 @@ +{ + "data": { + "domain_modules": [ + { + "name": "用户界面域", + "description": "负责提供直观、响应式的用户交互界面,支持多语言和主题切换,实现信息的可视化展示与用户操作反馈。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "主界面布局", + "description": "实现应用的三栏式主布局结构,整合文章列表、阅读器和AI助手面板等核心组件。", + "code_paths": [ + "app/src/routes/main/+page.svelte" + ], + "key_functions": [ + "响应式布局管理", + "条件渲染控制", + "全局状态注入" + ], + "importance": 9.5 + }, + { + "name": "文章交互组件", + "description": "提供文章列表浏览、详情阅读、收藏标记等核心阅读功能的UI实现。", + "code_paths": [ + "app/src/routes/main/widgets/ArticlesList.svelte", + "app/src/routes/main/widgets/ArticleReader.svelte" + ], + "key_functions": [ + "文章列表渲染", + "滚动加载更多", + "阅读状态更新", + "内容模式切换" + ], + "importance": 9.0 + }, + { + "name": "AI助手集成", + "description": "实现与AI助手的对话交互界面,支持消息历史展示、实时回复和Markdown渲染。", + "code_paths": [ + "app/src/routes/main/widgets/AISpritePanel.svelte", + "app/src/lib/widgets/Markdown.svelte" + ], + "key_functions": [ + "对话窗口管理", + "消息流式显示", + "AI回复渲染" + ], + "importance": 8.5 + }, + { + "name": "订阅管理界面", + "description": "提供订阅源的增删改查操作界面,支持分组管理和快捷导航。", + "code_paths": [ + "app/src/routes/main/widgets/FeedsList.svelte", + "app/src/routes/feedsPackage/create_or_edit/+page.svelte" + ], + "key_functions": [ + "订阅树形展示", + "上下文菜单操作", + "虚拟Feed导航" + ], + "importance": 8.0 + } + ], + "code_paths": [ + "app/src/routes/main", + "app/src/lib/widgets" + ], + "importance": 9.0, + "complexity": 7.5 + }, + { + "name": "状态管理域", + "description": "集中管理应用的全局状态和数据流,确保各组件间的状态同步与一致性,支持响应式编程模型。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "全局状态容器", + "description": "作为应用的核心状态枢纽,整合多个子store并提供统一访问接口。", + "code_paths": [ + "app/src/routes/main/stores/index.svelte.ts" + ], + "key_functions": [ + "状态聚合", + "依赖注入", + "自动初始化" + ], + "importance": 9.5 + }, + { + "name": "异步任务追踪", + "description": "管理系统中所有异步操作的生命周期状态,为UI提供加载反馈。", + "code_paths": [ + "app/src/routes/main/stores/tasks.svelte.ts" + ], + "key_functions": [ + "任务注册", + "并发控制", + "状态派生" + ], + "importance": 8.5 + }, + { + "name": "文章状态管理", + "description": "专门管理文章列表的数据获取、分页加载和搜索过滤逻辑。", + "code_paths": [ + "app/src/routes/main/stores/articles/list/index.svelte.ts", + "app/src/routes/main/stores/articles/search/index.svelte.ts" + ], + "key_functions": [ + "数据分页", + "搜索过滤", + "下拉刷新" + ], + "importance": 8.0 + } + ], + "code_paths": [ + "app/src/routes/main/stores" + ], + "importance": 9.0, + "complexity": 8.0 + }, + { + "name": "内容处理域", + "description": "负责从多种来源获取网络内容,并利用大语言模型进行智能化处理,包括清洗、优化和融合。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "内容抓取引擎", + "description": "实现从RSS源和搜索引擎获取原始网页内容的能力。", + "code_paths": [ + "crates/scrap/src/rss/mod.rs", + "crates/scrap/src/search/bing.rs", + "crates/scrap/src/article_reader.rs" + ], + "key_functions": [ + "RSS解析", + "搜索引擎爬取", + "HTML内容提取" + ], + "importance": 9.0 + }, + { + "name": "LLM内容处理器", + "description": "利用大语言模型对文章内容进行净化、优化和熔炼等智能处理。", + "code_paths": [ + "crates/intelligent/src/article_processor/purge.rs", + "crates/intelligent/src/article_processor/optimizer.rs", + "crates/intelligent/src/article_processor/melt.rs" + ], + "key_functions": [ + "内容净化", + "语义优化", + "信息融合" + ], + "importance": 9.5 + }, + { + "name": "智能代理服务", + "description": "作为连接外部LLM服务的适配层,统一不同提供商的API差异。", + "code_paths": [ + "crates/llm/src/llm_agent.rs", + "crates/llm/src/providers/llm_openaibase_like.rs" + ], + "key_functions": [ + "请求适配", + "协议转换", + "服务路由" + ], + "importance": 8.5 + } + ], + "code_paths": [ + "crates/scrap", + "crates/intelligent", + "crates/llm" + ], + "importance": 9.5, + "complexity": 9.0 + }, + { + "name": "数据存储域", + "description": "负责应用程序的数据持久化,管理本地数据库的读写操作,确保数据的一致性和可靠性。", + "domain_type": "基础设施域", + "sub_modules": [ + { + "name": "数据库访问层", + "description": "封装对SQLite数据库的CRUD操作,提供类型安全的数据访问接口。", + "code_paths": [ + "crates/recorder/src/operator.rs", + "crates/recorder/src/entity/article_record.rs" + ], + "key_functions": [ + "实体映射", + "查询构建", + "连接池管理" + ], + "importance": 8.5 + }, + { + "name": "文章记录服务", + "description": "提供文章数据的完整业务逻辑封装,包括状态管理和全文搜索。", + "code_paths": [ + "crates/recorder/src/article_recorder_service.rs" + ], + "key_functions": [ + "生命周期管理", + "多维度查询", + "全文检索" + ], + "importance": 8.0 + } + ], + "code_paths": [ + "crates/recorder" + ], + "importance": 8.0, + "complexity": 7.0 + }, + { + "name": "系统集成域", + "description": "处理应用与操作系统及其他外部系统的集成,包括配置管理、守护进程和Tauri桥接。", + "domain_type": "工具支撑域", + "sub_modules": [ + { + "name": "启动初始化", + "description": "协调应用启动时的各项初始化任务,包括配置加载和服务准备。", + "code_paths": [ + "crates/feed_api_rs/src/startup/mod.rs", + "crates/feed_api_rs/src/startup/init_app_config.rs" + ], + "key_functions": [ + "配置初始化", + "日志系统设置", + "LLM服务检测" + ], + "importance": 8.5 + }, + { + "name": "Tauri插件桥接", + "description": "实现前端JavaScript与后端Rust代码之间的通信桥梁。", + "code_paths": [ + "crates/tauri-plugin-feed-api/src/lib.rs", + "crates/tauri-plugin-feed-api/src/commands.rs" + ], + "key_functions": [ + "命令暴露", + "状态共享", + "原生调用" + ], + "importance": 8.0 + }, + { + "name": "后台任务调度", + "description": "管理定时更新任务和守护进程,确保内容的定期同步。", + "code_paths": [ + "app/src-tauri/src/daemon/feeds_update.rs", + "app/src-tauri/src/daemon/launcher.rs" + ], + "key_functions": [ + "定时触发", + "实例互斥", + "日志监控" + ], + "importance": 7.5 + } + ], + "code_paths": [ + "crates/feed_api_rs/src/startup", + "crates/tauri-plugin-feed-api", + "app/src-tauri/src/daemon" + ], + "importance": 8.0, + "complexity": 8.5 + } + ], + "domain_relations": [ + { + "from_domain": "用户界面域", + "to_domain": "状态管理域", + "relation_type": "状态依赖", + "strength": 9.5, + "description": "UI组件通过Svelte stores从状态管理域获取数据和状态,实现响应式更新。" + }, + { + "from_domain": "用户界面域", + "to_domain": "系统集成域", + "relation_type": "功能调用", + "strength": 8.5, + "description": "前端通过Tauri插件调用后端Rust命令,执行如内容抓取、配置更新等操作。" + }, + { + "from_domain": "状态管理域", + "to_domain": "内容处理域", + "relation_type": "服务调用", + "strength": 8.0, + "description": "状态管理模块调用FeaturesAPI接口触发内容更新、文章读取等业务操作。" + }, + { + "from_domain": "内容处理域", + "to_domain": "数据存储域", + "relation_type": "数据依赖", + "strength": 9.0, + "description": "内容处理结果需要持久化到本地数据库,由文章记录服务完成存储操作。" + }, + { + "from_domain": "内容处理域", + "to_domain": "系统集成域", + "relation_type": "配置依赖", + "strength": 7.5, + "description": "LLM处理器需要读取应用配置中的模型参数和API密钥等信息。" + }, + { + "from_domain": "系统集成域", + "to_domain": "内容处理域", + "relation_type": "服务编排", + "strength": 8.5, + "description": "启动初始化流程会触发内容抓取引擎和LLM服务的准备工作。" + } + ], + "business_flows": [ + { + "name": "项目分析流程", + "description": "用户打开应用后,系统自动加载订阅源并展示最新文章列表的完整流程。", + "steps": [ + { + "step": 1, + "domain_module": "系统集成域", + "sub_module": "启动初始化", + "operation": "加载应用配置和用户配置文件", + "code_entry_point": "crates/feed_api_rs/src/startup/init_app_config.rs" + }, + { + "step": 2, + "domain_module": "系统集成域", + "sub_module": "启动初始化", + "operation": "初始化日志系统并检查LLM服务状态", + "code_entry_point": "crates/feed_api_rs/src/startup/init_logger.rs" + }, + { + "step": 3, + "domain_module": "状态管理域", + "sub_module": "全局状态容器", + "operation": "创建全局状态实例并注入子stores", + "code_entry_point": "app/src/routes/main/stores/index.svelte.ts" + }, + { + "step": 4, + "domain_module": "内容处理域", + "sub_module": "内容抓取引擎", + "operation": "调用RSS和搜索引擎API获取最新文章", + "code_entry_point": "crates/scrap/src/rss/mod.rs" + }, + { + "step": 5, + "domain_module": "内容处理域", + "sub_module": "LLM内容处理器", + "operation": "对获取的文章内容进行净化、优化和熔炼处理", + "code_entry_point": "crates/intelligent/src/article_processor/optimizer.rs" + }, + { + "step": 6, + "domain_module": "数据存储域", + "sub_module": "文章记录服务", + "operation": "将处理后的文章保存到本地数据库", + "code_entry_point": "crates/recorder/src/article_recorder_service.rs" + }, + { + "step": 7, + "domain_module": "状态管理域", + "sub_module": "文章状态管理", + "operation": "从数据库加载文章列表并更新UI状态", + "code_entry_point": "app/src/routes/main/stores/articles/list/index.svelte.ts" + }, + { + "step": 8, + "domain_module": "用户界面域", + "sub_module": "文章交互组件", + "operation": "渲染文章列表,用户可浏览和选择文章阅读", + "code_entry_point": "app/src/routes/main/widgets/ArticlesList.svelte" + } + ], + "entry_point": "用户启动应用", + "importance": 9.5, + "involved_domains_count": 5 + }, + { + "name": "代码洞察生成流程", + "description": "当用户与AI助手对话时,系统生成基于文章内容的智能回复的完整流程。", + "steps": [ + { + "step": 1, + "domain_module": "用户界面域", + "sub_module": "AI助手集成", + "operation": "捕获用户输入并发送聊天请求", + "code_entry_point": "app/src/routes/main/stores/sprite.svelte.ts" + }, + { + "step": 2, + "domain_module": "系统集成域", + "sub_module": "Tauri插件桥接", + "operation": "通过Tauri命令将请求转发至Rust后端", + "code_entry_point": "crates/tauri-plugin-feed-api/src/commands.rs" + }, + { + "step": 3, + "domain_module": "内容处理域", + "sub_module": "智能代理服务", + "operation": "构造包含文章内容和用户问题的完整提示词", + "code_entry_point": "crates/intelligent/src/article_processor/assistant.rs" + }, + { + "step": 4, + "domain_module": "内容处理域", + "sub_module": "智能代理服务", + "operation": "调用配置的LLM服务(Ollama/Mistral/GLM等)生成回复", + "code_entry_point": "crates/llm/src/llm_agent.rs" + }, + { + "step": 5, + "domain_module": "系统集成域", + "sub_module": "Tauri插件桥接", + "operation": "将生成的回复通过事件机制返回前端", + "code_entry_point": "crates/tauri-plugin-feed-api/src/lib.rs" + }, + { + "step": 6, + "domain_module": "用户界面域", + "sub_module": "AI助手集成", + "operation": "在对话面板中流式显示AI生成的回复", + "code_entry_point": "app/src/routes/main/widgets/AISpritePanel.svelte" + } + ], + "entry_point": "用户在AI精灵面板输入问题", + "importance": 9.0, + "involved_domains_count": 4 + } + ], + "architecture_summary": "采用前后端分离的桌面应用架构,前端使用Svelte框架实现响应式UI,后端采用Rust编写高性能业务逻辑。通过Tauri框架实现JS-Rust桥接,利用SeaORM进行数据库操作,并集成多种LLM服务提供商实现内容智能化处理。系统遵循清晰的分层架构,包含UI层、状态管理层、业务逻辑层、数据访问层和基础设施层。", + "confidence_score": 0.95 + }, + "timestamp": 1758807559, + "prompt_hash": "65390a58cc330d06fba7bd2cdb86164c", + "token_usage": { + "input_tokens": 28308, + "output_tokens": 4101, + "total_tokens": 32409 + }, + "model_name": null +} \ No newline at end of file diff --git "a/.litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/e58e3850ee9a8cb05d89ea5b4e6fe22a.json" "b/.litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/e58e3850ee9a8cb05d89ea5b4e6fe22a.json" new file mode 100644 index 0000000..54208e8 --- /dev/null +++ "b/.litho/cache/studies_research/\351\242\206\345\237\237\346\250\241\345\235\227\350\260\203\347\240\224\346\212\245\345\221\212/e58e3850ee9a8cb05d89ea5b4e6fe22a.json" @@ -0,0 +1,616 @@ +{ + "data": { + "domain_modules": [ + { + "name": "用户界面域", + "description": "负责应用的整体视觉呈现、用户交互和前端状态管理,为用户提供直观、响应式的操作体验。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "主页面布局", + "description": "实现应用主界面的三栏式布局结构,协调信息源列表、文章列表和内容阅读器等组件。", + "code_paths": [ + "app/src/routes/main/+page.svelte" + ], + "key_functions": [ + "初始化主状态存储", + "集成全局通知系统", + "协调多模块UI组件" + ], + "importance": 9.5 + }, + { + "name": "侧边栏导航", + "description": "提供结构化的订阅包和订阅项管理界面,支持聚合视图切换和上下文菜单操作。", + "code_paths": [ + "app/src/routes/main/widgets/FeedsList.svelte" + ], + "key_functions": [ + "渲染FeedsPackage和Feed列表", + "处理分组展开/折叠", + "提供右键上下文菜单" + ], + "importance": 8.0 + }, + { + "name": "文章列表展示", + "description": "负责文章条目的分组渲染、加载状态管理和自动标记已读等交互逻辑。", + "code_paths": [ + "app/src/routes/main/widgets/ArticlesList.svelte" + ], + "key_functions": [ + "按分组显示文章", + "实现滚动加载更多", + "自动标记阅读状态" + ], + "importance": 9.0 + }, + { + "name": "内容阅读器", + "description": "提供文章内容的多模式阅读体验,支持优化、熔炼和原始三种视图切换。", + "code_paths": [ + "app/src/routes/main/widgets/ArticleReader.svelte" + ], + "key_functions": [ + "渲染HTML或Markdown内容", + "实现标签页视图切换", + "提供外部链接打开功能" + ], + "importance": 9.5 + }, + { + "name": "AI助手面板", + "description": "实现悬浮式AI聊天界面,支持与文章内容相关的智能对话交互。", + "code_paths": [ + "app/src/routes/main/widgets/AISpritePanel.svelte" + ], + "key_functions": [ + "管理对话历史记录", + "发送消息至AI服务", + "渲染Markdown回复内容" + ], + "importance": 8.5 + } + ], + "code_paths": [ + "app/src/routes/main/+page.svelte", + "app/src/routes/main/widgets/*.svelte" + ], + "importance": 9.0, + "complexity": 7.5 + }, + { + "name": "状态管理域", + "description": "集中管理应用的全局和局部状态,确保数据一致性并驱动UI更新,是前后端交互的核心枢纽。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "集中式状态存储", + "description": "创建和整合多个子store,对外提供统一的状态访问接口,是整个应用的状态中枢。", + "code_paths": [ + "app/src/routes/main/stores/index.svelte.ts" + ], + "key_functions": [ + "整合feeds、articles、tasks等多个子store", + "管理当前feed和文章选择状态", + "调度定时内容更新任务" + ], + "importance": 10.0 + }, + { + "name": "文章状态管理", + "description": "专门管理文章列表的展示逻辑,包括分组、分页、搜索过滤和刷新操作。", + "code_paths": [ + "app/src/routes/main/stores/articles/list/index.svelte.ts" + ], + "key_functions": [ + "实现文章分组与分页", + "响应搜索条件变化", + "管理不同场景下的加载状态" + ], + "importance": 9.0 + }, + { + "name": "异步任务管理", + "description": "集中跟踪所有后台异步任务的执行状态,为用户提供可视化的进度反馈。", + "code_paths": [ + "app/src/routes/main/stores/tasks.svelte.ts" + ], + "key_functions": [ + "维护待处理任务队列", + "统一管理加载状态文本", + "提供任务添加和查询接口" + ], + "importance": 8.5 + }, + { + "name": "阅读状态管理", + "description": "管理单篇文章的阅读状态和内容刷新逻辑,支持智能去重的任务调度。", + "code_paths": [ + "app/src/routes/main/stores/reader.svelte.ts" + ], + "key_functions": [ + "标记文章为已读", + "调度增强型抓取任务", + "实现任务复用机制避免重复请求" + ], + "importance": 8.0 + }, + { + "name": "AI对话状态", + "description": "管理AI精灵对话界面的状态,包括消息历史、加载状态和可见性控制。", + "code_paths": [ + "app/src/routes/main/stores/sprite.svelte.ts" + ], + "key_functions": [ + "维护对话历史记录", + "处理用户消息发送", + "管理异步请求状态" + ], + "importance": 8.0 + } + ], + "code_paths": [ + "app/src/routes/main/stores/*.svelte.ts" + ], + "importance": 9.5, + "complexity": 8.0 + }, + { + "name": "内容获取与处理域", + "description": "负责从多种来源抓取网页内容,并通过大语言模型进行净化、优化和融合等智能处理,形成高质量的可读内容。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "RSS内容抓取", + "description": "实现标准RSS源的内容解析和正文提取,是传统信息源的主要获取方式。", + "code_paths": [ + "crates/scrap/src/rss/mod.rs" + ], + "key_functions": [ + "解析RSS XML数据", + "提取文章元信息", + "调用文章阅读器获取完整正文" + ], + "importance": 8.5 + }, + { + "name": "搜索引擎爬虫", + "description": "从Bing、百度等搜索引擎结果页抓取内容,扩展信息获取渠道。", + "code_paths": [ + "crates/scrap/src/search/bing.rs", + "crates/scrap/src/search/baidu.rs" + ], + "key_functions": [ + "发起关键词搜索请求", + "解析HTML搜索结果", + "抓取目标网页全文内容" + ], + "importance": 8.0 + }, + { + "name": "智能网页抓取", + "description": "通过Tauri Webview实现对JavaScript渲染页面的智能抓取,支持自动重定向检测。", + "code_paths": [ + "crates/scrap/src/simulator.rs", + "crates/scrap/src/article_reader.rs" + ], + "key_functions": [ + "创建隐藏Webview窗口", + "执行JavaScript提取DOM内容", + "利用LLM判断是否存在前端跳转" + ], + "importance": 9.0 + }, + { + "name": "文章内容处理管道", + "description": "构建基于LLM的文章处理流水线,依次执行净化、优化和融合操作。", + "code_paths": [ + "crates/intelligent/src/article_processor/purge.rs", + "crates/intelligent/src/article_processor/optimizer.rs", + "crates/intelligent/src/article_processor/melt.rs" + ], + "key_functions": [ + "构造LLM提示词", + "调用底层AI服务", + "串联多个处理阶段" + ], + "importance": 9.5 + } + ], + "code_paths": [ + "crates/scrap/src/*", + "crates/intelligent/src/article_processor/*" + ], + "importance": 9.5, + "complexity": 9.0 + }, + { + "name": "AI能力集成域", + "description": "封装与各种大语言模型提供商的交互逻辑,为上层应用提供统一的AI服务能力。", + "domain_type": "核心业务域", + "sub_modules": [ + { + "name": "LLM代理服务", + "description": "实现面向多种LLM提供商的代理模式,屏蔽底层接口差异,提供统一的文本生成能力。", + "code_paths": [ + "crates/llm/src/llm_agent.rs" + ], + "key_functions": [ + "根据配置动态选择服务实例", + "转发用户输入至对应提供商", + "处理不同提供商的响应格式" + ], + "importance": 9.5 + }, + { + "name": "Ollama集成", + "description": "实现对本地Ollama模型的补全服务调用,支持私有化部署的AI能力。", + "code_paths": [ + "crates/llm/src/providers/llm_ollama.rs" + ], + "key_functions": [ + "构造Ollama API请求", + "解析completion响应", + "管理模型配置" + ], + "importance": 9.0 + }, + { + "name": "OpenAI兼容接口", + "description": "实现与OpenAI风格API兼容的服务调用,支持主流云端大模型接入。", + "code_paths": [ + "crates/llm/src/providers/llm_openaibase_like.rs" + ], + "key_functions": [ + "构造OpenAI格式请求", + "解析流式响应", + "支持系统提示词配置" + ], + "importance": 8.5 + }, + { + "name": "GLM/Mistral适配", + "description": "作为适配层使系统能够以统一方式调用智谱AI和Mistral等特定厂商的模型服务。", + "code_paths": [ + "crates/llm/src/providers/llm_glm.rs", + "crates/llm/src/providers/llm_mistral.rs" + ], + "key_functions": [ + "转换GLM配置为通用格式", + "复用OpenAI兼容逻辑", + "适配特定API端点" + ], + "importance": 8.0 + } + ], + "code_paths": [ + "crates/llm/src/*" + ], + "importance": 9.0, + "complexity": 8.5 + }, + { + "name": "数据持久化域", + "description": "负责应用程序的数据存储与管理,包括用户配置、文章记录和数据库操作。", + "domain_type": "基础设施域", + "sub_modules": [ + { + "name": "文章记录服务", + "description": "封装对文章记录的各类数据访问逻辑,是连接业务逻辑与数据库的关键中介。", + "code_paths": [ + "crates/recorder/src/article_recorder_service.rs" + ], + "key_functions": [ + "插入和更新文章记录", + "按条件查询文章", + "标记已读和收藏状态" + ], + "importance": 8.5 + }, + { + "name": "数据库操作器", + "description": "使用SeaORM框架实现对SQLite数据库的访问,管理`t_article_record`表的CRUD操作。", + "code_paths": [ + "crates/recorder/src/operator.rs" + ], + "key_functions": [ + "建立数据库连接池", + "执行异步数据库操作", + "确保表结构存在" + ], + "importance": 8.0 + }, + { + "name": "数据路径管理", + "description": "封装应用程序数据存储路径的生成与管理,确保跨平台兼容性。", + "code_paths": [ + "crates/recorder/src/path.rs" + ], + "key_functions": [ + "获取标准系统路径", + "构建完整文件路径", + "自动创建缺失目录" + ], + "importance": 7.0 + } + ], + "code_paths": [ + "crates/recorder/src/*" + ], + "importance": 8.0, + "complexity": 7.0 + }, + { + "name": "系统启动与配置域", + "description": "负责应用程序的初始化流程、配置管理和生命周期控制,确保系统稳定运行。", + "domain_type": "基础设施域", + "sub_modules": [ + { + "name": "启动流程管理", + "description": "作为应用启动中枢,采用分阶段策略进行初始化,提升启动效率。", + "code_paths": [ + "crates/feed_api_rs/src/startup/mod.rs" + ], + "key_functions": [ + "同步初始化关键配置", + "并行加载用户配置与LLM依赖", + "实现错误聚合处理" + ], + "importance": 9.0 + }, + { + "name": "应用配置管理", + "description": "加载或创建默认的应用配置,支持运行时动态保存配置实现持久化。", + "code_paths": [ + "crates/feed_api_rs/src/startup/init_app_config.rs" + ], + "key_functions": [ + "读取TOML格式配置文件", + "生成默认配置对象", + "同步配置到磁盘" + ], + "importance": 8.5 + }, + { + "name": "用户配置管理", + "description": "在应用启动时初始化用户个人资料,为新用户提供引导体验。", + "code_paths": [ + "crates/feed_api_rs/src/startup/init_user_profile.rs" + ], + "key_functions": [ + "读取user_config.toml文件", + "生成默认用户配置", + "持久化到磁盘" + ], + "importance": 8.0 + }, + { + "name": "日志系统", + "description": "初始化应用程序的日志系统,根据配置决定输出位置和格式。", + "code_paths": [ + "crates/feed_api_rs/src/startup/init_logger.rs" + ], + "key_functions": [ + "配置全局日志行为", + "实现按天轮转的日志写入", + "设置可读的日志格式" + ], + "importance": 7.5 + }, + { + "name": "LLM运行时管理", + "description": "在应用启动时初始化指定的大型语言模型提供程序,如唤醒Ollama服务。", + "code_paths": [ + "crates/feed_api_rs/src/startup/init_llm.rs" + ], + "key_functions": [ + "检查LLM安装状态", + "尝试唤醒未运行的服务", + "执行空初始化保持流程一致" + ], + "importance": 8.5 + } + ], + "code_paths": [ + "crates/feed_api_rs/src/startup/*" + ], + "importance": 8.5, + "complexity": 7.5 + } + ], + "domain_relations": [ + { + "from_domain": "用户界面域", + "to_domain": "状态管理域", + "relation_type": "状态依赖", + "strength": 10.0, + "description": "用户界面域的所有组件都依赖于状态管理域提供的store来获取数据和触发状态变更。" + }, + { + "from_domain": "用户界面域", + "to_domain": "内容获取与处理域", + "relation_type": "功能调用", + "strength": 8.0, + "description": "UI组件通过hybrid-apis间接调用内容获取与处理域的功能,如刷新文章内容。" + }, + { + "from_domain": "用户界面域", + "to_domain": "AI能力集成域", + "relation_type": "服务调用", + "strength": 7.0, + "description": "AI助手面板直接与AI能力集成域交互,发送消息并接收回复。" + }, + { + "from_domain": "状态管理域", + "to_domain": "内容获取与处理域", + "relation_type": "数据流", + "strength": 9.0, + "description": "状态管理域中的stores调用内容获取与处理域的API来获取最新内容并更新状态。" + }, + { + "from_domain": "状态管理域", + "to_domain": "数据持久化域", + "relation_type": "数据依赖", + "strength": 8.5, + "description": "状态管理需要从数据持久化域读取初始数据,并将变更持久化回数据库。" + }, + { + "from_domain": "内容获取与处理域", + "to_domain": "AI能力集成域", + "relation_type": "服务依赖", + "strength": 10.0, + "description": "文章内容处理管道必须依赖AI能力集成域提供的LLM服务来完成净化、优化和融合操作。" + }, + { + "from_domain": "内容获取与处理域", + "to_domain": "数据持久化域", + "relation_type": "数据写入", + "strength": 9.0, + "description": "处理完成后的内容需要持久化到数据库中,供后续读取和展示。" + }, + { + "from_domain": "AI能力集成域", + "to_domain": "系统启动与配置域", + "relation_type": "配置依赖", + "strength": 8.0, + "description": "LLM服务的初始化和配置需要依赖系统启动时加载的应用配置。" + }, + { + "from_domain": "数据持久化域", + "to_domain": "系统启动与配置域", + "relation_type": "路径依赖", + "strength": 7.0, + "description": "数据库操作需要使用系统启动与配置域提供的数据存储路径。" + } + ], + "business_flows": [ + { + "name": "项目分析流程", + "description": "用户启动应用后,系统自动加载配置、初始化状态并展示主界面的过程。", + "steps": [ + { + "step": 1, + "domain_module": "系统启动与配置域", + "sub_module": "启动流程管理", + "operation": "执行分阶段初始化:先同步初始化配置和日志,再并行加载用户配置与LLM服务", + "code_entry_point": "crates/feed_api_rs/src/startup/mod.rs" + }, + { + "step": 2, + "domain_module": "系统启动与配置域", + "sub_module": "应用配置管理", + "operation": "尝试从磁盘读取app_config.toml,若不存在则创建默认配置并持久化", + "code_entry_point": "crates/feed_api_rs/src/startup/init_app_config.rs" + }, + { + "step": 3, + "domain_module": "系统启动与配置域", + "sub_module": "用户配置管理", + "operation": "尝试读取user_config.toml,若为新用户则生成包含预设订阅包的默认配置", + "code_entry_point": "crates/feed_api_rs/src/startup/init_user_profile.rs" + }, + { + "step": 4, + "domain_module": "系统启动与配置域", + "sub_module": "LLM运行时管理", + "operation": "检查Ollama服务状态,若已安装但未运行则尝试唤醒服务", + "code_entry_point": "crates/feed_api_rs/src/startup/init_llm.rs" + }, + { + "step": 5, + "domain_module": "状态管理域", + "sub_module": "集中式状态存储", + "operation": "创建主状态store,整合feeds、articles、tasks等子模块", + "code_entry_point": "app/src/routes/main/stores/index.svelte.ts" + }, + { + "step": 6, + "domain_module": "用户界面域", + "sub_module": "主页面布局", + "operation": "渲染主界面三栏布局,绑定各组件到对应的状态store", + "code_entry_point": "app/src/routes/main/+page.svelte" + } + ], + "entry_point": "app/src-tauri/src/main.rs", + "importance": 9.0, + "involved_domains_count": 4 + }, + { + "name": "代码洞察生成流程", + "description": "当用户点击某篇文章时,系统通过AI模型生成内容摘要和洞察的完整流程。", + "steps": [ + { + "step": 1, + "domain_module": "用户界面域", + "sub_module": "文章列表展示", + "operation": "捕获用户点击事件,获取被点击文章的ID", + "code_entry_point": "app/src/routes/main/widgets/ArticlesList.svelte" + }, + { + "step": 2, + "domain_module": "状态管理域", + "sub_module": "文章状态管理", + "operation": "根据文章ID查询详细内容,并更新当前选中文章状态", + "code_entry_point": "app/src/routes/main/stores/articles/list/index.svelte.ts" + }, + { + "step": 3, + "domain_module": "内容获取与处理域", + "sub_module": "文章内容处理管道", + "operation": "启动LLM处理流水线,依次执行Purge(净化)、Optimize(优化)、Melt(融合)操作", + "code_entry_point": "crates/intelligent/src/article_processor/*" + }, + { + "step": 4, + "domain_module": "AI能力集成域", + "sub_module": "LLM代理服务", + "operation": "根据配置选择具体的LLM提供商(如Ollama、OpenAI),发送处理请求", + "code_entry_point": "crates/llm/src/llm_agent.rs" + }, + { + "step": 5, + "domain_module": "AI能力集成域", + "sub_module": "Ollama集成", + "operation": "向本地Ollama服务发送POST请求,执行文本生成任务", + "code_entry_point": "crates/llm/src/providers/llm_ollama.rs" + }, + { + "step": 6, + "domain_module": "内容获取与处理域", + "sub_module": "文章内容处理管道", + "operation": "接收LLM返回的处理结果,更新文章的优化后和熔炼后内容字段", + "code_entry_point": "crates/intelligent/src/article_processor/llm_processor.rs" + }, + { + "step": 7, + "domain_module": "数据持久化域", + "sub_module": "文章记录服务", + "operation": "将处理后的文章内容更新到数据库中", + "code_entry_point": "crates/recorder/src/article_recorder_service.rs" + }, + { + "step": 8, + "domain_module": "用户界面域", + "sub_module": "内容阅读器", + "operation": "重新渲染文章阅读器,展示新的优化和熔炼内容", + "code_entry_point": "app/src/routes/main/widgets/ArticleReader.svelte" + } + ], + "entry_point": "用户点击文章条目", + "importance": 9.5, + "involved_domains_count": 4 + } + ], + "architecture_summary": "系统采用分层架构设计,前端基于SvelteKit构建响应式UI,通过Tauri桥接Rust后端。核心业务逻辑分布在内容获取与处理、AI能力集成等领域,由状态管理域统一协调。数据持久化基于SeaORM操作SQLite数据库。整体架构清晰分离关注点,支持本地AI模型集成和多源内容抓取。", + "confidence_score": 9.0 + }, + "timestamp": 1759024866, + "prompt_hash": "e58e3850ee9a8cb05d89ea5b4e6fe22a", + "token_usage": { + "input_tokens": 28201, + "output_tokens": 6217, + "total_tokens": 34418 + }, + "model_name": null +} \ No newline at end of file diff --git "a/litho.docs/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" "b/litho.docs/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" new file mode 100644 index 0000000..43028a3 --- /dev/null +++ "b/litho.docs/1\343\200\201\351\241\271\347\233\256\346\246\202\350\277\260.md" @@ -0,0 +1,296 @@ +# 项目概述 + +## 1. 系统概览 + +### 1.1 项目简介 +**项目名称**:`saga-reader` +**项目类型**:全栈桌面端信息聚合与智能阅读应用(FullStack Desktop App) +**核心定位**:为知识工作者和技术爱好者提供一站式的深度内容获取、净化与理解平台,融合自动化信息抓取与本地/云端大语言模型能力,打造高效、私密且智能化的阅读体验。 + +`saga-reader` 是一个基于 **Tauri + SvelteKit + Rust** 技术栈构建的跨平台桌面应用程序。它通过集成 RSS 订阅、搜索引擎爬虫和 JavaScript 渲染网页抓取技术,从多种来源聚合互联网上的高质量内容,并利用大语言模型(LLM)对文章进行“净化 → 优化 → 融合”三级处理,帮助用户去除噪音、提炼要点并生成洞察性摘要。 + +该系统强调**本地化 AI 处理能力**,支持 Ollama 等本地 LLM 运行时,保障用户数据隐私;同时兼容 OpenAI、GLM、Mistral 等主流云服务,实现灵活可扩展的智能处理架构。 + +--- + +### 1.2 核心功能与业务价值 + +| 功能模块 | 描述 | 业务价值 | +|--------|------|---------| +| **多源内容聚合** | 支持 RSS Feed、Bing/Baidu 搜索结果页的内容抓取 | 打破信息孤岛,统一管理分散的知识源 | +| **智能内容提取** | 使用 Tauri Webview 实现 JS 渲染页面抓取,自动识别跳转逻辑 | 提升复杂网页的解析成功率,确保内容完整性 | +| **AI 内容处理管道** | 构建 Purge(去噪)、Optimize(润色)、Melt(融合)三阶段 LLM 流水线 | 将原始文本转化为结构清晰、重点突出的可读内容 | +| **本地 LLM 集成** | 内置对 Ollama 的启停控制与调用接口,支持离线运行 | 保护敏感信息不外泄,满足高隐私需求场景 | +| **统一 AI 接口抽象** | 通过 LLM Agent 层屏蔽不同提供商(OpenAI/GLM/Mistral)的差异 | 用户可自由切换模型服务商,提升系统灵活性 | +| **状态驱动 UI 架构** | 基于 Svelte stores 实现集中式状态管理,驱动界面响应式更新 | 提供流畅一致的交互体验,降低前端复杂度 | + +> ✅ **关键优势总结**: +- **隐私优先**:默认使用本地模型处理敏感内容 +- **智能增强**:AI 不仅用于摘要,更参与全文重构与语义融合 +- **开箱即用**:新用户自动加载预设订阅包,降低上手门槛 +- **极客友好**:支持自定义规则、插件扩展与多模型配置 + +--- + +### 1.3 技术特征概述 + +| 维度 | 技术选型 | 说明 | +|------|--------|------| +| **前端框架** | SvelteKit | 轻量级、高性能的现代前端框架,适合构建桌面级单页应用 | +| **后端逻辑** | Rust (via Tauri) | 利用内存安全与并发性能优势处理爬虫、AI 调用等重负载任务 | +| **UI 构建** | Tailwind CSS + Svelte Svelte Components | 快速构建美观、响应式的三栏布局界面 | +| **状态管理** | Svelte Stores | 集中式 store 管理 feeds、articles、tasks 等全局状态 | +| **数据持久化** | SQLite + SeaORM | 轻量嵌入式数据库,适用于本地存储文章记录与用户配置 | +| **AI 集成方式** | RESTful API / HTTP + 进程控制 | 对接 Ollama(本地)、OpenAI、GLM、Mistral 等多种 LLM 提供商 | +| **构建工具链** | Vite + Bun + Cargo | 高效开发构建流程,支持热重载与快速编译 | + +--- + +## 2. 目标用户 + +### 2.1 用户角色定义 + +#### 👤 知识工作者(Knowledge Workers) +- **典型人群**:研究员、产品经理、工程师、分析师 +- **核心诉求**: + - 高效跟踪行业动态与技术趋势 + - 快速筛选出有价值的信息片段 + - 在不泄露工作相关内容的前提下完成内容提炼 + - 获取去除广告、导航栏等干扰元素的纯净阅读视图 + +#### 🧪 技术爱好者(Tech Enthusiasts / Developers) +- **典型人群**:开发者、极客、开源贡献者 +- **核心诉求**: + - 可控性强:希望了解并干预内容抓取与 AI 处理过程 + - 支持本地部署的大模型(如 Ollama),避免依赖云服务 + - 具备插件化或脚本化扩展能力 + - 跨平台运行(Windows/macOS/Linux) + +--- + +### 2.2 使用场景描述 + +| 场景 | 描述 | +|------|------| +| **每日晨读模式** | 用户启动应用后,系统自动刷新所有订阅源,展示最新文章列表,点击即可查看 AI 生成的优化版内容 | +| **专题研究模式** | 用户输入关键词,系统通过 Bing/Baidu 搜索获取相关网页,批量抓取并调用 LLM 进行“熔炼”处理,形成综述报告 | +| **离线学习模式** | 用户在无网络环境下打开已缓存的文章,仍可通过本地 Ollama 模型重新生成摘要或提问 | +| **AI 对话辅助阅读** | 在阅读器中激活悬浮 AI 助手面板,针对当前文章提出问题,获得上下文感知的回答 | + +--- + +## 3. 系统边界 + +### 3.1 系统范围定义 +`saga-reader` 是一个完整的**桌面端信息聚合与智能阅读系统**,涵盖从内容采集、AI 处理到用户交互的全流程闭环。 + +#### ✅ 包含的核心组件: + +| 组件类别 | 具体功能 | +|--------|--------| +| **内容获取层** | +| - RSS 解析引擎 | 解析标准 RSS/XML 源,提取标题、链接、发布时间等元信息 | +| - 搜索引擎爬虫 | 从 Bing 和 Baidu 结果页提取目标 URL 并抓取正文 | +| - 智能网页抓取器 | 借助 Tauri Webview 执行 JS 渲染后的 DOM 提取,支持 SPA 页面 | +| **AI 处理层** | +| - 文章处理流水线 | Purge → Optimize → Melt 三阶段处理管道 | +| - LLM 代理服务 | 统一调度本地(Ollama)与云端(OpenAI/GLM/Mistral)模型 | +| - 提示词工程管理 | 内置结构化 prompt 模板库,支持动态注入上下文 | +| **状态与数据层** | +| - 集中式状态存储 | 基于 Svelte stores 管理 feed、article、task 状态 | +| - 数据持久化服务 | 使用 SeaORM 操作 SQLite 存储文章记录与用户配置 | +| - 数据路径管理 | 自动创建 `~/.saga-reader` 目录存放配置与数据库文件 | +| **系统基础设施** | +| - 启动流程控制器 | 分阶段初始化配置、日志、用户档案与 LLM 服务 | +| - 日志系统 | 按天轮转的日志输出,便于调试与监控 | +| - 托盘守护进程 | 应用最小化至系统托盘,保持后台任务运行 | + +--- + +#### ❌ 明确排除的外部依赖与功能: + +| 排除项 | 原因说明 | +|-------|----------| +| 第三方 AI 模型的训练与维护 | 仅作为推理客户端使用,不涉及模型训练 | +| 搜索引擎的索引构建 | 不建立自己的搜索引擎,仅消费现有搜索结果 | +| 云同步服务 | 当前版本仅支持本地存储,未实现账户体系或多设备同步 | +| 社交分享功能 | 不提供一键分享至微博、微信、Twitter 等社交平台 | +| 浏览器插件集成 | 不提供 Chrome/Firefox 插件用于网页收藏或划词翻译 | + +> ⚠️ **边界说明**:本系统聚焦于“**个人知识流的终端处理环节**”,而非内容生产、分发或社交传播。其设计哲学是“**把互联网变成你的私人图书馆**”。 + +--- + +## 4. 外部系统交互 + +### 4.1 外部系统列表及交互方式 + +| 外部系统 | 作用描述 | 交互方式 | 安全性考虑 | +|--------|--------|--------|-----------| +| **Ollama** | 本地大语言模型运行时,执行文章净化、优化、融合等任务 | HTTP API 调用 + 进程启停控制 | 数据不出本地,完全私有化处理 | +| **OpenAI** | 云端通用大模型服务(如 GPT-4),作为可选 AI 引擎 | RESTful API 调用(兼容 OpenAI 格式) | 需用户自行配置 API Key,敏感内容建议禁用 | +| **GLM (智谱AI)** | 国产中文大模型,擅长处理中文语境下的语义理解与生成 | RESTful API 调用 | 支持国产替代方案,符合信创要求 | +| **Mistral AI** | 国际先进开源模型提供商,提供高性能推理服务 | RESTful API 调用 | 支持前沿模型接入,提升处理质量 | +| **Bing Search** | 英文内容检索的主要来源之一 | HTML 爬取 + CSS 选择器解析 | 遵守 robots.txt,限制请求频率 | +| **Baidu Search** | 中文搜索引擎,用于获取中文优质内容 | HTML 爬取 + 动态渲染检测 | 防止被反爬机制封禁 | +| **RSS Feeds** | 用户订阅的技术博客、新闻站点等内容源 | RSS XML 解析 | 支持 Atom、JSON Feed 等变体格式 | + +--- + +### 4.2 依赖关系分析 + +```mermaid +graph TD + subgraph ExternalSystems [外部系统] + A[Ollama] -->|HTTP API| saga-reader + B[OpenAI] -->|REST API| saga-reader + C[GLM] -->|REST API| saga-reader + D[Mistral AI] -->|REST API| saga-reader + E[Bing Search] -->|HTML Scraping| saga-reader + F[Baidu Search] -->|HTML Scraping| saga-reader + G[RSS Feeds] -->|XML Parsing| saga-reader + end + + subgraph InternalSystem [saga-reader] + H[内容获取与处理域] --> I[AI能力集成域] + I --> J[数据持久化域] + K[状态管理域] --> H + K --> J + L[用户界面域] --> K + M[系统启动与配置域] --> I + M --> J + end + + style ExternalSystems fill:#f9f,stroke:#333,stroke-width:1px + style InternalSystem fill:#bbf,stroke:#333,stroke-width:2px +``` + +> 🔗 **关键交互路径说明**: +- **内容获取 → AI处理 → 持久化**:抓取的文章经由 `ArticleProcessor` 调用 `LLMAgent` 发送到指定模型,处理结果写回数据库。 +- **UI ↔ 状态管理**:前端组件通过 Svelte stores 订阅数据变化,实现响应式更新。 +- **启动流程协调**:`init_app_config.rs` 和 `init_user_profile.rs` 在启动时加载配置,`init_llm.rs` 尝试唤醒 Ollama 服务。 + +--- + +## 5. 系统上下文图(C4 Model - System Context) + +```mermaid +C4Context + title 系统上下文图:saga-reader + + Person_Ext(knowledge_worker, "知识工作者", "需要持续学习的专业人士,如研究员、PM、工程师") + Person_Ext(tech_enthusiast, "技术爱好者", "关注前沿技术的开发者或极客用户") + + System(saga_reader, "saga-reader", "基于Tauri的桌面端信息聚合与智能阅读应用") + + Rel(knowledge_worker, saga_reader, "使用") + Rel(tech_enthusiast, saga_reader, "使用") + + System_Ext(ollama, "Ollama", "本地大语言模型运行时") + System_Ext(openai, "OpenAI", "云端大语言模型服务") + System_Ext(glm, "GLM (智谱AI)", "国产大语言模型服务") + System_Ext(mistral, "Mistral AI", "国际开源大模型服务") + System_Ext(bing, "Bing Search", "英文搜索引擎内容源") + System_Ext(baidu, "Baidu Search", "中文搜索引擎内容源") + System_Ext(rss, "RSS Feeds", "用户订阅的内容源") + + Rel(saga_reader, ollama, "HTTP API 调用\n启动/停止服务") + Rel(saga_reader, openai, "RESTful API 调用") + Rel(saga_reader, glm, "RESTful API 调用") + Rel(saga_reader, mistral, "RESTful API 调用") + Rel(saga_reader, bing, "HTML 爬取与解析") + Rel(saga_reader, baidu, "HTML 爬取与解析") + Rel(saga_reader, rss, "RSS XML 解析") + + UpdateLayoutConfig($c4DiagramType,"NeuralGrid") +``` + +> 📌 **图表说明**: +- 本图为 C4 模型的第一层级 —— **System Context Diagram** +- 展示了 `saga-reader` 作为一个独立系统,与其用户和外部依赖之间的关系 +- 所有外部系统均标记为 `System_Ext`,表示不属于本项目控制范围 +- 用户角色分为两类,体现不同的使用动机与需求层次 + +--- + +## 6. 技术架构概览 + +### 6.1 主要技术栈 + +| 层级 | 技术 | 用途 | +|------|------|------| +| **前端 UI** | SvelteKit, Tailwind CSS, Vite | 构建现代化响应式界面 | +| **前端状态** | Svelte Stores | 全局状态管理,驱动 UI 更新 | +| **桥接层** | Tauri | 安全地将前端与 Rust 后端连接 | +| **后端逻辑** | Rust (async/.await) | 高性能异步任务处理(爬虫、AI 调用) | +| **数据访问** | SeaORM + SQLite | 类型安全的 ORM 操作本地数据库 | +| **AI 集成** | reqwest, serde_json, tokio | 发起 HTTP 请求并与 LLM 交互 | +| **构建工具** | Bun, Vite, Cargo | 开发服务器、打包与发布 | + +--- + +### 6.2 架构模式 + +#### 分层架构设计(Layered Architecture) + +```text ++----------------------------+ +| 用户界面域 | ← Svelte 组件 + Stores ++----------------------------+ + ↓ ++----------------------------+ +| 状态管理域 | ← 集中式 Store 协调数据流 ++----------------------------+ + ↓ ++----------------------------+ +| 内容获取与处理域 | ← RSS/爬虫 + LLM 处理管道 ++----------------------------+ + ↓ ++----------------------------+ +| AI能力集成域 | ← LLM Agent + Provider 适配器 ++----------------------------+ + ↓ ++----------------------------+ +| 数据持久化域 | ← SeaORM + SQLite ++----------------------------+ + ↓ ++----------------------------+ +| 系统启动与配置域 | ← 初始化流程 + 日志 + 路径管理 ++----------------------------+ +``` + +> ✅ **各层职责分明**: +- 上层依赖下层服务,但不直接越级调用 +- 状态管理作为“中枢神经”,串联 UI 与业务逻辑 +- AI 能力以“服务”形式被内容处理模块调用 + +--- + +### 6.3 关键设计决策 + +| 决策 | 说明 | 影响 | +|------|------|------| +| **采用 Tauri 而非 Electron** | 减少资源占用,提升安全性,Rust 后端更适合系统级操作 | 更轻量、更快启动、更低功耗 | +| **Svelte Stores 集中式管理** | 避免 prop drilling,统一状态变更入口 | 提高可维护性,便于调试 | +| **LLM 代理模式(LLM Agent)** | 抽象不同提供商接口,支持运行时切换 | 提升可扩展性,降低耦合度 | +| **本地优先的数据策略** | 所有数据默认保存在本地 SQLite 中 | 无需联网也可使用,保障隐私 | +| **分阶段启动流程** | 先初始化配置,再并行加载用户数据与 LLM 服务 | 缩短冷启动时间,提升用户体验 | + +--- + +### 6.4 架构洞察与未来演进建议 + +| 方向 | 当前状态 | 建议 | +|------|----------|------| +| **可扩展性** | 已预留插件机制接口(`crates/tauri-plugin-feed-api`) | 可引入插件市场,支持自定义抓取规则或 AI 模型封装 | +| **多端同步** | 仅本地存储 | 可在未来引入加密云同步(如 Dropbox/SyncThing 集成) | +| **AI 工作流编排** | 固定三段式流水线 | 可发展为可视化 AI 工作流编辑器,支持条件分支与循环 | +| **性能监控** | 基础日志记录 | 建议增加处理延迟、API 成本统计等可观测性指标 | + +--- + +## 总结 + +`saga-reader` 是一个定位清晰、架构合理、技术先进的智能阅读工具。它成功地将 **信息聚合、内容清洗、AI 增强与本地隐私保护** 四大要素融合在一起,为目标用户提供了真正有价值的生产力解决方案。 + +通过本次 C4 System Context 分析,我们明确了系统的边界、用户画像、外部依赖和技术架构,为后续的详细设计(Container、Component、Code 层级)奠定了坚实基础。该文档可作为产品、研发与架构团队共同协作的权威参考依据。 \ No newline at end of file diff --git "a/litho.docs/2\343\200\201\346\236\266\346\236\204\346\246\202\350\247\210.md" "b/litho.docs/2\343\200\201\346\236\266\346\236\204\346\246\202\350\247\210.md" new file mode 100644 index 0000000..57ea4b4 --- /dev/null +++ "b/litho.docs/2\343\200\201\346\236\266\346\236\204\346\246\202\350\247\210.md" @@ -0,0 +1,3 @@ +ReAct Agent因达到最大迭代次数而被中断,未能获得完整响应。 + +[注意: 因达到最大迭代次数(15)而被中断] \ No newline at end of file diff --git "a/litho.docs/3\343\200\201\345\267\245\344\275\234\346\265\201\347\250\213.md" "b/litho.docs/3\343\200\201\345\267\245\344\275\234\346\265\201\347\250\213.md" new file mode 100644 index 0000000..6fde94b --- /dev/null +++ "b/litho.docs/3\343\200\201\345\267\245\344\275\234\346\265\201\347\250\213.md" @@ -0,0 +1,434 @@ +# 核心工作流程 + +## 1. 工作流程概览 (Workflow Overview) + +### 系统主干工作流程 +本系统 `saga-reader` 是一个基于 Tauri 框架的桌面端信息聚合与智能阅读应用,其核心价值在于将原始网页内容通过 AI 驱动的处理管道转化为结构化、高质量的知识内容。整个系统的主干工作流程围绕“**内容获取 → 智能处理 → 用户呈现**”这一主线展开。 + +用户在界面上选择一篇文章后,系统会判断是否已有缓存内容。若无,则启动从 RSS/搜索引擎/直接 URL 的抓取流程;若有,则加载本地数据库中的记录。随后,无论新旧内容,都会进入由 **Purge(净化)→ Optimize(优化)→ Melt(融合)** 构成的三阶段 LLM 处理流水线。最终结果被持久化并展示给用户,支持多模式阅读和 AI 对话交互。 + +该流程贯穿了前端 UI 层、状态管理层、Rust 后端业务逻辑层、AI 能力集成层以及数据持久化层,体现了典型的前后端协同架构特征。 + +--- + +### 核心执行路径 +``` +[用户点击文章] + ↓ +[检查本地是否存在已处理内容] + ↓ + 是 ──→ [加载数据库中已存档内容] + 否 ──→ [启动内容抓取:RSS / Search / Direct URL] + ↓ +[提取正文文本(含 JavaScript 渲染页面智能解析)] + ↓ +[LLM 处理管道:Purge → Optimize → Melt] + ↓ +[更新或插入数据库记录] + ↓ +[前端渲染优化后内容] + ↓ +[用户获得智能阅读体验] +``` + +此路径是系统最核心的价值交付链路,实现了从噪声繁杂的互联网信息到可读性强、洞察深刻的知识产品的转化。 + +--- + +### 关键流程节点 +| 节点 | 描述 | 所属模块 | +|------|------|---------| +| **内容抓取触发** | 用户操作或定时任务触发对订阅源的内容更新 | 内容获取与处理域 | +| **正文提取** | 使用 HTML 解析器 + Webview 模拟 + LLM 判断跳转,确保准确提取正文 | 智能网页抓取子模块 | +| **Purge 阶段** | 去除 HTML/CSS/JS 及无关元素,保留核心图文内容,输出 Markdown | 文章内容处理管道 | +| **Optimize 阶段** | 将 Purge 输出重构为现代 HTML 片段,增强可读性与视觉表达 | 文章内容处理管道 | +| **Melt 阶段** | 提炼关键信息、生成摘要、提出建议,形成深度洞察 | 文章内容处理管道 | +| **状态同步** | 前端 Store 监听变化并驱动 UI 更新 | 状态管理域 | +| **异常检测** | 若任一阶段返回 `QINO-AGENTIC-EXECUTION-FAILURE`,中断流程并上报错误 | 异常处理机制 | + +--- + +### 流程协调机制 +系统采用 **集中式状态管理 + 分布式异步服务调用** 的协调模式: + +- **前端协调**:通过 Svelte 的 `$state`, `$derived`, `$effect` 实现响应式状态流,所有 UI 组件绑定至统一的 `createStore`。 +- **跨层通信**:Tauri 插件桥接前端与 Rust 后端,暴露 `#[tauri::command]` 接口供 JS 安全调用本地能力。 +- **服务调度**:使用 `Arc>` 包裹共享资源(如 `FeaturesAPIImpl`),保证多命令并发访问下的线程安全。 +- **任务队列**:`tasks.svelte.ts` 统一管理所有异步任务的状态(加载中、完成、失败),并通过底部 Footer 可视化反馈。 +- **去重控制**:`reader.svelte.ts` 中的 `refreshByEnhancedScraper` 方法实现任务复用机制,避免重复请求。 + +--- + +## 2. 主要工作流程 (Main Workflows) + +### 2.1 文章智能处理与阅读流程(核心业务流程) + +#### 流程图(Mermaid) +```mermaid +graph TD + A[用户点击文章] --> B{文章内容是否存在} + B -->|否| C[启动内容抓取] + C --> D[RSS/搜索/直接URL抓取] + D --> E[提取正文文本] + B -->|是| F[加载已存档内容] + E --> G[LLM净化: 去除噪音] + F --> G + G --> H[LLM优化: 结构化摘要] + H --> I[LLM融合: 深度洞察生成] + I --> J[更新数据库] + J --> K[前端展示优化后内容] + K --> L[用户获得智能阅读体验] +``` + +#### 技术流程说明 +1. **输入来源**: + - 来自 RSS Feed(`crates/scrap/src/rss/mod.rs`) + - 来自搜索引擎(Bing/Baidu,`crates/scrap/src/search/*`) + - 来自直接 URL 输入(Webview 模拟加载) + +2. **正文提取策略**: + - 对静态页面:使用 `scraper` 库解析 HTML,过滤 ` + +
+ + + + + + + +
+ {#if mainStore.currentArticle} + + {:else} + + {/if} +
+ + +
+ + + +
+``` + +#### 关键特性 +- 使用 `$state()` 创建响应式变量 +- 通过 props 向子组件传递 store 实例和回调函数 +- 实现跨模块状态同步机制 +- 集成全局 Toaster 通知系统 + +--- + +### 3.2 侧边栏导航 (`FeedsList.svelte`) + +#### 功能描述 +提供结构化的订阅包和订阅项管理界面,支持聚合视图切换和上下文菜单操作。 + +#### 技术实现 +```svelte + + +{#snippet listSection(text: string)} +
{text}
+{/snippet} + +{#snippet listItem(text: string, IconRender, onclick, stateSelected, menus)} + + {#if menus && menus.length !== 0} + + {@render listItemInner(text, IconRender, stateSelected)} + + {:else} + {@render listItemInner(text, IconRender, stateSelected)} + {/if} + +{/snippet} +``` + +#### 关键特性 +- 支持分组展开/折叠 +- 提供右键上下文菜单 +- 实现动态菜单创建 +- 使用 i18n 国际化文本 + +--- + +### 3.3 文章列表展示 (`ArticlesList.svelte`) + +#### 功能描述 +负责文章条目的分组渲染、加载状态管理和自动标记已读等交互逻辑。 + +#### 技术实现 +```svelte + + +{#if articles_init_loading.status === Status.Loading} + +{:else if store.articles_init_loading.status === Status.Completed} + {@render render_articles_list(isFilterActived ? store.filteredArticles : store.groupedArticles)} +{/if} + +{#snippet render_articles_list(groups: ArticlesGroup[])} +
+ {#each groups as { name, articles } (name)} +
{name}
+ {#each articles as article (article.id)} + onArticlePressed(article)}> + {#if !article.has_read && selectedArticle?.id !== article.id} +
+ {/if} +
+
{article.title}
+

+ {article.head_read} +

+
+
+ {/each} + {/each} + + {#if !isFilterActived} + {#if store.groupedArticles.length !== 0} +
+ {#if articles_continous_loading.status === Status.Completed} + + {:else} + + {/if} + {/if} + {/if} +
+{/snippet} +``` + +#### 关键特性 +- 按日期分组显示文章 +- 实现滚动加载更多 +- 自动标记阅读状态 +- 支持搜索过滤 +- 显示加载进度指示器 + +--- + +### 3.4 内容阅读器 (`ArticleReader.svelte`) + +#### 功能描述 +提供文章内容的多模式阅读体验,支持优化、熔炼和原始三种视图切换。 + +#### 技术实现 +```svelte + + + (group = e.value as ArticleReadMode)}> + {#snippet list()} + + + {`${$_('reader.tab_optimized_content')}`}       + + + + {`${$_('reader.tab_melted_content')}`}       + + + + {`${$_('reader.tab_melted_original')}`}       + + {/snippet} + + {#snippet content()} + {#if article} + + {#key `optimized-${article.id}-${articleUpdatedSeq}`} + + {/key} + + + {#key `melted-${article.id}-${articleUpdatedSeq}`} + + {/key} + + + + + {/if} + {/snippet} + +``` + +#### 关键特性 +- 三标签页视图切换(优化/熔炼/原始) +- 使用 `{#key}` 指令强制重新渲染 +- 支持外部链接打开 +- 可复制文章链接 +- 收藏/取消收藏功能 +- "R"按钮触发增强型抓取 + +--- + +### 3.5 AI助手面板 (`AISpritePanel.svelte`) + +#### 功能描述 +实现悬浮式 AI 聊天界面,支持与当前文章内容相关的智能对话交互。 + +#### 技术实现 +```svelte + + +{#if store.opened} +
+
+

{$_('aisprite.label')}

+ +
+ +
+ {#each store.history as bubble (bubble.created_at)} + {#if bubble.role !== 'user'} +
+ + + +
+
+

Copilot

+ {toDateText(bubble.created_at).toLocaleString()} +
+ +
+
+ {:else} +
+
+
+

{$_('aisprite.chat_me')}

+ {toDateText(bubble.created_at).toLocaleString()} +
+ +
+ + + +
+ {/if} + {/each} + + {#if store.isLoading} + + {/if} +
+ +
+
+ + + {#if store.isLoading} + + {:else} + + {/if} +
+
+
+{/if} + +
+ +
+``` + +#### 关键特性 +- 浮动式设计,默认隐藏,点击按钮展开 +- 支持 Markdown 渲染回复内容 +- 显示时间戳和角色标识 +- 输入框自动调整高度 +- 发送按钮根据输入状态启用/禁用 +- 加载状态显示进度环 + +--- + +## 4. 状态管理集成 + +### 4.1 Store 初始化流程 +```typescript +// app/src/routes/main/stores/index.svelte.ts +function createStore() { + let currentFeedId: string | undefined = $state(undefined); + let currentArticle: Article | null = $state(null); + + const context: IContext = { + get currentArticle() { + return currentArticle!; + }, + get currentFeedId() { + return currentFeedId!; + } + }; + + const tasks = createTasks(); + const articles = createArticles(tasks); + const feeds = createFeeds(); + const reader = createReader({ tasks }); + const sprite = createSprite(context); + + return { + get feeds() { return feeds; }, + get currentFeedId() { return currentFeedId; }, + get currentArticle() { return currentArticle; }, + get articles() { return articles; }, + get tasks() { return tasks; }, + get reader() { return reader; }, + get sprite() { return sprite; }, + setCurrentFeedId, + setCurrentArticle, + getCurrentArticle, + scheduleUpdate, + onSelectToday, + onSelectWeekend, + onSelectFavorite, + onSelectUnread, + get isTodaySelected() { return isTodaySelected; }, + get isWeekendSelected() { return isWeekendSelected; }, + get isFavoriteSelected() { return isFavoriteSelected; }, + get isUnreadSelected() { return isUnreadSelected; }, + get isFeedSpecified() { return isFeedSpecified; } + }; +} +``` + +### 4.2 状态派生计算 +使用 `$derived` 实现派生状态: +```typescript +const isTodaySelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.TODAY_FILTER); +const isWeekendSelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.WEEKEND_FILTER); +const isFavoriteSelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.FAVORITE_FILTER); +const isUnreadSelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.UNREAD_FILTER); +const isFeedSpecified = $derived(isSpecifyFeed(currentFeedId)); +``` + +--- + +## 5. 与后端通信机制 + +### 5.1 Hybrid API 调用链路 +前端通过 hybrid-apis 与后端 Rust 逻辑通信: + +``` +frontend: + app/src/lib/hybrid-apis/feed/api.ts → 定义 TypeScript 接口 + app/src/lib/hybrid-apis/feed/impl.ts → 实现调用 tauri.invoke + app/src/lib/hybrid-apis/tauri-regular/index.ts → 封装 invoke 方法 + +backend: + crates/tauri-plugin-feed-api/src/lib.rs → 注册 Tauri 插件 + crates/tauri-plugin-feed-api/src/commands.rs → 定义 #[tauri::command] + crates/feed_api_rs/src/features/impl_default.rs → 实际业务逻辑 +``` + +### 5.2 通信示例 +```typescript +// 前端调用 +featuresApi.update_feed_contents(packageId, feedId); + +// 转换为 Tauri invoke +async function call(methodName: string, args: InvokeArgs): Promise { + return invoke(`plugin:feed-api|${methodName}`, args); +} +``` + +--- + +## 6. 交互流程分析 + +### 6.1 用户点击文章流程 +```mermaid +sequenceDiagram + participant User + participant MainPage as 主页面布局 + participant FeedsList as 侧边栏导航 + participant ArticlesList as 文章列表 + participant ArticleReader as 内容阅读器 + + User->>MainPage: 访问/main路由 + MainPage->>MainPage: 初始化createStore() + MainPage->>FeedsList: 传递feedsStore和回调 + MainPage->>ArticlesList: 传递articlesStore和markAsRead + MainPage->>ArticleReader: 传递readerStore + FeedsList->>MainPage: onFeedPressed(feedId) + ArticlesList->>MainPage: onArticlePressed(article) + MainPage->>ArticlesList: 更新selectedArticle + MainPage->>ArticleReader: 显示currentArticle内容 +``` + +### 6.2 AI 对话交互流程 +```mermaid +graph TD + A[用户打开AI精灵面板] --> B[输入问题并发送] + B --> C[拼接上下文: 文章内容 + 对话历史] + C --> D[构造Prompt发送至LLM代理] + D --> E{选择LLM提供商} + E --> F[调用Ollama/OpenAI/GLM/Mistral] + F --> G[接收流式响应] + G --> H[前端实时渲染回答] + H --> I[追加到对话历史] + I --> J[等待下一轮输入] +``` + +--- + +## 7. 最佳实践总结 + +### 7.1 设计亮点 +1. **响应式架构**:充分利用 Svelte 的反应性系统,实现高效的 UI 更新 +2. **模块化设计**:将 UI 拆分为独立可复用的组件 +3. **状态集中管理**:通过 createStore 统一管理全局状态 +4. **用户体验优先**:自动标记已读、平滑滚动、加载动画等细节处理 +5. **国际化支持**:全面采用 i18n 方案,便于多语言扩展 + +### 7.2 性能优化建议 +1. **虚拟滚动**:对于大量文章列表,考虑引入虚拟滚动以提升性能 +2. **懒加载**:非首屏组件可采用动态导入实现懒加载 +3. **缓存策略**:对频繁访问的数据增加内存缓存层 +4. **Web Worker**:复杂计算任务可移至 Web Worker 避免阻塞主线程 + +### 7.3 扩展性建议 +1. **主题系统**:可进一步完善主题切换机制,支持更多自定义选项 +2. **插件体系**:探索 UI 插件化可能,允许第三方扩展界面功能 +3. **快捷键支持**:增加键盘导航和操作快捷键,提升效率 +4. **无障碍访问**:加强 ARIA 标签和屏幕阅读器支持 + +--- + +## 8. 结论 + +用户界面域作为 `saga-reader` 应用的门面,不仅实现了美观、易用的交互界面,更重要的是构建了一个高效、稳定的状态管理和通信机制。通过 SvelteKit 的现代化开发范式,结合 Tauri 的原生能力,成功打造了兼具桌面应用性能和 Web 应用灵活性的优秀用户体验。 + +该模块的设计充分体现了关注点分离原则,各子模块职责清晰,耦合度低,为后续功能扩展和维护提供了良好基础。特别是其与状态管理域的深度整合,确保了数据流的一致性和可预测性,是整个应用架构中的关键枢纽。 \ No newline at end of file diff --git "a/litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237.md" "b/litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237.md" new file mode 100644 index 0000000..70dd0ad --- /dev/null +++ "b/litho.docs/4\343\200\201\346\267\261\345\205\245\346\216\242\347\264\242/\347\263\273\347\273\237\345\220\257\345\212\250\344\270\216\351\205\215\347\275\256\345\237\237.md" @@ -0,0 +1,345 @@ +# **系统启动与配置域技术实现文档** + +--- + +## **1. 模块概述** + +### **模块名称** +`系统启动与配置域`(System Startup & Configuration Domain) + +### **所属层级** +基础设施域(Infrastructure Layer) + +### **核心职责** +负责应用程序的初始化流程、全局配置管理、日志系统构建以及关键依赖服务(如本地LLM运行时)的状态准备。该模块是整个应用生命周期的起点,确保后续业务逻辑在稳定、一致的环境中运行。 + +### **设计目标** +- 实现**分阶段、可扩展的启动策略**,提升启动效率。 +- 提供**健壮的配置加载机制**,支持默认值生成与持久化。 +- 统一管理**日志输出行为**,便于调试和监控。 +- 预检并激活**AI模型运行环境**(如Ollama),保障核心功能可用性。 +- 通过**错误聚合机制**保证初始化过程的可靠性。 + +--- + +## **2. 架构设计与核心组件** + +本模块采用**分层+插件式初始化架构**,以 `Startup` 结构体为核心控制器,协调多个独立子模块完成系统初始化任务。整体结构如下: + +```rust +// crates/feed_api_rs/src/startup/mod.rs +pub struct Startup { + context: ApplicationContext, +} + +impl Startup { + pub async fn launch() -> anyhow::Result; +} +``` + +### **主要子模块构成** + +| 子模块 | 功能描述 | 关键文件 | +|-------|--------|---------| +| **启动流程管理** | 控制整体初始化顺序,实现同步与并行阶段划分 | `mod.rs`, `tiger0_1()` | +| **应用配置管理** | 加载/创建 `app_config.toml`,提供全局配置对象 | `init_app_config.rs` | +| **用户配置管理** | 管理用户级订阅数据(`user_config.toml`) | `init_user_profile.rs` | +| **LLM运行时管理** | 检查并唤醒本地LLM服务(如Ollama) | `init_llm.rs` | +| **日志系统** | 初始化结构化日志输出,支持磁盘轮转 | `init_logger.rs` | +| **初始化任务抽象** | 封装通用初始化行为,支持耗时统计与状态追踪 | `task.rs`, `types.rs` | + +--- + +## **3. 启动流程详解(Tiger0_1 分阶段策略)** + +系统采用名为 **"Tiger0_1"** 的两阶段初始化策略,旨在分离阻塞型与非阻塞型操作,优化启动性能。 + +### **3.1 流程图示** + +```mermaid +graph TD + A[启动流程开始] --> B{是否Debug模式} + B -->|是| C[启用默认日志] + B -->|否| D[读取app_config.toml] + D --> E{文件存在?} + E -->|否| F[生成默认配置] + E -->|是| G[解析TOML配置] + F --> H[持久化到磁盘] + G --> I[初始化日志系统] + H --> I + I --> J[并行初始化] + J --> K[加载用户配置] + J --> L[唤醒LLM服务] + K --> M{成功?} + L --> N{成功?} + M -->|否| O[聚合错误退出] + N -->|否| O + M -->|是| P[构建ApplicationContext] + N -->|是| P + P --> Q[启动完成] +``` + +### **3.2 阶段说明** + +#### **阶段一:Tiger0 —— 同步关键初始化** +此阶段为串行执行,必须成功才能进入下一阶段。 + +1. **加载应用配置 (`init_app_config::call`)** + - 尝试从 `$APPDATA/saga-reader/app_config.toml` 读取配置。 + - 若文件不存在,则调用 `default_app_config()` 生成默认配置,并立即持久化至磁盘。 + - 使用 `tokio::fs::File` 异步I/O避免主线程阻塞。 + +2. **初始化日志系统 (`init_logger::call`)** + - 根据 `app_config.log` 设置决定日志行为: + - Debug模式:强制开启控制台输出,级别为 `All`。 + - 正式环境:根据 `enable` 和 `output_type` 决定输出方式(Stdout / Disk)。 + - 日志写入采用 `spdlog-rs`,支持按天轮转(`RotatingFileSink`),路径为 `$APPDATA/saga-reader/logs/app*.log`。 + - 自定义格式器输出 `[日期 时间.毫秒] [线程ID] [级别] 日志内容`。 + +> ✅ **优势**:即使配置损坏或缺失,也能降级运行,保障基本可用性。 + +#### **阶段二:Tiger1 —— 并行依赖初始化** +使用 `tokio::join!` 实现并发加载,缩短总启动时间。 + +```rust +let (r1, r2) = tokio::join!( + init_user_profile::call(), + init_llm::call(llm_section) +); +``` + +- **并行任务A:用户配置加载** + - 读取 `user_config.toml`。 + - 若为新用户,生成包含预设订阅包(如“未分类”组 + 默认关键词抓取)的初始配置,并持久化。 + +- **并行任务B:LLM服务状态检查** + - 根据当前激活的 LLM 提供商类型进行处理: + - **Ollama**:调用 `ollama::query_platform(&endpoint)` 探测安装与运行状态。 + - 已安装但未运行 → 调用 `ollama::launch().await` 唤醒服务。 + - 未安装 → 记录状态,不中断启动。 + - 其他提供商(OpenAI/GLM等)→ 执行空初始化(仅占位)。 + +> ⚠️ **失败处理**:任一并行任务失败将导致整体启动中止,并通过 `anyhow::Error::msg(format!("..."))` 聚合错误信息返回。 + +--- + +## **4. 核心技术实现细节** + +### **4.1 配置管理机制** + +#### **配置文件格式** +- 文件名:`app_config.toml`, `user_config.toml` +- 格式:TOML(易于人类编辑) +- 序列化库:`toml` crate + +#### **默认配置生成** +- `default_app_config()` 返回一个完整的 `AppConfig` 对象,包含: + ```rust + AppConfig { + llm: LLMSection { + provider_ollama: OllamaLLMProvider { endpoint: "http://localhost:11434".into() }, + provider_glm: GLMLLMProvider { model_name: "GLM-4.5-Flash".to_string(), ... }, + active_provider_type: LLMProviderType::Ollama, + max_parallel: Some(5), + instruct: LLMInstructOption::default(), + }, + scrap: ScrapSection::default(), + log: Default::default(), + daemon: Default::default(), + diagnostic: Default::default(), + } + ``` + +- `sync_to(...)` 函数负责将内存中的配置对象写回磁盘,确保变更持久化。 + +#### **路径管理** +- 所有配置文件路径由 `recorder::path::get_appdata_file(...)` 统一生成,遵循各平台标准目录规范(如 Windows `%APPDATA%`, macOS `~/Library/Application Support`)。 + +--- + +### **4.2 日志系统实现** + +#### **日志库选择** +- 使用 `spdlog-rs`(Rust绑定自C++ spdlog),具备高性能、低开销、多后端支持等优点。 + +#### **初始化逻辑** +```rust +pub fn init_by(log_section: &AppConfigLogSection) -> anyhow::Result<()> { + if cfg!(debug_assertions) { + // Debug模式自动启用全量日志 + specify_logger_format(&spdlog::default_logger()); + spdlog::default_logger().set_level_filter(LevelFilter::All); + return Ok(()); + } + + if !log_section.enable { + spdlog::default_logger().set_level_filter(LevelFilter::Off); + return Ok(()); + } + + match log_section.output_type { + OutputType::Stdout => { /* 控制台输出 */ } + OutputType::Disk => { + let path = get_appdata_file_in_dir("logs", format!("app{}.log", tail)); + let file_sink = RotatingFileSink::builder() + .base_path(path) + .rotation_policy(RotationPolicy::Daily { hour: 0, minute: 0 }) + .build()?; + let new_logger = spdlog::default_logger().fork_with(|new| { + new.sinks_mut().push(Arc::new(file_sink)); + Ok(()) + })?; + spdlog::set_default_logger(new_logger); + specify_logger_format(&spdlog::default_logger()); + } + _ => { /* fallback to stdout */ } + } + Ok(()) +} +``` + +#### **日志格式** +``` +[2025-04-05 14:23:01.123] [thread-12345] [INFO] starting up...tiger0_1, application configuration and logger initialized +``` + +--- + +### **4.3 LLM 运行时管理(以 Ollama 为例)** + +#### **状态探测机制** +`ollama::query_platform()` 实现双通道检测: + +1. **进程级检测(优先)** + - 在 Unix 系统上调用 `ollama -v` 检查是否存在可执行文件。 + - 成功返回版本号且无连接错误 → `ProgramStatus::Running` + - 存在可执行文件但无法连接 → `ProgramStatus::InstallButNotRunning` + - 命令执行失败 → `ProgramStatus::Uninstall` + +2. **HTTP API 探测(备用)** + - 向 `http://localhost:11434` 发送 GET 请求。 + - 响应体为 `"Ollama is running"` → 判断为运行中。 + - 否则视为未安装或不可达。 + +#### **服务唤醒** +- 调用 `ollama::launch()` 通过 shell 命令触发后台服务启动: + ```rust + #[cfg(unix)] + Command::new("sh").arg("-c").arg("/usr/local/bin/ollama list") + #[cfg(windows)] + Command::new("cmd").arg("/C").arg("ollama list").creation_flags(0x08000000) // CREATE_NO_WINDOW + ``` +- 注意:仅发送命令,不等待结果,防止阻塞主流程。 + +--- + +### **4.4 初始化任务抽象(InitTask)** + +为统一管理各类初始化操作,定义了泛型结构 `InitTask` 与 trait `TaskInitializer`。 + +#### **核心结构** +```rust +pub struct InitTask { + pub result: Option, + pub task_cost: u128, // 耗时(毫秒) + pub task_status: Status, // UnLaunch/Running/Completed/Error +} + +pub enum Status { + UnLaunch, Running, Completed, Aborted, Error +} +``` + +#### **使用模式** +```rust +let mut task = InitTask::default(); +task.start("app_config", || async { + // 具体初始化逻辑 +}).await?; +``` + +- 自动记录开始/结束时间。 +- 成功时设置 `result` 和 `Completed` 状态。 +- 失败时记录错误日志并抛出异常。 + +> 📌 **价值**:提供标准化接口,便于未来扩展延迟初始化(Tiger2)或健康检查功能。 + +--- + +## **5. 上下文传递:ApplicationContext** + +所有初始化成果最终封装为 `ApplicationContext`,作为后续业务模块共享的上下文对象。 + +```rust +#[derive(Clone)] +pub struct ApplicationContext { + pub app_config: AppConfig, + pub user_config: UserConfig, +} +``` + +- 通过 `ContextHost` trait 实现上下文持有者模式: + ```rust + pub trait ContextHost { + fn new(context: ApplicationContext) -> Self; + fn get_context(&self) -> &ApplicationContext; + fn copy_context(&self) -> ApplicationContext; + } + ``` + +- `Startup` 实现该 trait,允许其他模块安全访问配置信息。 + +--- + +## **6. 错误处理与可观测性** + +### **错误传播机制** +- 使用 `anyhow::Result` 进行链式错误传播。 +- 启动失败时聚合多个子任务错误信息,便于定位问题根源。 + +### **日志观测点** +| 阶段 | 日志内容 | +|------|--------| +| Tiger0 开始 | `starting up...tiger0_1, application configuration and logger initialized` | +| 用户配置加载 | `the task user_profile execute completed, cost 12ms` | +| LLM 初始化 | `the task llm_provider_ollama execute completed, cost 87ms` | +| 启动完成 | `starting up...tiger0_1, end initialize` | +| 启动失败 | `error in startup..., Some(...), None` | + +--- + +## **7. 可扩展性设计(预留 Tiger2)** + +当前仅实现 `tiger0_1()`,但已预留 `tiger2(_context: ApplicationContext)` 接口: + +```rust +pub async fn tiger2(_context: ApplicationContext) -> anyhow::Result { + todo!(); +} +``` + +可用于未来实现: +- 插件动态加载 +- 守护进程注册 +- AI模型预热缓存 +- 网络状态检测等非关键路径初始化 + +--- + +## **8. 总结与建议** + +### **模块亮点** +- ✅ **分阶段启动策略** 显著提升用户体验。 +- ✅ **配置即代码** 设计增强可维护性。 +- ✅ **本地LLM无缝集成** 支持私有化部署场景。 +- ✅ **结构化日志 + 任务追踪** 提升运维能力。 + +### **改进建议** +1. **增加配置校验机制**:对 `app_config.toml` 添加 schema validation,防止非法输入。 +2. **支持热重载配置**:监听文件变化,无需重启即可生效。 +3. **完善Ollama自动安装逻辑**:目前仅唤醒,可考虑集成下载安装向导。 +4. **引入指标监控**:记录各阶段耗时,用于性能分析。 + +--- + +✅ **结论**:`系统启动与配置域` 是一个设计严谨、职责清晰、具备良好扩展性的基础设施模块,为 `saga-reader` 的稳定性与智能化奠定了坚实基础。 \ No newline at end of file diff --git a/litho.docs/__Litho_Summary_Brief__.md b/litho.docs/__Litho_Summary_Brief__.md new file mode 100644 index 0000000..5e29d40 --- /dev/null +++ b/litho.docs/__Litho_Summary_Brief__.md @@ -0,0 +1,63 @@ +# 项目分析摘要报告 + +生成时间: 2025-09-28 02:54:24 UTC + +## 执行概览 + +**总执行时间**: 1734.54 秒 +**各阶段耗时**: +- 文档化: 1570.72s (90.6%) +- 研究调研: 97.05s (5.6%) +- 预处理: 66.77s (3.8%) +- 输出: 0.00s (0.0%) + +## 缓存效果概览 + +**缓存命中率**: 99.5% 🟢 优秀 +**节省时间**: 997.2 秒 +**节省Token**: 286955 输入 + 135038 输出 = 421993 总计 +**节省成本**: $0.2290 +**效率提升**: 0.6x 倍 +**成本效益**: $0.000132/秒 + +## 调研数据概览 + +根据Prompt模板数据整合规则,成功收集四类调研材料: + +✅ **系统上下文调研报告**: 已生成 +✅ **领域模块调研报告**: 已生成 +✅ **工作流调研报告**: 已生成 +✅ **代码洞察数据**: 已生成 + +**调研完成度**: 4/4 (100.0%) + +## Memory存储概览 + +**总存储大小**: 870629 bytes +**存储作用域数量**: 4 个 + +### 主要存储分布(前3位) +- **preprocess**: 690819 bytes (79.3%) +- **documentation**: 115625 bytes (13.3%) +- **studies_research**: 64147 bytes (7.4%) + +## 文档生成概览 + +**文档生成数量**: 9 个 +**文档类型**: + - 核心模块与组件调研报告_用户界面域 + - 核心流程 + - 核心模块与组件调研报告_状态管理域 + - 核心模块与组件调研报告_系统启动与配置域 + - 项目概述 + - 核心模块与组件调研报告_AI能力集成域 + - 核心模块与组件调研报告_内容获取与处理域 + - 核心模块与组件调研报告_数据持久化域 + - 架构说明 + +## 总体评估 + +**数据完整性**: 100.0% 🟢 完整 +**缓存效率**: 99.5% 🟢 高效 +**执行效率**: 1734.54s 🔴 较慢 +**文档生成**: 已完成 🟢 成功 diff --git a/litho.docs/__Litho_Summary_Detail__.md b/litho.docs/__Litho_Summary_Detail__.md new file mode 100644 index 0000000..4001504 --- /dev/null +++ b/litho.docs/__Litho_Summary_Detail__.md @@ -0,0 +1,13915 @@ +# 项目分析总结报告(完整版) + +生成时间: 2025-09-28 02:54:24 UTC + +## 执行耗时统计 + +- **总执行时间**: 1734.54 秒 +- **预处理阶段**: 66.77 秒 (3.8%) +- **研究阶段**: 97.05 秒 (5.6%) +- **文档生成阶段**: 1570.72 秒 (90.6%) +- **输出阶段**: 0.00 秒 (0.0%) +- **Summary生成时间**: 0.004 秒 + +## 缓存性能统计与节约效果 + +### 性能指标 +- **缓存命中率**: 99.5% +- **总操作次数**: 217 +- **缓存命中**: 216 次 +- **缓存未命中**: 1 次 +- **缓存写入**: 1 次 + +### 节约效果 +- **节省推理时间**: 997.2 秒 +- **节省Token数量**: 286955 输入 + 135038 输出 = 421993 总计 +- **估算节省成本**: $0.2290 +- **性能提升**: 99.5% +- **效率提升比**: 0.6x(节省时间 / 实际执行时间) + +## 核心调研数据汇总 + +根据Prompt模板数据整合规则,以下为四类调研材料的完整内容: + +### 系统上下文调研报告 +提供项目的核心目标、用户角色和系统边界信息。 + +```json +{ + "business_value": "为用户提供一站式的深度内容阅读体验,结合自动化信息聚合与AI智能处理能力,帮助用户高效获取、筛选和理解互联网上的高质量信息,提升知识吸收效率。", + "confidence_score": 0.95, + "external_systems": [ + { + "description": "本地大语言模型运行时,用于执行文章内容的净化、优化和融合等AI任务。", + "interaction_type": "HTTP API 调用与进程控制", + "name": "Ollama" + }, + { + "description": "云端大语言模型服务,作为可选的AI能力提供者之一。", + "interaction_type": "RESTful API 调用", + "name": "OpenAI" + }, + { + "description": "国产大语言模型服务,支持中文语境下的智能处理。", + "interaction_type": "RESTful API 调用", + "name": "GLM (智谱AI)" + }, + { + "description": "国际先进的开源大语言模型提供商,提供高性能推理服务。", + "interaction_type": "RESTful API 调用", + "name": "Mistral AI" + }, + { + "description": "用于关键词搜索的内容抓取来源之一。", + "interaction_type": "HTML 爬取与解析", + "name": "Bing Search" + }, + { + "description": "中文搜索引擎,作为中文内容检索的主要数据源。", + "interaction_type": "HTML 爬取与解析", + "name": "Baidu Search" + }, + { + "description": "用户订阅的各类博客、新闻网站等内容源。", + "interaction_type": "RSS XML 解析", + "name": "RSS Feeds" + } + ], + "project_description": "一个基于Tauri框架的桌面端信息聚合与智能阅读应用,支持RSS订阅管理、网页内容抓取、本地AI模型集成(如Ollama)以及通过大语言模型对文章进行净化、优化和融合处理。", + "project_name": "saga-reader", + "project_type": "FullStackApp", + "system_boundary": { + "excluded_components": [ + "第三方AI模型的训练与维护", + "搜索引擎的索引构建", + "云同步服务(当前仅支持本地存储)", + "社交分享功能", + "浏览器插件集成" + ], + "included_components": [ + "RSS订阅管理(增删改查)", + "网页内容智能抓取(支持JavaScript渲染)", + "基于LLM的文章内容处理管道(Purge, Optimize, Melt)", + "本地Ollama模型的启停与状态管理", + "多语言支持与主题切换", + "系统托盘与守护进程机制", + "前端SvelteKit界面与后端Rust逻辑的Tauri桥接" + ], + "scope": "完整的桌面端信息聚合与智能阅读系统" + }, + "target_users": [ + { + "description": "需要持续学习和跟踪行业动态的专业人士,如研究员、工程师、产品经理等。", + "name": "知识工作者", + "needs": [ + "高效的信息源聚合", + "去除干扰内容的纯净阅读模式", + "智能摘要与内容提炼", + "本地化AI处理保障隐私" + ] + }, + { + "description": "关注前沿技术和开源项目的开发者或极客用户。", + "name": "技术爱好者", + "needs": [ + "支持自定义爬虫规则", + "可扩展的插件架构", + "本地运行的大语言模型集成", + "跨平台桌面应用体验" + ] + } + ] +} +``` + +### 领域模块调研报告 +提供高层次的领域划分、模块关系和核心业务流程信息。 + +```json +{ + "architecture_summary": "系统采用分层架构设计,前端基于SvelteKit构建响应式UI,通过Tauri桥接Rust后端。核心业务逻辑分布在内容获取与处理、AI能力集成等领域,由状态管理域统一协调。数据持久化基于SeaORM操作SQLite数据库。整体架构清晰分离关注点,支持本地AI模型集成和多源内容抓取。", + "business_flows": [ + { + "description": "用户启动应用后,系统自动加载配置、初始化状态并展示主界面的过程。", + "entry_point": "app/src-tauri/src/main.rs", + "importance": 9.0, + "involved_domains_count": 4, + "name": "项目分析流程", + "steps": [ + { + "code_entry_point": "crates/feed_api_rs/src/startup/mod.rs", + "domain_module": "系统启动与配置域", + "operation": "执行分阶段初始化:先同步初始化配置和日志,再并行加载用户配置与LLM服务", + "step": 1, + "sub_module": "启动流程管理" + }, + { + "code_entry_point": "crates/feed_api_rs/src/startup/init_app_config.rs", + "domain_module": "系统启动与配置域", + "operation": "尝试从磁盘读取app_config.toml,若不存在则创建默认配置并持久化", + "step": 2, + "sub_module": "应用配置管理" + }, + { + "code_entry_point": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "domain_module": "系统启动与配置域", + "operation": "尝试读取user_config.toml,若为新用户则生成包含预设订阅包的默认配置", + "step": 3, + "sub_module": "用户配置管理" + }, + { + "code_entry_point": "crates/feed_api_rs/src/startup/init_llm.rs", + "domain_module": "系统启动与配置域", + "operation": "检查Ollama服务状态,若已安装但未运行则尝试唤醒服务", + "step": 4, + "sub_module": "LLM运行时管理" + }, + { + "code_entry_point": "app/src/routes/main/stores/index.svelte.ts", + "domain_module": "状态管理域", + "operation": "创建主状态store,整合feeds、articles、tasks等子模块", + "step": 5, + "sub_module": "集中式状态存储" + }, + { + "code_entry_point": "app/src/routes/main/+page.svelte", + "domain_module": "用户界面域", + "operation": "渲染主界面三栏布局,绑定各组件到对应的状态store", + "step": 6, + "sub_module": "主页面布局" + } + ] + }, + { + "description": "当用户点击某篇文章时,系统通过AI模型生成内容摘要和洞察的完整流程。", + "entry_point": "用户点击文章条目", + "importance": 9.5, + "involved_domains_count": 4, + "name": "代码洞察生成流程", + "steps": [ + { + "code_entry_point": "app/src/routes/main/widgets/ArticlesList.svelte", + "domain_module": "用户界面域", + "operation": "捕获用户点击事件,获取被点击文章的ID", + "step": 1, + "sub_module": "文章列表展示" + }, + { + "code_entry_point": "app/src/routes/main/stores/articles/list/index.svelte.ts", + "domain_module": "状态管理域", + "operation": "根据文章ID查询详细内容,并更新当前选中文章状态", + "step": 2, + "sub_module": "文章状态管理" + }, + { + "code_entry_point": "crates/intelligent/src/article_processor/*", + "domain_module": "内容获取与处理域", + "operation": "启动LLM处理流水线,依次执行Purge(净化)、Optimize(优化)、Melt(融合)操作", + "step": 3, + "sub_module": "文章内容处理管道" + }, + { + "code_entry_point": "crates/llm/src/llm_agent.rs", + "domain_module": "AI能力集成域", + "operation": "根据配置选择具体的LLM提供商(如Ollama、OpenAI),发送处理请求", + "step": 4, + "sub_module": "LLM代理服务" + }, + { + "code_entry_point": "crates/llm/src/providers/llm_ollama.rs", + "domain_module": "AI能力集成域", + "operation": "向本地Ollama服务发送POST请求,执行文本生成任务", + "step": 5, + "sub_module": "Ollama集成" + }, + { + "code_entry_point": "crates/intelligent/src/article_processor/llm_processor.rs", + "domain_module": "内容获取与处理域", + "operation": "接收LLM返回的处理结果,更新文章的优化后和熔炼后内容字段", + "step": 6, + "sub_module": "文章内容处理管道" + }, + { + "code_entry_point": "crates/recorder/src/article_recorder_service.rs", + "domain_module": "数据持久化域", + "operation": "将处理后的文章内容更新到数据库中", + "step": 7, + "sub_module": "文章记录服务" + }, + { + "code_entry_point": "app/src/routes/main/widgets/ArticleReader.svelte", + "domain_module": "用户界面域", + "operation": "重新渲染文章阅读器,展示新的优化和熔炼内容", + "step": 8, + "sub_module": "内容阅读器" + } + ] + } + ], + "confidence_score": 9.0, + "domain_modules": [ + { + "code_paths": [ + "app/src/routes/main/+page.svelte", + "app/src/routes/main/widgets/*.svelte" + ], + "complexity": 7.5, + "description": "负责应用的整体视觉呈现、用户交互和前端状态管理,为用户提供直观、响应式的操作体验。", + "domain_type": "核心业务域", + "importance": 9.0, + "name": "用户界面域", + "sub_modules": [ + { + "code_paths": [ + "app/src/routes/main/+page.svelte" + ], + "description": "实现应用主界面的三栏式布局结构,协调信息源列表、文章列表和内容阅读器等组件。", + "importance": 9.5, + "key_functions": [ + "初始化主状态存储", + "集成全局通知系统", + "协调多模块UI组件" + ], + "name": "主页面布局" + }, + { + "code_paths": [ + "app/src/routes/main/widgets/FeedsList.svelte" + ], + "description": "提供结构化的订阅包和订阅项管理界面,支持聚合视图切换和上下文菜单操作。", + "importance": 8.0, + "key_functions": [ + "渲染FeedsPackage和Feed列表", + "处理分组展开/折叠", + "提供右键上下文菜单" + ], + "name": "侧边栏导航" + }, + { + "code_paths": [ + "app/src/routes/main/widgets/ArticlesList.svelte" + ], + "description": "负责文章条目的分组渲染、加载状态管理和自动标记已读等交互逻辑。", + "importance": 9.0, + "key_functions": [ + "按分组显示文章", + "实现滚动加载更多", + "自动标记阅读状态" + ], + "name": "文章列表展示" + }, + { + "code_paths": [ + "app/src/routes/main/widgets/ArticleReader.svelte" + ], + "description": "提供文章内容的多模式阅读体验,支持优化、熔炼和原始三种视图切换。", + "importance": 9.5, + "key_functions": [ + "渲染HTML或Markdown内容", + "实现标签页视图切换", + "提供外部链接打开功能" + ], + "name": "内容阅读器" + }, + { + "code_paths": [ + "app/src/routes/main/widgets/AISpritePanel.svelte" + ], + "description": "实现悬浮式AI聊天界面,支持与文章内容相关的智能对话交互。", + "importance": 8.5, + "key_functions": [ + "管理对话历史记录", + "发送消息至AI服务", + "渲染Markdown回复内容" + ], + "name": "AI助手面板" + } + ] + }, + { + "code_paths": [ + "app/src/routes/main/stores/*.svelte.ts" + ], + "complexity": 8.0, + "description": "集中管理应用的全局和局部状态,确保数据一致性并驱动UI更新,是前后端交互的核心枢纽。", + "domain_type": "核心业务域", + "importance": 9.5, + "name": "状态管理域", + "sub_modules": [ + { + "code_paths": [ + "app/src/routes/main/stores/index.svelte.ts" + ], + "description": "创建和整合多个子store,对外提供统一的状态访问接口,是整个应用的状态中枢。", + "importance": 10.0, + "key_functions": [ + "整合feeds、articles、tasks等多个子store", + "管理当前feed和文章选择状态", + "调度定时内容更新任务" + ], + "name": "集中式状态存储" + }, + { + "code_paths": [ + "app/src/routes/main/stores/articles/list/index.svelte.ts" + ], + "description": "专门管理文章列表的展示逻辑,包括分组、分页、搜索过滤和刷新操作。", + "importance": 9.0, + "key_functions": [ + "实现文章分组与分页", + "响应搜索条件变化", + "管理不同场景下的加载状态" + ], + "name": "文章状态管理" + }, + { + "code_paths": [ + "app/src/routes/main/stores/tasks.svelte.ts" + ], + "description": "集中跟踪所有后台异步任务的执行状态,为用户提供可视化的进度反馈。", + "importance": 8.5, + "key_functions": [ + "维护待处理任务队列", + "统一管理加载状态文本", + "提供任务添加和查询接口" + ], + "name": "异步任务管理" + }, + { + "code_paths": [ + "app/src/routes/main/stores/reader.svelte.ts" + ], + "description": "管理单篇文章的阅读状态和内容刷新逻辑,支持智能去重的任务调度。", + "importance": 8.0, + "key_functions": [ + "标记文章为已读", + "调度增强型抓取任务", + "实现任务复用机制避免重复请求" + ], + "name": "阅读状态管理" + }, + { + "code_paths": [ + "app/src/routes/main/stores/sprite.svelte.ts" + ], + "description": "管理AI精灵对话界面的状态,包括消息历史、加载状态和可见性控制。", + "importance": 8.0, + "key_functions": [ + "维护对话历史记录", + "处理用户消息发送", + "管理异步请求状态" + ], + "name": "AI对话状态" + } + ] + }, + { + "code_paths": [ + "crates/scrap/src/*", + "crates/intelligent/src/article_processor/*" + ], + "complexity": 9.0, + "description": "负责从多种来源抓取网页内容,并通过大语言模型进行净化、优化和融合等智能处理,形成高质量的可读内容。", + "domain_type": "核心业务域", + "importance": 9.5, + "name": "内容获取与处理域", + "sub_modules": [ + { + "code_paths": [ + "crates/scrap/src/rss/mod.rs" + ], + "description": "实现标准RSS源的内容解析和正文提取,是传统信息源的主要获取方式。", + "importance": 8.5, + "key_functions": [ + "解析RSS XML数据", + "提取文章元信息", + "调用文章阅读器获取完整正文" + ], + "name": "RSS内容抓取" + }, + { + "code_paths": [ + "crates/scrap/src/search/bing.rs", + "crates/scrap/src/search/baidu.rs" + ], + "description": "从Bing、百度等搜索引擎结果页抓取内容,扩展信息获取渠道。", + "importance": 8.0, + "key_functions": [ + "发起关键词搜索请求", + "解析HTML搜索结果", + "抓取目标网页全文内容" + ], + "name": "搜索引擎爬虫" + }, + { + "code_paths": [ + "crates/scrap/src/simulator.rs", + "crates/scrap/src/article_reader.rs" + ], + "description": "通过Tauri Webview实现对JavaScript渲染页面的智能抓取,支持自动重定向检测。", + "importance": 9.0, + "key_functions": [ + "创建隐藏Webview窗口", + "执行JavaScript提取DOM内容", + "利用LLM判断是否存在前端跳转" + ], + "name": "智能网页抓取" + }, + { + "code_paths": [ + "crates/intelligent/src/article_processor/purge.rs", + "crates/intelligent/src/article_processor/optimizer.rs", + "crates/intelligent/src/article_processor/melt.rs" + ], + "description": "构建基于LLM的文章处理流水线,依次执行净化、优化和融合操作。", + "importance": 9.5, + "key_functions": [ + "构造LLM提示词", + "调用底层AI服务", + "串联多个处理阶段" + ], + "name": "文章内容处理管道" + } + ] + }, + { + "code_paths": [ + "crates/llm/src/*" + ], + "complexity": 8.5, + "description": "封装与各种大语言模型提供商的交互逻辑,为上层应用提供统一的AI服务能力。", + "domain_type": "核心业务域", + "importance": 9.0, + "name": "AI能力集成域", + "sub_modules": [ + { + "code_paths": [ + "crates/llm/src/llm_agent.rs" + ], + "description": "实现面向多种LLM提供商的代理模式,屏蔽底层接口差异,提供统一的文本生成能力。", + "importance": 9.5, + "key_functions": [ + "根据配置动态选择服务实例", + "转发用户输入至对应提供商", + "处理不同提供商的响应格式" + ], + "name": "LLM代理服务" + }, + { + "code_paths": [ + "crates/llm/src/providers/llm_ollama.rs" + ], + "description": "实现对本地Ollama模型的补全服务调用,支持私有化部署的AI能力。", + "importance": 9.0, + "key_functions": [ + "构造Ollama API请求", + "解析completion响应", + "管理模型配置" + ], + "name": "Ollama集成" + }, + { + "code_paths": [ + "crates/llm/src/providers/llm_openaibase_like.rs" + ], + "description": "实现与OpenAI风格API兼容的服务调用,支持主流云端大模型接入。", + "importance": 8.5, + "key_functions": [ + "构造OpenAI格式请求", + "解析流式响应", + "支持系统提示词配置" + ], + "name": "OpenAI兼容接口" + }, + { + "code_paths": [ + "crates/llm/src/providers/llm_glm.rs", + "crates/llm/src/providers/llm_mistral.rs" + ], + "description": "作为适配层使系统能够以统一方式调用智谱AI和Mistral等特定厂商的模型服务。", + "importance": 8.0, + "key_functions": [ + "转换GLM配置为通用格式", + "复用OpenAI兼容逻辑", + "适配特定API端点" + ], + "name": "GLM/Mistral适配" + } + ] + }, + { + "code_paths": [ + "crates/recorder/src/*" + ], + "complexity": 7.0, + "description": "负责应用程序的数据存储与管理,包括用户配置、文章记录和数据库操作。", + "domain_type": "基础设施域", + "importance": 8.0, + "name": "数据持久化域", + "sub_modules": [ + { + "code_paths": [ + "crates/recorder/src/article_recorder_service.rs" + ], + "description": "封装对文章记录的各类数据访问逻辑,是连接业务逻辑与数据库的关键中介。", + "importance": 8.5, + "key_functions": [ + "插入和更新文章记录", + "按条件查询文章", + "标记已读和收藏状态" + ], + "name": "文章记录服务" + }, + { + "code_paths": [ + "crates/recorder/src/operator.rs" + ], + "description": "使用SeaORM框架实现对SQLite数据库的访问,管理`t_article_record`表的CRUD操作。", + "importance": 8.0, + "key_functions": [ + "建立数据库连接池", + "执行异步数据库操作", + "确保表结构存在" + ], + "name": "数据库操作器" + }, + { + "code_paths": [ + "crates/recorder/src/path.rs" + ], + "description": "封装应用程序数据存储路径的生成与管理,确保跨平台兼容性。", + "importance": 7.0, + "key_functions": [ + "获取标准系统路径", + "构建完整文件路径", + "自动创建缺失目录" + ], + "name": "数据路径管理" + } + ] + }, + { + "code_paths": [ + "crates/feed_api_rs/src/startup/*" + ], + "complexity": 7.5, + "description": "负责应用程序的初始化流程、配置管理和生命周期控制,确保系统稳定运行。", + "domain_type": "基础设施域", + "importance": 8.5, + "name": "系统启动与配置域", + "sub_modules": [ + { + "code_paths": [ + "crates/feed_api_rs/src/startup/mod.rs" + ], + "description": "作为应用启动中枢,采用分阶段策略进行初始化,提升启动效率。", + "importance": 9.0, + "key_functions": [ + "同步初始化关键配置", + "并行加载用户配置与LLM依赖", + "实现错误聚合处理" + ], + "name": "启动流程管理" + }, + { + "code_paths": [ + "crates/feed_api_rs/src/startup/init_app_config.rs" + ], + "description": "加载或创建默认的应用配置,支持运行时动态保存配置实现持久化。", + "importance": 8.5, + "key_functions": [ + "读取TOML格式配置文件", + "生成默认配置对象", + "同步配置到磁盘" + ], + "name": "应用配置管理" + }, + { + "code_paths": [ + "crates/feed_api_rs/src/startup/init_user_profile.rs" + ], + "description": "在应用启动时初始化用户个人资料,为新用户提供引导体验。", + "importance": 8.0, + "key_functions": [ + "读取user_config.toml文件", + "生成默认用户配置", + "持久化到磁盘" + ], + "name": "用户配置管理" + }, + { + "code_paths": [ + "crates/feed_api_rs/src/startup/init_logger.rs" + ], + "description": "初始化应用程序的日志系统,根据配置决定输出位置和格式。", + "importance": 7.5, + "key_functions": [ + "配置全局日志行为", + "实现按天轮转的日志写入", + "设置可读的日志格式" + ], + "name": "日志系统" + }, + { + "code_paths": [ + "crates/feed_api_rs/src/startup/init_llm.rs" + ], + "description": "在应用启动时初始化指定的大型语言模型提供程序,如唤醒Ollama服务。", + "importance": 8.5, + "key_functions": [ + "检查LLM安装状态", + "尝试唤醒未运行的服务", + "执行空初始化保持流程一致" + ], + "name": "LLM运行时管理" + } + ] + } + ], + "domain_relations": [ + { + "description": "用户界面域的所有组件都依赖于状态管理域提供的store来获取数据和触发状态变更。", + "from_domain": "用户界面域", + "relation_type": "状态依赖", + "strength": 10.0, + "to_domain": "状态管理域" + }, + { + "description": "UI组件通过hybrid-apis间接调用内容获取与处理域的功能,如刷新文章内容。", + "from_domain": "用户界面域", + "relation_type": "功能调用", + "strength": 8.0, + "to_domain": "内容获取与处理域" + }, + { + "description": "AI助手面板直接与AI能力集成域交互,发送消息并接收回复。", + "from_domain": "用户界面域", + "relation_type": "服务调用", + "strength": 7.0, + "to_domain": "AI能力集成域" + }, + { + "description": "状态管理域中的stores调用内容获取与处理域的API来获取最新内容并更新状态。", + "from_domain": "状态管理域", + "relation_type": "数据流", + "strength": 9.0, + "to_domain": "内容获取与处理域" + }, + { + "description": "状态管理需要从数据持久化域读取初始数据,并将变更持久化回数据库。", + "from_domain": "状态管理域", + "relation_type": "数据依赖", + "strength": 8.5, + "to_domain": "数据持久化域" + }, + { + "description": "文章内容处理管道必须依赖AI能力集成域提供的LLM服务来完成净化、优化和融合操作。", + "from_domain": "内容获取与处理域", + "relation_type": "服务依赖", + "strength": 10.0, + "to_domain": "AI能力集成域" + }, + { + "description": "处理完成后的内容需要持久化到数据库中,供后续读取和展示。", + "from_domain": "内容获取与处理域", + "relation_type": "数据写入", + "strength": 9.0, + "to_domain": "数据持久化域" + }, + { + "description": "LLM服务的初始化和配置需要依赖系统启动时加载的应用配置。", + "from_domain": "AI能力集成域", + "relation_type": "配置依赖", + "strength": 8.0, + "to_domain": "系统启动与配置域" + }, + { + "description": "数据库操作需要使用系统启动与配置域提供的数据存储路径。", + "from_domain": "数据持久化域", + "relation_type": "路径依赖", + "strength": 7.0, + "to_domain": "系统启动与配置域" + } + ] +} +``` + +### 工作流调研报告 +包含对代码库的静态分析结果和业务流程分析。 + +```json +{ + "main_workflow": { + "description": "用户选择一篇文章后,系统从数据库或网络抓取原始内容,并通过LLM代理依次执行净化(Purge)、优化(Optimize)和融合(Melt)三个阶段的智能处理,最终将结构化、高质量的内容呈现给用户。该流程是系统的核心价值所在,实现了从原始网页到可读性强的知识内容的转化。", + "flowchart_mermaid": "graph TD\n A[用户点击文章] --> B{文章内容是否存在}\n B -->|否| C[启动内容抓取]\n C --> D[RSS/搜索/直接URL抓取]\n D --> E[提取正文文本]\n B -->|是| F[加载已存档内容]\n E --> G[LLM净化: 去除噪音]\n F --> G\n G --> H[LLM优化: 结构化摘要]\n H --> I[LLM融合: 深度洞察生成]\n I --> J[更新数据库]\n J --> K[前端展示优化后内容]\n K --> L[用户获得智能阅读体验]", + "name": "文章智能处理与阅读流程" + }, + "other_important_workflows": [ + { + "description": "应用程序启动时,首先加载全局配置和日志系统,然后并行初始化用户配置和个人订阅信息,并检查本地AI模型(如Ollama)的运行状态。完成后创建前端状态管理器并渲染主界面,确保用户进入应用即可使用完整功能。", + "flowchart_mermaid": "graph TD\n A[启动应用] --> B[加载app_config.toml]\n B --> C{文件存在?}\n C -->|否| D[创建默认配置]\n C -->|是| E[读取配置]\n D --> F[持久化配置]\n E --> F\n F --> G[初始化日志系统]\n G --> H[加载user_config.toml]\n H --> I{新用户?}\n I -->|是| J[生成默认订阅包]\n I -->|否| K[加载用户数据]\n J --> L[初始化LLM服务]\n K --> L\n L --> M[唤醒Ollama若未运行]\n M --> N[构建全局状态Store]\n N --> O[渲染主界面]", + "name": "应用启动初始化流程" + }, + { + "description": "系统定时触发订阅源更新任务,对每个订阅项调用对应的抓取器(RSS或搜索引擎),获取最新的文章列表。对于每篇新文章,启动异步处理管道进行内容提取和AI增强处理,并将结果存储至本地数据库,供后续阅读使用。", + "flowchart_mermaid": "graph TD\n A[定时触发更新] --> B[遍历所有订阅源]\n B --> C{类型=RSS?}\n C -->|是| D[解析RSS XML]\n C -->|否| E[执行Bing/Baidu搜索]\n D --> F[提取标题/链接/摘要]\n E --> F\n F --> G[抓取文章完整正文]\n G --> H[检查是否已存在]\n H -->|否| I[创建新文章记录]\n H -->|是| J[跳过或标记为新]\n I --> K[加入LLM处理队列]\n K --> L[Purge → Optimize → Melt]\n L --> M[持久化处理结果]\n M --> N[通知UI刷新列表]", + "name": "订阅内容自动更新流程" + }, + { + "description": "用户在AI精灵面板中输入问题后,系统将当前文章内容与用户提问结合,构造提示词发送至LLM代理。代理根据配置选择具体提供商(如Ollama、GLM等)进行推理,并将生成的回答返回前端展示,支持多轮对话历史维护。", + "flowchart_mermaid": "graph TD\n A[用户打开AI精灵面板] --> B[输入问题并发送]\n B --> C[拼接上下文: 文章内容 + 对话历史]\n C --> D[构造Prompt发送至LLM代理]\n D --> E{选择LLM提供商}\n E --> F[调用Ollama/OpenAI/GLM/Mistral]\n F --> G[接收流式响应]\n G --> H[前端实时渲染回答]\n H --> I[追加到对话历史]\n I --> J[等待下一轮输入]", + "name": "AI助手对话交互流程" + } + ] +} +``` + +### 代码洞察数据 +来自预处理阶段的代码分析结果,包含函数、类和模块的定义。 + +```json +[ + { + "code_dossier": { + "code_purpose": "page", + "description": "主页面路由组件,负责整合feeds、文章列表、阅读器和AI精灵面板等核心UI模块。", + "file_path": "app/src/routes/main/+page.svelte", + "functions": [], + "importance_score": 1.0, + "interfaces": [ + "onFeedPressed", + "onSelectToday", + "onSelectWeekend", + "onSelectFavorite", + "onSelectUnread", + "onArticlePressed" + ], + "name": "+page.svelte", + "source_summary": "\n\n
\n\t
\n\t\t\n\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t
\n\t\t\t\n\t\t\n\t\t\n\t\t
\n\t\t\t{#if mainStore.currentArticle}\n\t\t\t\t\n\t\t\t{:else}\n\t\t\t\t\n\t\t\t{/if}\n\t\t
\n\t
\n\t\n\t
\n\n\t\n\n\t\n\t\n\t\n
\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 11.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 75, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": false, + "line_number": 1, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + }, + { + "dependency_type": "import", + "is_external": true, + "line_number": 2, + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 3, + "name": "./widgets/FeedsList.svelte", + "path": "./widgets/FeedsList.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 4, + "name": "./widgets/ArticlesList.svelte", + "path": "./widgets/ArticlesList.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 5, + "name": "./widgets/SearchBar.svelte", + "path": "./widgets/SearchBar.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 6, + "name": "./widgets/ArticleReader.svelte", + "path": "./widgets/ArticleReader.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 7, + "name": "./widgets/Footer.svelte", + "path": "./widgets/Footer.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 8, + "name": "./widgets/ReaderBlankIndicator.svelte", + "path": "./widgets/ReaderBlankIndicator.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 9, + "name": "./stores/index.svelte", + "path": "./stores/index.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 10, + "name": "./widgets/AISpritePanel.svelte", + "path": "./widgets/AISpritePanel.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 11, + "name": "./stores/toast", + "path": "./stores/toast", + "version": null + } + ], + "detailed_description": "该组件是SvelteKit应用中的主页面路由组件(+page.svelte),位于 /main 路由下。它作为整个主界面的布局容器,负责协调多个功能模块:左侧为信息源列表(FeedsList),中间为文章列表(ArticlesList)与搜索栏(SearchBar),右侧为主内容区的文章阅读器(ArticleReader)或空白提示(ReaderBlankIndicator)。底部包含全局Footer和AI精灵面板(AISpritePanel)。通过导入 createStore 初始化主状态 store,并将其拆分为 feedsStore、articlesStore、readerStore 等子模块供各子组件使用。同时集成了两个 Toaster 实例用于全局通知和AI相关通知。组件使用 disableContextMenu 指令防止右键菜单触发,提升用户体验。", + "interfaces": [ + { + "description": "当用户点击某个信息源时触发,用于更新当前选中的feed", + "interface_type": "function", + "name": "onFeedPressed", + "parameters": [ + { + "description": "被点击的信息源ID", + "is_optional": false, + "name": "feedId", + "param_type": "string" + } + ], + "return_type": "void", + "visibility": "public" + }, + { + "description": "选择今日推荐内容", + "interface_type": "function", + "name": "onSelectToday", + "parameters": [], + "return_type": "void", + "visibility": "public" + }, + { + "description": "选择周末精选内容", + "interface_type": "function", + "name": "onSelectWeekend", + "parameters": [], + "return_type": "void", + "visibility": "public" + }, + { + "description": "选择收藏的文章", + "interface_type": "function", + "name": "onSelectFavorite", + "parameters": [], + "return_type": "void", + "visibility": "public" + }, + { + "description": "选择未读文章", + "interface_type": "function", + "name": "onSelectUnread", + "parameters": [], + "return_type": "void", + "visibility": "public" + }, + { + "description": "当用户点击文章列表中的某篇文章时触发", + "interface_type": "function", + "name": "onArticlePressed", + "parameters": [ + { + "description": "被点击的文章对象", + "is_optional": false, + "name": "article", + "param_type": "Article" + } + ], + "return_type": "void", + "visibility": "public" + } + ], + "responsibilities": [ + "作为主路由页面的布局容器,组织并渲染核心UI组件", + "初始化并管理全局状态 store 及其子模块", + "协调不同功能模块之间的数据流和事件通信", + "处理用户交互事件(如选择feed、文章点击等)", + "集成全局通知系统(Toaster)和AI精灵面板" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "文章列表状态管理Store,负责聚合文章数据、处理分页加载、搜索过滤及与后端服务交互。基于Svelte的响应式系统实现。", + "file_path": "app/src/routes/main/stores/articles/list/index.svelte.ts", + "functions": [ + "create", + "generateTaskIdForUpdateFeed", + "refresh", + "updateFeeds", + "loadMore", + "notifyDatasourceUpdated", + "attachInitLoadingFuture" + ], + "importance_score": 1.0, + "interfaces": [ + "StoreType", + "Associations" + ], + "name": "index.svelte.ts", + "source_summary": "import { featuresApi, isSpecifyFeed } from '$lib/hybrid-apis/feed/impl';\nimport type { Article } from '$lib/types/article';\nimport { tick } from 'svelte';\nimport type { ArticlesGroup } from '../../../widgets/types';\nimport { create as createLoading, Status } from '../../loading.svelte';\nimport type { StoreType as LoadingStore } from '../../loading.svelte';\nimport type { StoreType as SearchStore } from '../search/index.svelte';\nimport type { StoreType as TasksStoreType } from '../../tasks.svelte';\n\nconst PAGING_SIZE = 20;\nconst FEED_ID_DEFAULT_FLAT_ON_ROOT = 'default_flat_on_root';\n\ntype StoreType = {\n\tgroupedArticles: ArticlesGroup[];\n\tfilteredArticles: ArticlesGroup[];\n\tassociatedPackageId: string | undefined;\n\tassociatedFeedId: string | undefined;\n\tarticles_init_loading: LoadingStore;\n\tarticles_continous_loading: LoadingStore;\n\tfiltered_articles_loading: LoadingStore;\n\trefresh: (waitUpdatePending: boolean) => Promise;\n\tupdateFeeds: () => Promise;\n\tloadMore: () => void;\n\tnotifyDatasourceUpdated: (continueLoading: boolean) => void;\n\tattachInitLoadingFuture: (future: Promise) => void;\n\tisFeedSpecified: boolean;\n};\n\ntype Associations = {\n\ttasks: TasksStoreType;\n\tsearch: SearchStore;\n};\n\nfunction create(associations: Associations): StoreType {\n\tlet associatedPackageId: string | undefined = $state();\n\tlet associatedFeedId = $state(FEED_ID_DEFAULT_FLAT_ON_ROOT);\n\tlet groupedArticles: ArticlesGroup[] = $state([]);\n\tlet filteredArticles: ArticlesGroup[] = $state([]);\n\tconst articles_init_loading = createLoading();\n\tconst articles_continous_loading = createLoading(Status.Completed);\n\tconst filtered_articles_loading = createLoading();\n\tconst searchAssociator: SearchStore = $state(associations.search);\n\tconst isFeedSpecified = $derived(isSpecifyFeed(associatedFeedId));\n\n\t$effect(() => {\n\t\tlet filterText = searchAssociator.filterText;\n\t\ttick().then(() => {\n\t\t\tfilterText = searchAssociator.filterText;\n\t\t\tif (filterText === '') {\n\t\t\t\tfilteredArticles = [];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst resultGroup = {\n\t\t\t\tname: '搜索结果',\n\t\t\t\tarticles: [] as Article[]\n\t\t\t};\n\n\t\t\tfeaturesApi\n\t\t\t\t.search_contents_by_keyword(filterText, 0, 10000)\n\t\t\t\t.then((articles) => {\n\t\t\t\t\tresultGroup.articles.push(...articles);\n\t\t\t\t\tfilteredArticles = [resultGroup];\n\t\t\t\t})\n\t\t\t\t.catch((e) => {\n\t\t\t\t\tconsole.error(e);\n\t\t\t\t\tfilteredArticles = [resultGroup];\n\t\t\t\t});\n\t\t});\n\t});\n\n\tfunction notifyDatasourceUpdated(continueLoading: boolean = false) {\n\t\t// TODO:当底层数据更新时,期望的是尝试拉取比当前列表更新的数据项,而非刷新并重制当前列表。\n\t\trefresh(false, continueLoading);\n\t}\n\n\tasync function updateFeeds(): Promise {\n\t\tif (!associatedPackageId || !associatedFeedId)\n\t\t\treturn Promise.reject(\n\t\t\t\t`then package id or feed id is null when updateFeeds called, packageId = ${associatedPackageId}, feedId = ${associatedFeedId}`\n\t\t\t);\n\n\t\tarticles_init_loading.load();\n\t\tconst taskId = generateTaskIdForUpdateFeed(associatedFeedId);\n\t\tconst { tasks } = associations;\n\t\tconst pending = tasks.queryPending(taskId);\n\t\tif (pending) {\n\t\t\tpending.promise.then(() => refresh(false)).catch((e) => articles_init_loading.error(e));\n\t\t\treturn pending.promise;\n\t\t}\n\t\tconst promise = featuresApi\n\t\t\t.update_feed_contents(associatedPackageId, associatedFeedId)\n\t\t\t.then(() => refresh(false))\n\t\t\t.catch((e) => articles_init_loading.error(e));\n\t\ttasks.addPending(taskId, promise);\n\t\treturn promise;\n\t}\n\n\tfunction attachInitLoadingFuture(future: Promise) {\n\t\tconsole.log('attachInitLoadingFuture...begin');\n\t\tarticles_init_loading.load();\n\t\tfuture\n\t\t\t.then(() => console.log('attachInitLoadingFuture...end by then'))\n\t\t\t.then(() => refresh(true))\n\t\t\t.catch((e) => {\n\t\t\t\tarticles_init_loading.error(e);\n\t\t\t\tconsole.log('attachInitLoadingFuture...end by error', e);\n\t\t\t});\n\t}\n\n\tasync function refresh(waitUpdatePending = false, continueLoading = false) {\n\t\treturn featuresApi\n\t\t\t.read_feed_contents(associatedFeedId, 0, PAGING_SIZE)\n\t\t\t.then((data) => {\n\t\t\t\tconst pending_groupedArticles = [];\n\t\t\t\tlet rolling_published_at = null;\n\t\t\t\tlet rolling_group = null;\n\t\t\t\tfor (const article of data) {\n\t\t\t\t\tconst published_at = article.published_at;\n\t\t\t\t\tif (published_at !== rolling_published_at) {\n\t\t\t\t\t\trolling_published_at = published_at;\n\t\t\t\t\t\trolling_group = {\n\t\t\t\t\t\t\tname: published_at,\n\t\t\t\t\t\t\tarticles: [article]\n\t\t\t\t\t\t};\n\t\t\t\t\t\tpending_groupedArticles.push(rolling_group);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\trolling_group?.articles.push(article);\n\t\t\t\t}\n\t\t\t\tgroupedArticles = pending_groupedArticles;\n\n\t\t\t\tconst { tasks } = associations;\n\t\t\t\tconst taskId = generateTaskIdForUpdateFeed(associatedFeedId);\n\t\t\t\tconst pending = tasks.queryPending(taskId);\n\t\t\t\tif (waitUpdatePending && pending) {\n\t\t\t\t\tarticles_init_loading.load();\n\t\t\t\t\tpending.promise.then(articles_init_loading.complete).catch(articles_init_loading.error);\n\t\t\t\t\treturn pending.promise;\n\t\t\t\t}\n\t\t\t\tif (!continueLoading) {\n\t\t\t\t\tarticles_init_loading.complete();\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((e) => articles_init_loading.error(e));\n\t}\n\n\tfunction loadMore() {\n\t\tif (articles_continous_loading.status === Status.Loading) return;\n\n\t\tarticles_continous_loading.load();\n\t\tlet rolling_group = groupedArticles[groupedArticles.length - 1];\n\t\tlet rolling_published_at = rolling_group.name;\n\t\tconst offset = groupedArticles\n\t\t\t.map((ag) => ag.articles.length)\n\t\t\t.reduce((accumulator, currentValue) => accumulator + currentValue);\n\t\tfeaturesApi.read_feed_contents(associatedFeedId, offset, PAGING_SIZE).then((data) => {\n\t\t\tarticles_continous_loading.complete();\n\t\t\tfor (const article of data) {\n\t\t\t\tconst published_at = article.published_at;\n\t\t\t\tif (published_at !== rolling_published_at) {\n\t\t\t\t\trolling_published_at = published_at;\n\t\t\t\t\trolling_group = {\n\t\t\t\t\t\tname: published_at,\n\t\t\t\t\t\tarticles: [article]\n\t\t\t\t\t};\n\t\t\t\t\tgroupedArticles.push(rolling_group);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\trolling_group?.articles.push(article);\n\t\t\t}\n\t\t\tgroupedArticles = groupedArticles.map((ag) => {\n\t\t\t\treturn { ...ag };\n\t\t\t});\n\t\t});\n\t}\n\n\treturn {\n\t\tget associatedPackageId() {\n\t\t\treturn associatedPackageId!;\n\t\t},\n\t\tset associatedPackageId(val: string) {\n\t\t\tassociatedPackageId = val;\n\t\t},\n\t\tget associatedFeedId() {\n\t\t\treturn associatedFeedId;\n\t\t},\n\t\tset associatedFeedId(value: string) {\n\t\t\tassociatedFeedId = value;\n\t\t},\n\t\tget groupedArticles() {\n\t\t\treturn groupedArticles;\n\t\t},\n\t\tget filteredArticles() {\n\t\t\treturn filteredArticles;\n\t\t},\n\t\tget articles_init_loading() {\n\t\t\treturn articles_init_loading;\n\t\t},\n\t\tget articles_continous_loading() {\n\t\t\treturn articles_continous_loading;\n\t\t},\n\t\tget filtered_articles_loading() {\n\t\t\treturn filtered_articles_loading;\n\t\t},\n\t\trefresh,\n\t\tupdateFeeds,\n\t\tloadMore,\n\t\tnotifyDatasourceUpdated,\n\t\tattachInitLoadingFuture,\n\t\tget isFeedSpecified() {\n\t\t\treturn isFeedSpecified;\n\t\t}\n\t};\n}\n\nfunction generateTaskIdForUpdateFeed(associatedFeedId: string) {\n\treturn `Feed Updating For Feed ID = ${associatedFeedId}`;\n}\n\nexport type { StoreType };\nexport { create };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.72, + "coupling_factor": 0.875, + "cyclomatic_complexity": 11.0, + "depth_of_inheritance": 0, + "lines_of_code": 221, + "number_of_classes": 0, + "number_of_functions": 7 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": false, + "line_number": 1, + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 1, + "name": "isSpecifyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "import", + "is_external": true, + "line_number": 2, + "name": "tick", + "path": "svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 3, + "name": "Article", + "path": "$lib/types/article", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 4, + "name": "ArticlesGroup", + "path": "../../../widgets/types", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 5, + "name": "createLoading", + "path": "../../loading.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 5, + "name": "Status", + "path": "../../loading.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 6, + "name": "LoadingStore", + "path": "../../loading.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 7, + "name": "SearchStore", + "path": "../search/index.svelte", + "version": null + }, + { + "dependency_type": "import", + "is_external": false, + "line_number": 8, + "name": "TasksStoreType", + "path": "../../tasks.svelte", + "version": null + } + ], + "detailed_description": "该组件是Svelte应用中的核心状态管理模块(Store),用于管理文章列表的展示逻辑。它封装了文章分组、分页加载、搜索过滤、数据刷新等关键功能。通过依赖注入方式关联tasks和search两个外部store,形成协作关系。使用$state和$derived实现响应式状态,利用$effect监听搜索条件变化并触发内容检索。支持初始化加载、连续加载更多、强制刷新、更新订阅源等操作,并通过loading store管理不同场景下的加载状态。整体采用工厂模式(create函数)生成具名store实例,符合Svelte stores规范。", + "interfaces": [ + { + "description": "定义文章列表Store的完整接口结构,包含状态字段和行为方法", + "interface_type": "type", + "name": "StoreType", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "内部类型,定义该Store所依赖的其他Store引用集合", + "interface_type": "type", + "name": "Associations", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "工厂函数,创建并返回一个具备完整功能的文章列表Store实例", + "interface_type": "function", + "name": "create", + "parameters": [ + { + "description": "注入的依赖Store集合", + "is_optional": false, + "name": "associations", + "param_type": "Associations" + } + ], + "return_type": "StoreType", + "visibility": "public" + }, + { + "description": "生成用于任务追踪的唯一任务ID", + "interface_type": "function", + "name": "generateTaskIdForUpdateFeed", + "parameters": [ + { + "description": "目标Feed的ID", + "is_optional": false, + "name": "associatedFeedId", + "param_type": "string" + } + ], + "return_type": "string", + "visibility": "private" + } + ], + "responsibilities": [ + "管理文章列表的分组显示状态(按发布时间聚合)", + "协调与后端API的交互(加载、刷新、更新feed内容)", + "处理分页逻辑(初始加载与滚动加载更多)", + "响应搜索输入变化并更新过滤结果", + "维护多个加载状态(初始化、连续加载、过滤加载)" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "提供文章阅读状态管理与内容刷新功能的Svelte store控制器", + "file_path": "app/src/routes/main/stores/reader.svelte.ts", + "functions": [ + "create", + "markAsRead", + "refreshByEnhancedScraper" + ], + "importance_score": 1.0, + "interfaces": [ + "StoreType", + "Associates" + ], + "name": "reader.svelte.ts", + "source_summary": "import { featuresApi } from '$lib/hybrid-apis/feed/impl';\nimport type { Article } from '$lib/types/article';\nimport { Status } from './loading.svelte';\nimport type { StoreType as TasksStoreType } from './tasks.svelte';\n\ntype Associates = {\n\ttasks: TasksStoreType;\n};\n\ntype StoreType = {\n\tmarkAsRead: (articleId: number) => Promise;\n\trefreshByEnhancedScraper: (articleId: number, url: string) => Promise
;\n};\n\nfunction create(associates: Associates): StoreType {\n\tconst { tasks } = associates;\n\tfunction markAsRead(articleId: number) {\n\t\treturn featuresApi.mark_as_read(articleId);\n\t}\n\n\tasync function refreshByEnhancedScraper(articleId: number, url: string): Promise
{\n\t\tconst taskId = `Article Updating For ArticleID = ${articleId}`;\n\t\tconst pending = tasks.queryPending(taskId);\n\t\tif (pending) {\n\t\t\tif (pending.loadingStore.status === Status.Error) {\n\t\t\t\ttasks.remove(pending);\n\t\t\t} else {\n\t\t\t\treturn pending.promise as Promise
;\n\t\t\t}\n\t\t}\n\n\t\tconst promise = featuresApi\n\t\t\t.update_article_by_source(articleId, url)\n\t\t\t.then(() => featuresApi.query_by_id(articleId));\n\n\t\ttasks.addPending(taskId, promise);\n\t\treturn promise;\n\t}\n\n\treturn {\n\t\tmarkAsRead,\n\t\trefreshByEnhancedScraper\n\t};\n}\n\nexport type { StoreType };\nexport { create };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.85, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 47, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "api", + "is_external": false, + "line_number": 1, + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 2, + "name": "Article", + "path": "$lib/types/article", + "version": null + }, + { + "dependency_type": "constant", + "is_external": false, + "line_number": 3, + "name": "Status", + "path": "./loading.svelte", + "version": null + }, + { + "dependency_type": "store", + "is_external": false, + "line_number": 4, + "name": "TasksStoreType", + "path": "./tasks.svelte", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte store实现,用于管理文章的阅读状态和内容刷新逻辑。它通过create函数接收关联依赖(如tasks store),并返回包含markAsRead和refreshByEnhancedScraper两个方法的StoreType对象。markAsRead调用API标记文章为已读;refreshByEnhancedScraper则实现了智能去重的任务调度机制:先检查是否存在相同任务ID的待处理请求,若存在且出错则清除,若正在进行则复用原有Promise,否则创建新任务并注册到tasks store中。", + "interfaces": [ + { + "description": null, + "interface_type": "type", + "name": "StoreType", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "markAsRead", + "param_type": "(articleId: number) => Promise" + }, + { + "description": null, + "is_optional": false, + "name": "refreshByEnhancedScraper", + "param_type": "(articleId: number, url: string) => Promise
" + } + ], + "return_type": null, + "visibility": "export" + }, + { + "description": null, + "interface_type": "type", + "name": "Associates", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "tasks", + "param_type": "TasksStoreType" + } + ], + "return_type": null, + "visibility": "local" + } + ], + "responsibilities": [ + "管理文章的已读状态更新", + "协调文章内容的增强式刷新流程", + "通过任务去重避免重复网络请求", + "集成外部API与本地任务调度系统", + "提供类型安全的store接口供UI层使用" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "负责管理侧边栏对话窗口的状态与交互逻辑,封装了与文章助手的聊天功能。", + "file_path": "app/src/routes/main/stores/sprite.svelte.ts", + "functions": [ + "create", + "send", + "toggle", + "cleanUp" + ], + "importance_score": 1.0, + "interfaces": [ + "StoreType", + "ConversationInput", + "ConversationMessage" + ], + "name": "sprite.svelte.ts", + "source_summary": "import type {\n ConversationInput,\n ConversationMessage,\n} from \"$lib/hybrid-apis/feed/types\";\nimport {\n Status,\n create as createLoadingStore,\n type StoreType as LoadingStore,\n} from \"./loading.svelte\";\nimport { featuresApi } from \"$lib/hybrid-apis/feed/impl\";\nimport type { IContext } from \"./context\";\n\ntype StoreType = {\n opened: boolean;\n loading: LoadingStore;\n toggle: () => void;\n history: ConversationMessage[];\n send: (input: ConversationInput) => Promise;\n isLoading: boolean;\n};\n\nfunction create(context: IContext): StoreType {\n let opened = $state(false);\n let history = $state([]);\n const loading = createLoadingStore();\n\n function cleanUp() {\n history = [];\n loading.unset();\n }\n\n async function send(input: ConversationInput): Promise {\n if (loading.status === Status.Loading) return false;\n\n loading.load();\n\n try {\n const message: ConversationMessage = {\n role: \"user\",\n mtype: input.mtype,\n payload: input.payload,\n created_at: `${Date.now()}`,\n };\n history.push(message);\n\n const replyText = await featuresApi.chat_with_article_assistant(\n context.currentArticle?.id,\n message.payload,\n history,\n );\n\n const replyMessage: ConversationMessage = {\n role: \"system\",\n mtype: \"text\",\n payload: replyText,\n created_at: `${Date.now()}`,\n };\n history.push(replyMessage);\n loading.complete();\n return true;\n } catch (e) {\n console.error(\"error occurs when the store.send executing\", e);\n loading.error(new Error(String(e)));\n return false;\n }\n }\n\n return {\n get loading() {\n return loading;\n },\n get opened() {\n return opened;\n },\n get history() {\n return history;\n },\n toggle: () => {\n opened = !opened;\n if (!opened) cleanUp();\n },\n get isLoading() {\n return loading.status === Status.Loading;\n },\n send,\n };\n}\n\nexport { create };\nexport type { StoreType };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.4, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 90, + "number_of_classes": 0, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "service", + "is_external": true, + "line_number": 4, + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "store", + "is_external": false, + "line_number": 2, + "name": "loading.svelte", + "path": "./loading.svelte", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte状态存储模块,用于管理一个可打开/关闭的对话界面(Sprite)的状态。它维护了对话历史记录、加载状态和可见性,并提供了发送消息给文章助手的功能。当用户发送输入时,组件会调用外部API进行处理,并将用户和系统的消息依次添加到历史中。同时通过loading store管理异步请求状态,在出错时进行错误捕获与报告。清理逻辑会在关闭窗口时重置历史和加载状态。", + "interfaces": [ + { + "description": "定义了对外暴露的状态结构和方法集合,包括opened、history、loading、toggle、send等", + "interface_type": "type", + "name": "StoreType", + "parameters": [], + "return_type": null, + "visibility": "exported" + }, + { + "description": "工厂函数,用于创建并初始化Store实例", + "interface_type": "function", + "name": "create", + "parameters": [ + { + "description": "上下文对象,包含当前文章等运行时信息", + "is_optional": false, + "name": "context", + "param_type": "IContext" + } + ], + "return_type": "StoreType", + "visibility": "exported" + }, + { + "description": "发送消息并更新对话历史,返回是否成功", + "interface_type": "function", + "name": "send", + "parameters": [ + { + "description": "用户输入内容", + "is_optional": false, + "name": "input", + "param_type": "ConversationInput" + } + ], + "return_type": "Promise", + "visibility": "internal" + } + ], + "responsibilities": [ + "管理对话窗口的打开/关闭状态", + "维护与展示对话消息的历史记录", + "协调与文章助手API的异步通信", + "管理UI加载与错误状态", + "提供状态清理机制以释放资源" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "管理用户订阅源(feeds)的聚合状态与操作,提供本地状态存储及远程API同步能力。", + "file_path": "app/src/routes/main/stores/feeds.svelte.ts", + "functions": [ + "create", + "refresh", + "findPackagesOwnerByFeedId", + "addFeedsPackage", + "removeFeedsPackage", + "renameFeedsPackage", + "addFeed", + "removeFeed", + "renameFeed" + ], + "importance_score": 1.0, + "interfaces": [ + "StoreType", + "FeedsPackage", + "FeedTargetDescription", + "LoadingStore", + "Status" + ], + "name": "feeds.svelte.ts", + "source_summary": "import { featuresApi } from '$lib/hybrid-apis/feed/impl';\nimport type { FeedsPackage, FeedTargetDescription } from '$lib/hybrid-apis/feed/types';\nimport {\n\tStatus,\n\tcreate as createLoadingStore,\n\ttype StoreType as LoadingStore\n} from './loading.svelte';\n\ntype StoreType = {\n\tloadingStore: LoadingStore;\n\tfeedPackages: FeedsPackage[];\n\trefresh: () => Promise;\n\taddFeedsPackage: (feedsPackage: FeedsPackage) => Promise;\n\tremoveFeedsPackage: (packageId: string) => Promise;\n\trenameFeedsPackage: (packageId: string, newName: string) => Promise;\n\taddFeed: (packageId: string, ftd: FeedTargetDescription) => Promise;\n\tremoveFeed: (packageId: string, feedId: string) => Promise;\n\trenameFeed: (packageId: string, feedId: string, newName: string) => Promise;\n\tfindPackagesOwnerByFeedId: (feedId: string) => FeedsPackage | undefined;\n};\n\nfunction create(): StoreType {\n\tconst loadingStore = createLoadingStore(Status.Loading);\n\tlet feedPackages: FeedsPackage[] = $state([]);\n\n\tasync function refresh() {\n\t\treturn featuresApi\n\t\t\t.get_feeds_packages()\n\t\t\t.then((data) => {\n\t\t\t\tfeedPackages = data;\n\t\t\t\tloadingStore.complete();\n\t\t\t})\n\t\t\t.catch((e) => {\n\t\t\t\tloadingStore.error(e);\n\t\t\t});\n\t}\n\n\tfunction findPackagesOwnerByFeedId(feedId: string): FeedsPackage | undefined {\n\t\treturn feedPackages.find((feedPackage) => {\n\t\t\treturn feedPackage.feeds.findIndex((feed) => feed.id === feedId) >= 0;\n\t\t});\n\t}\n\n\tfunction addFeedsPackage(feedsPackage: FeedsPackage): Promise {\n\t\treturn featuresApi.add_feeds_package(feedsPackage);\n\t}\n\n\tfunction removeFeedsPackage(packageId: string): Promise {\n\t\treturn featuresApi.remove_feeds_package(packageId);\n\t}\n\n\tfunction renameFeedsPackage(packageId: string, newName: string): Promise {\n\t\treturn featuresApi.rename_feeds_package(packageId, newName);\n\t}\n\n\tfunction addFeed(packageId: string, ftd: FeedTargetDescription): Promise {\n\t\treturn featuresApi.add_feed(packageId, ftd);\n\t}\n\n\tfunction removeFeed(packageId: string, feedId: string): Promise {\n\t\treturn featuresApi.remove_feed(packageId, feedId);\n\t}\n\n\tfunction renameFeed(packageId: string, feedId: string, newName: string): Promise {\n\t\treturn featuresApi.rename_feed(packageId, feedId, newName);\n\t}\n\n\treturn {\n\t\tloadingStore,\n\t\tget feedPackages() {\n\t\t\treturn feedPackages;\n\t\t},\n\t\trefresh,\n\t\taddFeedsPackage,\n\t\tremoveFeedsPackage,\n\t\trenameFeedsPackage,\n\t\taddFeed,\n\t\tremoveFeed,\n\t\trenameFeed,\n\t\tfindPackagesOwnerByFeedId\n\t};\n}\n\nexport type { StoreType };\n\nexport { create };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.25, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 86, + "number_of_classes": 0, + "number_of_functions": 9 + }, + "dependencies": [ + { + "dependency_type": "api-client", + "is_external": false, + "line_number": 1, + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "state-utils", + "is_external": false, + "line_number": 4, + "name": "LoadingStore", + "path": "./loading.svelte", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte状态管理模块,用于在前端维护用户订阅包(FeedsPackage)及其内部订阅项(Feed)的集合。它封装了对后端feeds服务的所有CRUD操作,并通过loading.svelte提供的加载状态机制统一处理异步请求的状态反馈(加载中、成功、失败)。组件暴露一个`create`工厂函数返回响应式store实例,包含当前feedPackages列表和多个操作方法。所有修改操作均通过`featuresApi`代理到后端实现,读取操作如`findPackagesOwnerByFeedId`则在本地内存中完成。支持自动刷新、增删改包/订阅等功能,是feeds功能域的核心协调者。", + "interfaces": [ + { + "description": "定义feeds store的结构,包括状态字段和可调用方法", + "interface_type": "type", + "name": "StoreType", + "parameters": [], + "return_type": null, + "visibility": "exported" + }, + { + "description": "工厂函数,创建并返回一个新的feeds store实例", + "interface_type": "function", + "name": "create", + "parameters": [], + "return_type": "StoreType", + "visibility": "exported" + }, + { + "description": "从后端重新拉取所有feeds packages并更新本地状态", + "interface_type": "method", + "name": "refresh", + "parameters": [], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "添加新的feeds package并通过API持久化", + "interface_type": "method", + "name": "addFeedsPackage", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "feedsPackage", + "param_type": "FeedsPackage" + } + ], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "根据ID删除指定的feeds package", + "interface_type": "method", + "name": "removeFeedsPackage", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "packageId", + "param_type": "string" + } + ], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "重命名指定ID的feeds package", + "interface_type": "method", + "name": "renameFeedsPackage", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "packageId", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "newName", + "param_type": "string" + } + ], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "向指定package添加新的feed", + "interface_type": "method", + "name": "addFeed", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "packageId", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "ftd", + "param_type": "FeedTargetDescription" + } + ], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "从指定package中移除feed", + "interface_type": "method", + "name": "removeFeed", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "packageId", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "feedId", + "param_type": "string" + } + ], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "重命名指定feed", + "interface_type": "method", + "name": "renameFeed", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "packageId", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "feedId", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "newName", + "param_type": "string" + } + ], + "return_type": "Promise", + "visibility": "internal" + }, + { + "description": "根据feed ID查找其所属的package", + "interface_type": "method", + "name": "findPackagesOwnerByFeedId", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "feedId", + "param_type": "string" + } + ], + "return_type": "FeedsPackage | undefined", + "visibility": "internal" + } + ], + "responsibilities": [ + "提供响应式的feeds数据存储与访问", + "协调本地状态与远程API的数据同步", + "封装feeds相关的所有业务操作接口", + "管理异步操作的加载状态与错误处理", + "实现基于ID的feed归属查询逻辑" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "核心状态管理容器,协调文章、任务、订阅源等子模块的状态与行为。", + "file_path": "app/src/routes/main/stores/index.svelte.ts", + "functions": [ + "createStore", + "setCurrentArticle", + "getCurrentArticle", + "scheduleUpdate", + "onSelectToday", + "onSelectWeekend", + "onSelectFavorite", + "onSelectUnread", + "setCurrentFeedId" + ], + "importance_score": 1.0, + "interfaces": [ + "IContext" + ], + "name": "index.svelte.ts", + "source_summary": "import type { Article } from '$lib/types/article';\n\nimport {\n\tfeaturesApi,\n\tisRecentFamilyFeed,\n\tisSpecifyFeed,\n\tSPECIFY_FEED_IDSET\n} from '$lib/hybrid-apis/feed/impl';\nimport { create as createArticles } from './articles/index.svelte';\nimport { create as createTasks } from './tasks.svelte';\nimport { create as createFeeds } from './feeds.svelte';\nimport { create as createReader } from './reader.svelte';\nimport { create as createSprite } from './sprite.svelte';\nimport { currentDateText } from '$lib/utils/date';\nimport type { IContext } from './context';\n\nlet globalSharedScheduleUpdatingFuture: Promise | undefined = undefined;\nlet has_update_feeds_on_boot = false;\n\nfunction createStore() {\n\tlet currentFeedId: string | undefined = $state(undefined);\n\tlet currentArticle: Article | null = $state(null);\n\n\tconst context: IContext = {\n\t\tget currentArticle() {\n\t\t\treturn currentArticle!;\n\t\t},\n\n\t\tget currentFeedId() {\n\t\t\treturn currentFeedId!;\n\t\t}\n\t};\n\n\tconst tasks = createTasks();\n\tconst articles = createArticles(tasks);\n\tconst feeds = createFeeds();\n\tconst reader = createReader({ tasks });\n\tconst sprite = createSprite(context);\n\n\tconst isTodaySelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.TODAY_FILTER);\n\tconst isWeekendSelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.WEEKEND_FILTER);\n\tconst isFavoriteSelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.FAVORITE_FILTER);\n\tconst isUnreadSelected = $derived(currentFeedId === SPECIFY_FEED_IDSET.UNREAD_FILTER);\n\n\tconst isFeedSpecified = $derived(isSpecifyFeed(currentFeedId));\n\n\tfunction setCurrentArticle(value: Article) {\n\t\tcurrentArticle = value;\n\t}\n\n\tasync function getCurrentArticle(): Promise
{\n\t\tif (!currentArticle) {\n\t\t\treturn Promise.reject('the current article id is null!');\n\t\t}\n\t\treturn featuresApi.query_by_id(currentArticle.id);\n\t}\n\n\tasync function scheduleUpdate() {\n\t\tif (globalSharedScheduleUpdatingFuture) return;\n\t\tlet resolve: (() => void) | null = null;\n\t\tlet reject: (() => void) | null = null;\n\t\tglobalSharedScheduleUpdatingFuture = new Promise((r1, r2) => {\n\t\t\tresolve = r1;\n\t\t\treject = r2;\n\t\t});\n\t\tlet haveTaskCompleted = false;\n\t\tconst { list } = articles;\n\t\tfor (const feedPackage of feeds.feedPackages) {\n\t\t\tfor (const feed of feedPackage.feeds) {\n\t\t\t\tconst promise = featuresApi.update_feed_contents(feedPackage.id, feed.id);\n\t\t\t\tpromise.then(() => {\n\t\t\t\t\thaveTaskCompleted = true;\n\t\t\t\t\tlist.notifyDatasourceUpdated(true);\n\t\t\t\t});\n\t\t\t\ttasks.addPending(`Schedule Updating For ${feedPackage.name} - ${feed.name}`, promise);\n\t\t\t\ttry {\n\t\t\t\t\tawait promise;\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error(`Major schedule update failured for ${feedPackage.name} - ${feed.name}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (haveTaskCompleted) {\n\t\t\tresolve!();\n\t\t\tlist.notifyDatasourceUpdated(false);\n\t\t} else reject!();\n\t}\n\n\tfunction onSelectToday() {\n\t\tsetCurrentFeedId(SPECIFY_FEED_IDSET.TODAY_FILTER);\n\t}\n\n\tfunction onSelectWeekend() {\n\t\tsetCurrentFeedId(SPECIFY_FEED_IDSET.WEEKEND_FILTER);\n\t}\n\n\tfunction onSelectFavorite() {\n\t\tsetCurrentFeedId(SPECIFY_FEED_IDSET.FAVORITE_FILTER);\n\t}\n\n\tfunction onSelectUnread() {\n\t\tsetCurrentFeedId(SPECIFY_FEED_IDSET.UNREAD_FILTER);\n\t}\n\n\tasync function setCurrentFeedId(value: string) {\n\t\tconst feedPackage = feeds.findPackagesOwnerByFeedId(value);\n\t\tlet packageId = undefined;\n\t\tconst isFeedSpecified = isSpecifyFeed(value);\n\t\tif (!feedPackage) {\n\t\t\tif (!isFeedSpecified)\n\t\t\t\treturn Promise.reject(\n\t\t\t\t\t`unexpect error, the package owner of feedId = ${value} was not found`\n\t\t\t\t);\n\t\t\telse packageId = 'VIRTUAL_NO_PACKAGE_SPECIFY_FEED';\n\t\t} else {\n\t\t\tpackageId = feedPackage.id;\n\t\t}\n\n\t\tcurrentFeedId = value;\n\t\tconst { list } = articles;\n\t\tlist.associatedFeedId = currentFeedId;\n\t\tlist.associatedPackageId = packageId;\n\t\tawait list.refresh(true);\n\t\tcurrentArticle = list.groupedArticles[0]?.articles[0];\n\n\t\tif (!currentArticle) {\n\t\t\tif (!isFeedSpecified) {\n\t\t\t\tawait list.updateFeeds();\n\t\t\t} else if (isRecentFamilyFeed(value)) {\n\t\t\t\tif (!globalSharedScheduleUpdatingFuture) scheduleUpdate();\n\t\t\t\tlist.attachInitLoadingFuture(globalSharedScheduleUpdatingFuture!);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 处理初始化流程\n\t$effect(() => {\n\t\tconst { list } = articles;\n\t\tfeeds.refresh().then(() => {\n\t\t\tsetCurrentFeedId(SPECIFY_FEED_IDSET.TODAY_FILTER).then(() => {\n\t\t\t\t// 如果本次feed对应的内容不是当天且当天更新过则全力昂Feed更新。\n\t\t\t\t// TODO:应根据schedule最后更新日期判断。\n\t\t\t\tconst lastest_article = list.groupedArticles[0]?.articles[0];\n\t\t\t\tif (\n\t\t\t\t\t!has_update_feeds_on_boot &&\n\t\t\t\t\t(!lastest_article || lastest_article?.created_at != currentDateText())\n\t\t\t\t) {\n\t\t\t\t\thas_update_feeds_on_boot = true;\n\t\t\t\t\tscheduleUpdate();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n\n\treturn {\n\t\tget feeds() {\n\t\t\treturn feeds;\n\t\t},\n\t\tget currentFeedId() {\n\t\t\treturn currentFeedId;\n\t\t},\n\t\tget currentArticle() {\n\t\t\treturn currentArticle;\n\t\t},\n\t\tget articles() {\n\t\t\treturn articles;\n\t\t},\n\t\tget tasks() {\n\t\t\treturn tasks;\n\t\t},\n\t\tget reader() {\n\t\t\treturn reader;\n\t\t},\n\t\tget sprite() {\n\t\t\treturn sprite;\n\t\t},\n\t\tsetCurrentFeedId,\n\t\tsetCurrentArticle,\n\t\tgetCurrentArticle,\n\t\tscheduleUpdate,\n\t\tonSelectToday,\n\t\tonSelectWeekend,\n\t\tonSelectFavorite,\n\t\tonSelectUnread,\n\t\tget isTodaySelected() {\n\t\t\treturn isTodaySelected;\n\t\t},\n\t\tget isWeekendSelected() {\n\t\t\treturn isWeekendSelected;\n\t\t},\n\t\tget isFavoriteSelected() {\n\t\t\treturn isFavoriteSelected;\n\t\t},\n\t\tget isUnreadSelected() {\n\t\t\treturn isUnreadSelected;\n\t\t},\n\t\tget isFeedSpecified() {\n\t\t\treturn isFeedSpecified;\n\t\t}\n\t};\n}\n\nexport { createStore };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.78, + "coupling_factor": 0.5625, + "cyclomatic_complexity": 14.0, + "depth_of_inheritance": 0, + "lines_of_code": 203, + "number_of_classes": 0, + "number_of_functions": 13 + }, + "dependencies": [ + { + "dependency_type": "type", + "is_external": false, + "line_number": 1, + "name": "Article", + "path": "$lib/types/article", + "version": null + }, + { + "dependency_type": "variable", + "is_external": false, + "line_number": 4, + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 5, + "name": "isRecentFamilyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 6, + "name": "isSpecifyFeed", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "constant", + "is_external": false, + "line_number": 7, + "name": "SPECIFY_FEED_IDSET", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 8, + "name": "createArticles", + "path": "./articles/index.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 9, + "name": "createTasks", + "path": "./tasks.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 10, + "name": "createFeeds", + "path": "./feeds.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 11, + "name": "createReader", + "path": "./reader.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 12, + "name": "createSprite", + "path": "./sprite.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 13, + "name": "currentDateText", + "path": "$lib/utils/date", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 14, + "name": "IContext", + "path": "./context", + "version": null + } + ], + "detailed_description": "该组件是Svelte应用中的核心状态存储模块,通过`createStore`函数创建一个集中式的状态管理器。它整合了feeds、articles、tasks、reader和sprite等多个子store,并对外暴露统一的访问接口。组件利用Svelte的反应式特性($state, $derived, $effect)实现自动更新。主要功能包括:当前feed和文章的管理、特定筛选条件(今日/周末/收藏/未读)的选择逻辑、定时内容更新调度、以及初始化时的数据加载控制。特别地,通过全局共享的`globalSharedScheduleUpdatingFuture`确保更新任务不被重复触发。", + "interfaces": [ + { + "description": "定义上下文对象的结构,用于在store间传递共享状态", + "interface_type": "type", + "name": "IContext", + "parameters": [], + "return_type": null, + "visibility": "imported" + }, + { + "description": "工厂函数,创建并返回一个新的store实例,包含所有子模块和操作方法", + "interface_type": "function", + "name": "createStore", + "parameters": [], + "return_type": "object", + "visibility": "exported" + } + ], + "responsibilities": [ + "作为应用主界面的核心状态容器,聚合多个子状态模块", + "管理当前选中的feed和文章,支持基于虚拟feed ID的特殊筛选视图", + "协调定时内容更新流程,避免并发执行", + "处理应用启动时的初始化数据加载逻辑", + "提供统一的API供UI层调用以改变状态或获取数据" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "任务状态管理Store,用于跟踪异步操作的加载状态", + "file_path": "app/src/routes/main/stores/tasks.svelte.ts", + "functions": [ + "createPending", + "create" + ], + "importance_score": 1.0, + "interfaces": [ + "StoreType", + "PendingItem" + ], + "name": "tasks.svelte.ts", + "source_summary": "import type { StoreType as LoadingStore } from './loading.svelte';\nimport { create as createLoadingStore, Status } from './loading.svelte';\n\ntype PendingItem = {\n\tdescription: string;\n\tloadingStore: LoadingStore;\n\tpromise: Promise;\n};\n\ntype StoreType = {\n\tpendingStatus: Status;\n\tpendingStatusText: string;\n\tpendings: PendingItem[];\n\taddPending: (description: string, promise: Promise) => void;\n\tqueryPending: (description: string) => PendingItem | undefined;\n\tremove: (pending: PendingItem) => void;\n};\n\nfunction createPending(description: string, promise: Promise): PendingItem {\n\tconst loadingStore = createLoadingStore(Status.Loading);\n\tpromise.then(loadingStore.complete).catch(loadingStore.error);\n\treturn {\n\t\tdescription,\n\t\tloadingStore,\n\t\tpromise\n\t};\n}\n\nfunction create(): StoreType {\n\tlet pendings: PendingItem[] = $state([]);\n\tconst pendingStatus: Status = $derived.by(() => {\n\t\tlet hasError = false;\n\t\tfor (const pending of pendings) {\n\t\t\tif (pending.loadingStore.status === Status.Loading) return Status.Loading;\n\t\t\tif (pending.loadingStore.status === Status.Error) hasError = true;\n\t\t}\n\t\treturn hasError ? Status.Error : Status.Completed;\n\t});\n\n\tconst pendingStatusText = $derived.by(() => {\n\t\tswitch (pendingStatus) {\n\t\t\tcase Status.Loading:\n\t\t\t\tconst loadingPendings = pendings.filter((p) => p.loadingStore.status === Status.Loading);\n\t\t\t\treturn `处理中...${loadingPendings.length}项`;\n\t\t\tcase Status.Completed:\n\t\t\t\treturn '就绪';\n\t\t\tcase Status.Error:\n\t\t\t\treturn '出现错误,点击查看详情';\n\t\t}\n\t});\n\n\tfunction remove(p: PendingItem) {\n\t\tpendings = pendings.filter((pending) => pending !== p);\n\t}\n\n\tfunction addPending(description: string, promise: Promise) {\n\t\tconst pending = createPending(description, promise);\n\t\tpromise.then(() => {\n\t\t\tpendings = pendings.filter((pending) => pending.loadingStore.status !== Status.Completed);\n\t\t});\n\t\tpendings.push(pending);\n\t}\n\n\tfunction queryPending(description: string) {\n\t\treturn pendings.find((pending) => pending.description === description);\n\t}\n\n\treturn {\n\t\tget pendingStatus() {\n\t\t\treturn pendingStatus;\n\t\t},\n\t\tget pendingStatusText() {\n\t\t\treturn pendingStatusText;\n\t\t},\n\t\tget pendings() {\n\t\t\treturn pendings;\n\t\t},\n\t\taddPending,\n\t\tqueryPending,\n\t\tremove\n\t};\n}\n\nexport type { StoreType };\nexport { create };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.35, + "cyclomatic_complexity": 7.0, + "depth_of_inheritance": 0, + "lines_of_code": 85, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "type-import", + "is_external": false, + "line_number": 1, + "name": "LoadingStore", + "path": "./loading.svelte", + "version": null + }, + { + "dependency_type": "function-import", + "is_external": false, + "line_number": 2, + "name": "createLoadingStore", + "path": "./loading.svelte", + "version": null + }, + { + "dependency_type": "enum-import", + "is_external": false, + "line_number": 2, + "name": "Status", + "path": "./loading.svelte", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte状态管理模块,负责集中管理应用中所有异步任务的执行状态。它通过封装loading状态、维护待处理任务队列,并提供统一的状态反馈(如'处理中...'、'就绪'、'出现错误'等)来实现对异步操作生命周期的可视化控制。组件使用Svelte的$state和$derived响应式语法,自动计算整体任务状态和状态文本,并对外暴露添加、查询和移除任务的操作接口。", + "interfaces": [ + { + "description": "定义任务管理Store的公开接口,包含状态属性和操作方法", + "interface_type": "type", + "name": "StoreType", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "表示单个待处理任务的数据结构,包含描述、加载状态和关联的Promise", + "interface_type": "type", + "name": "PendingItem", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "工厂函数,创建并返回一个新的任务管理Store实例", + "interface_type": "function", + "name": "create", + "parameters": [], + "return_type": "StoreType", + "visibility": "public" + }, + { + "description": "创建一个新的待处理任务项", + "interface_type": "function", + "name": "createPending", + "parameters": [ + { + "description": "任务描述文本", + "is_optional": false, + "name": "description", + "param_type": "string" + }, + { + "description": "关联的异步操作Promise", + "is_optional": false, + "name": "promise", + "param_type": "Promise" + } + ], + "return_type": "PendingItem", + "visibility": "private" + } + ], + "responsibilities": [ + "管理异步任务的生命周期状态", + "聚合多个并行任务的整体状态", + "提供任务状态的响应式更新机制", + "生成用户友好的状态显示文本", + "与loading状态组件协同工作" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "Svelte组件,用于展示文章列表,支持分组显示、过滤、加载状态管理及用户交互。", + "file_path": "app/src/routes/main/widgets/ArticlesList.svelte", + "functions": [ + "onloadFeedContents", + "render_articles_list" + ], + "importance_score": 1.0, + "interfaces": [ + "ArticlesListProps" + ], + "name": "ArticlesList.svelte", + "source_summary": "\n\n{#if articles_init_loading.status === Status.Loading}\n\t\n{:else if store.articles_init_loading.status === Status.Completed}{:else if store.articles_init_loading.status === Status.Error}\n\t\n{/if}\n\n{#if store.articles_init_loading.status === Status.Completed}\n\t\n\t{@render render_articles_list(isFilterActived ? store.filteredArticles : store.groupedArticles)}\n{:else if store.groupedArticles.length !== 0}\n\t\n\t{@render render_articles_list(isFilterActived ? store.filteredArticles : store.groupedArticles)}\n{/if}\n\n{#snippet render_articles_list(groups: ArticlesGroup[])}\n\t
\n\t\t{#each groups as { name, articles } (name)}\n\t\t\t
{name}
\n\t\t\t{#each articles as article (article.id)}\n\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\t onArticlePressed(article)}\n\t\t\t\t\t>\n\t\t\t\t\t\t{#if !article.has_read && selectedArticle?.id !== article.id}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t{/if}\n\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t
{article.title}
\n\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t{article.head_read}\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t{/each}\n\t\t{/each}\n\t\t{#if !isFilterActived}\n\t\t\t{#if store.groupedArticles.length !== 0}\n\t\t\t\t
\n\t\t\t\t{#if articles_continous_loading.status === Status.Completed}\n\t\t\t\t\t\n\t\t\t\t{:else}\n\t\t\t\t\t\n\t\t\t\t{/if}\n\t\t\t{:else if !isFeedSpecified}\n\t\t\t\t{#if articles_init_loading.status !== Status.Loading}\n\t\t\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\n\t\t\n\t\t
\n\t\t\t{#each store.history as bubble (bubble.created_at)}\n\t\t\t\t{#if bubble.role !== 'user'}\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t

Copilot

\n\t\t\t\t\t\t\t\t{toDateText(bubble.created_at).toLocaleString()}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\n\t\t\t\t{:else}\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t

{$_('aisprite.chat_me')}

\n\t\t\t\t\t\t\t\t{toDateText(bubble.created_at).toLocaleString()}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{/if}\n\t\t\t{/each}\n\n\t\t\t{#if store.isLoading}\n\t\t\t\t\n\t\t\t{/if}\n\t\t
\n\t\t
\n\t\t\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t{:else}\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{/if}\n\t\t\t\n\t\t
\n\t\n{/if}\n\n
\n\t\n\t\t\n\t\tCopilot\n\t\n
\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 7.0, + "cyclomatic_complexity": 9.0, + "depth_of_inheritance": 0, + "lines_of_code": 186, + "number_of_classes": 0, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": null, + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "AISpriteProps", + "path": "../widgets/types", + "version": null + }, + { + "dependency_type": "ui_library", + "is_external": true, + "line_number": 3, + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "version": null + }, + { + "dependency_type": "icon_library", + "is_external": true, + "line_number": 4, + "name": "lucide-svelte", + "path": null, + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": 5, + "name": "$lib/widgets/Markdown.svelte", + "path": "$lib/widgets/Markdown.svelte", + "version": null + }, + { + "dependency_type": "store", + "is_external": false, + "line_number": 6, + "name": "toaster", + "path": "../stores/toast", + "version": null + }, + { + "dependency_type": "framework", + "is_external": true, + "line_number": 8, + "name": "svelte", + "path": null, + "version": null + } + ], + "detailed_description": "该组件实现了一个悬浮式AI助手聊天面板,包含消息历史展示、实时输入、加载状态反馈等功能。通过绑定store属性管理对话状态,支持键盘快捷发送(回车键),并集成国际化文本显示。UI采用Svelte框架构建,使用Skeleton UI库的Avatar、ProgressRing等组件,并通过Markdown渲染器展示AI回复内容。面板可展开/收起,具备流畅滚动动画和响应式布局。", + "interfaces": [ + { + "description": "接收外部传入的AI对话状态和控制方法", + "interface_type": "prop", + "name": "store", + "parameters": [ + { + "description": "包含对话历史、加载状态和操作方法的状态管理对象", + "is_optional": false, + "name": "store", + "param_type": "AISpriteProps" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "将聊天容器滚动到底部", + "interface_type": "function", + "name": "scrollChatBottom", + "parameters": [ + { + "description": "滚动动画行为", + "is_optional": true, + "name": "behavior", + "param_type": "'auto' | 'instant' | 'smooth'" + } + ], + "return_type": "void", + "visibility": "private" + }, + { + "description": "处理用户消息发送逻辑,包含防重复提交和错误提示", + "interface_type": "function", + "name": "addMessage", + "parameters": [], + "return_type": "Promise", + "visibility": "private" + }, + { + "description": "监听回车键触发消息发送", + "interface_type": "function", + "name": "onPromptKeydown", + "parameters": [ + { + "description": "键盘事件对象", + "is_optional": false, + "name": "event", + "param_type": "KeyboardEvent" + } + ], + "return_type": "void", + "visibility": "private" + } + ], + "responsibilities": [ + "管理AI助手面板的显示与隐藏状态", + "渲染对话历史记录,区分用户与AI消息", + "处理用户输入并触发消息发送逻辑", + "提供加载状态视觉反馈", + "实现聊天区域自动滚动到底部" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "Svelte组件,用于展示和管理用户订阅源列表,支持分组展开、上下文菜单操作及快捷入口。", + "file_path": "app/src/routes/main/widgets/FeedsList.svelte", + "functions": [ + "createRefreshFeedsAction", + "createFeedPackageMenus", + "createFeedMenus", + "toggleExpand", + "expandGroup", + "onAddFeedPressed" + ], + "importance_score": 1.0, + "interfaces": [ + "listSection", + "listSectionWithAction", + "listItem", + "listItemInner", + "listGroupItem" + ], + "name": "FeedsList.svelte", + "source_summary": "\n\n{#snippet listSection(text: string)}\n\t
{text}
\n{/snippet}\n\n{#snippet listSectionWithAction(text: string, IconRender, onclick)}\n\t
\n\t\t
{text}
\n\t\t\n\t\t\t\n\t\t
\n\t\n{/snippet}\n\n{#snippet listItem(text: string, IconRender, onclick, stateSelected, menus)}\n\t\n\t\t{#if menus && menus.length !== 0}\n\t\t\t\n\t\t\t\t{@render listItemInner(text, IconRender, stateSelected)}\n\t\t\t\n\t\t{:else}\n\t\t\t{@render listItemInner(text, IconRender, stateSelected)}\n\t\t{/if}\n\t\n{/snippet}\n\n{#snippet listItemInner(text: string, IconRender, stateSelected)}\n\t\n\t\t\n\t\t{text}\n\t\n{/snippet}\n\n{#snippet listGroupItem(text, IconRender, onclick, stateSelected, menus)}\n\t\n\t\n\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t{text}\n\t\t\t\n\t\t\n\t\n{/snippet}\n\n\n\t{@render listSection($_('common.product_name'))}\n\t{@render listItem(\n\t\t$_('main.menu.create_feeds_package'),\n\t\tIconAddFeed,\n\t\tonAddFeedPressed,\n\t\tfalse,\n\t\tnull\n\t)}\n\t{@render listItem($_('main.menu.settings'), IconSettings, openSettings, false, null)}\n\n\t{@render listSection($_('main.section_frequently_used.label'))}\n\t{@render listItem(\n\t\t$_('main.section_frequently_used.menu.today'),\n\t\tIconToday,\n\t\tonSelectToday,\n\t\tisTodaySelected,\n\t\tnull\n\t)}\n\t{@render listItem(\n\t\t$_('main.section_frequently_used.menu.this_week'),\n\t\tIconWeekend,\n\t\tonSelectWeekend,\n\t\tisWeekendSelected,\n\t\tnull\n\t)}\n\t{@render listItem(\n\t\t$_('main.section_frequently_used.menu.favorites'),\n\t\tIconFavorites,\n\t\tonSelectFavorite,\n\t\tisFavoriteSelected,\n\t\tnull\n\t)}\n\t{@render listItem(\n\t\t$_('main.section_frequently_used.menu.unread'),\n\t\tIconUnread,\n\t\tonSelectUnread,\n\t\tisUnreadSelected,\n\t\tnull\n\t)}\n\n\t{@render listSectionWithAction($_('main.section_subscriptions.label'), IconAdd, onAddFeedPressed)}\n\n\t
\n\t\t{#if store != null && store.loadingStore.status === Status.Completed}\n\t\t\t{#each store.feedPackages as feedPackage (feedPackage.id)}\n\t\t\t\t{@render listGroupItem(\n\t\t\t\t\tfeedPackage.name,\n\t\t\t\t\texpandState[feedPackage.id] ? IconPackageExpand : IconPackageUnExpand,\n\t\t\t\t\t() => toggleExpand(feedPackage.id),\n\t\t\t\t\tfalse,\n\t\t\t\t\tcreateFeedPackageMenus(feedPackage)\n\t\t\t\t)}\n\t\t\t\t{#if expandState[feedPackage.id]}\n\t\t\t\t\t{#each feedPackage.feeds as feed (feed.id)}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{@render listItem(\n\t\t\t\t\t\t\t\tfeed.name,\n\t\t\t\t\t\t\t\tIconScrapSource,\n\t\t\t\t\t\t\t\t() => onFeedPressed(feed.id),\n\t\t\t\t\t\t\t\tselectedFeedId === feed.id,\n\t\t\t\t\t\t\t\tcreateFeedMenus(feedPackage, feed)\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t
\n\t\t\t\t\t{/each}\n\t\t\t\t{/if}\n\t\t\t{/each}\n\t\t{/if}\n\t
\n\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 19.0, + "cyclomatic_complexity": 6.0, + "depth_of_inheritance": 0, + "lines_of_code": 263, + "number_of_classes": 0, + "number_of_functions": 6 + }, + "dependencies": [ + { + "dependency_type": "internationalization", + "is_external": true, + "line_number": null, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": null, + "name": "@tauri-apps/plugin-dialog", + "path": "@tauri-apps/plugin-dialog", + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": null, + "name": "$lib/widgets/ContextMenuProvider.svelte", + "path": "$lib/widgets/ContextMenuProvider.svelte", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/plus", + "path": "lucide-svelte/icons/plus", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/folder", + "path": "lucide-svelte/icons/folder", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/folder-open", + "path": "lucide-svelte/icons/folder-open", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/circle-plus", + "path": "lucide-svelte/icons/circle-plus", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/package", + "path": "lucide-svelte/icons/package", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/newspaper", + "path": "lucide-svelte/icons/newspaper", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/settings", + "path": "lucide-svelte/icons/settings", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/globe", + "path": "lucide-svelte/icons/globe", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/file-heart", + "path": "lucide-svelte/icons/file-heart", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": null, + "name": "lucide-svelte/icons/eye-off", + "path": "lucide-svelte/icons/eye-off", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": null, + "name": "./types", + "path": "./types", + "version": null + }, + { + "dependency_type": "store", + "is_external": false, + "line_number": null, + "name": "../stores/loading.svelte", + "path": "../stores/loading.svelte", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "$lib/windows/index", + "path": "$lib/windows/index", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": null, + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "$lib/windows/lite-edit", + "path": "$lib/windows/lite-edit", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": null, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": null, + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "version": null + } + ], + "detailed_description": "该组件实现了一个结构化的侧边栏导航界面,用于显示用户的RSS订阅包(FeedsPackage)及其内部的订阅项(Feed)。支持通过点击切换分组展开状态,并为每个订阅包和订阅项提供右键上下文菜单以执行创建、编辑、删除等操作。同时集成了‘今日’、‘本周’、‘收藏’、‘未读’等聚合视图入口。所有UI文本均通过i18n国际化处理,交互行为通过事件回调与外部store通信,保证了逻辑解耦。组件使用Svelte的状态驱动机制($state)管理展开状态,并利用自定义use指令disableContextMenu禁用默认右键菜单。", + "interfaces": [ + { + "description": "渲染一个无操作的标题区段", + "interface_type": "snippet", + "name": "listSection", + "parameters": [ + { + "description": "标题文本", + "is_optional": false, + "name": "text", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "private" + }, + { + "description": "渲染带可点击图标的标题区段", + "interface_type": "snippet", + "name": "listSectionWithAction", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "text", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "IconRender", + "param_type": "Component" + }, + { + "description": null, + "is_optional": false, + "name": "onclick", + "param_type": "Function" + } + ], + "return_type": null, + "visibility": "private" + }, + { + "description": "通用列表项,可选绑定上下文菜单", + "interface_type": "snippet", + "name": "listItem", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "text", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "IconRender", + "param_type": "Component" + }, + { + "description": null, + "is_optional": false, + "name": "onclick", + "param_type": "Function" + }, + { + "description": null, + "is_optional": false, + "name": "stateSelected", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": true, + "name": "menus", + "param_type": "Array" + } + ], + "return_type": null, + "visibility": "private" + }, + { + "description": "列表项内部样式封装", + "interface_type": "snippet", + "name": "listItemInner", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "text", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "IconRender", + "param_type": "Component" + }, + { + "description": null, + "is_optional": false, + "name": "stateSelected", + "param_type": "boolean" + } + ], + "return_type": null, + "visibility": "private" + }, + { + "description": "带上下文菜单的分组标题项", + "interface_type": "snippet", + "name": "listGroupItem", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "text", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "IconRender", + "param_type": "Component" + }, + { + "description": null, + "is_optional": false, + "name": "onclick", + "param_type": "Function" + }, + { + "description": null, + "is_optional": false, + "name": "stateSelected", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": false, + "name": "menus", + "param_type": "Array" + } + ], + "return_type": null, + "visibility": "private" + } + ], + "responsibilities": [ + "渲染订阅源层级结构并支持分组展开/折叠", + "提供上下文菜单支持对订阅包和订阅项进行增删改操作", + "集成国际化文本与动态提示消息", + "响应用户交互并通过回调通知父级组件状态变化", + "管理本地UI状态如分组展开状态" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "文章阅读器组件,支持多种阅读模式和交互功能", + "file_path": "app/src/routes/main/widgets/ArticleReader.svelte", + "functions": [ + "copyLink", + "openOriginalPage", + "refreshByEnhancedScraper", + "switchStar" + ], + "importance_score": 1.0, + "interfaces": [ + "ArticleReaderProps", + "ArticleReadMode" + ], + "name": "ArticleReader.svelte", + "source_summary": "\n\n
\n\t\n\t\t{#if article !== null}\n\t\t\t
{article.title}
\n\t\t\t
\n\t\t\t\t switchStar(article!)}\n\t\t\t\t\tonkeypress={() => switchStar(article!)}\n\t\t\t\t>\n\t\t\t\t\t{#if article.is_favorite}\n\t\t\t\t\t\t\n\t\t\t\t\t{:else}\n\t\t\t\t\t\t\n\t\t\t\t\t{/if}\n\t\t\t\t\n\t\t\t\t
\n\t\t{/if}\n\t
\n\n\t
\n\t\t (group = e.value as ArticleReadMode)}\n\t\t\tlistJustify=\"justify-center\"\n\t\t\tclasses=\"h-full overflow-hidden flex flex-col\"\n\t\t\tlistClasses=\"flex-0\"\n\t\t\tcontentClasses=\"h-full flex-1 overflow-auto\"\n\t\t\tlistMargin=\"p-0\"\n\t\t>\n\t\t\t{#snippet list()}\n\t\t\t\t\n\t\t\t\t\t{#snippet lead()}{/snippet}\n\t\t\t\t\t{`${$_('reader.tab_optimized_content')}`}     \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t{#snippet lead()}{/snippet}\n\t\t\t\t\t{`${$_('reader.tab_melted_content')}`}     \n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t{#snippet lead()}{/snippet}\n\t\t\t\t\t{`${$_('reader.tab_melted_original')}`}     \n\t\t\t\t\n\t\t\t{/snippet}\n\t\t\t{#snippet content()}\n\t\t\t\t{#if article}\n\t\t\t\t\t\n\t\t\t\t\t\t{#key `optimized-${article.id}-${articleUpdatedSeq}`}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{/key}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t{#key `melted-${article.id}-${articleUpdatedSeq}`}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t{/key}\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t{/if}\n\t\t\t{/snippet}\n\t\t\n\n\t\t
\n\t\t\tR\n\t\t
\n\t
\n\n" + }, + "complexity_metrics": { + "cohesion_score": 0.78, + "coupling_factor": 0.64, + "cyclomatic_complexity": 9.0, + "depth_of_inheritance": 0, + "lines_of_code": 156, + "number_of_classes": 0, + "number_of_functions": 5 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 2, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + }, + { + "dependency_type": "ui", + "is_external": true, + "line_number": 3, + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": 4, + "name": "lucide-svelte", + "path": "lucide-svelte", + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": 9, + "name": "$lib/widgets/ArticleRenderWidget.svelte", + "path": "$lib/widgets/ArticleRenderWidget.svelte", + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": 10, + "name": "$lib/widgets/EmbedWebView.svelte", + "path": "$lib/widgets/EmbedWebView.svelte", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 11, + "name": "./types", + "path": "./types", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 12, + "name": "$lib/types/article", + "path": "$lib/types/article", + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 13, + "name": "@tauri-apps/plugin-clipboard-manager", + "path": "@tauri-apps/plugin-clipboard-manager", + "version": null + }, + { + "dependency_type": "api", + "is_external": false, + "line_number": 15, + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "util", + "is_external": false, + "line_number": 16, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte前端UI组件,用于展示文章内容并提供多种阅读模式。它通过Tabs组件实现优化内容、熔炼内容和原始页面三种视图切换。组件从props接收articleId和store,使用$effect自动查询文章数据。提供了复制链接、打开原文、刷新内容和收藏文章等功能按钮。支持国际化文本显示,并集成了Tauri的剪贴板操作和外部应用打开能力。", + "interfaces": [ + { + "description": null, + "interface_type": "type", + "name": "ArticleReaderProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "articleId", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "store", + "param_type": "any" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": null, + "interface_type": "type", + "name": "ArticleReadMode", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": null, + "interface_type": "function", + "name": "copyLink", + "parameters": [], + "return_type": "Promise", + "visibility": "private" + }, + { + "description": null, + "interface_type": "function", + "name": "switchStar", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "article", + "param_type": "Article" + } + ], + "return_type": "void", + "visibility": "private" + } + ], + "responsibilities": [ + "管理文章阅读界面的状态和交互", + "提供多模式文章内容展示(优化/熔炼/原始)", + "处理用户与文章的交互操作(收藏、分享等)", + "集成第三方API实现系统级功能调用", + "响应式更新文章内容数据" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "定义前端UI组件所需的各种类型接口,包括属性传递和状态结构。", + "file_path": "app/src/routes/main/widgets/types.ts", + "functions": [], + "importance_score": 1.0, + "interfaces": [ + "FeedsListProps", + "SearchBarProps", + "ArticleReaderProps", + "ArticlesGroup", + "ArticlesListProps", + "FooterProps", + "AISpriteProps", + "ArticleReadMode" + ], + "name": "types.ts", + "source_summary": "import type { Article } from '$lib/types/article';\nimport type { StoreType as SearchStoreType } from '../stores/articles/search/index.svelte';\nimport type { StoreType as ListStoreType } from '../stores/articles/list/index.svelte';\nimport type { StoreType as TasksStoreType } from '../stores/tasks.svelte';\nimport type { StoreType as FeedsStoreType } from '../stores/feeds.svelte';\nimport type { StoreType as ReaderStoreType } from '../stores/reader.svelte';\nimport type { StoreType as AISpriteStore } from '../stores/sprite.svelte';\n\ninterface FeedsListProps {\n\tstore: FeedsStoreType;\n\tselectedFeedId: string | undefined;\n\tonFeedPressed: (feedId: string) => void;\n\tonSelectToday: () => void;\n\tonSelectWeekend: () => void;\n\tisTodaySelected: boolean;\n\tisWeekendSelected: boolean;\n\tonSelectFavorite: () => void;\n\tisFavoriteSelected: boolean;\n\tonSelectUnread: () => void;\n\tisUnreadSelected: boolean;\n}\n\ninterface SearchBarProps {\n\tstore: SearchStoreType;\n\tarticles_store: ListStoreType;\n}\n\ninterface ArticleReaderProps {\n\tarticleId: number;\n\tstore: ReaderStoreType;\n}\n\ninterface ArticlesGroup {\n\tname: string;\n\tarticles: Article[];\n}\n\ninterface ArticlesListProps {\n\tstore: ListStoreType;\n\tmarkAsRead: (articleId: number) => Promise;\n\tisFilterActived: boolean;\n\tisFeedSpecified: boolean;\n\tselectedArticle: Article | null;\n\tonArticlePressed: (article: Article) => void;\n}\n\ninterface FooterProps {\n\ttasksStore: TasksStoreType;\n}\n\ninterface AISpriteProps {\n\tstore: AISpriteStore;\n}\n\ntype ArticleReadMode = 'optimized' | 'melted' | 'original';\n\nexport type {\n\tFeedsListProps,\n\tArticleReaderProps,\n\tArticleReadMode,\n\tArticlesGroup,\n\tArticlesListProps,\n\tSearchBarProps,\n\tFooterProps,\n\tAISpriteProps\n};\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 7.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 66, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "type import", + "is_external": false, + "line_number": 1, + "name": "Article", + "path": "$lib/types/article", + "version": null + }, + { + "dependency_type": "type import", + "is_external": false, + "line_number": 2, + "name": "SearchStoreType", + "path": "../stores/articles/search/index.svelte", + "version": null + }, + { + "dependency_type": "type import", + "is_external": false, + "line_number": 3, + "name": "ListStoreType", + "path": "../stores/articles/list/index.svelte", + "version": null + }, + { + "dependency_type": "type import", + "is_external": false, + "line_number": 4, + "name": "TasksStoreType", + "path": "../stores/tasks.svelte", + "version": null + }, + { + "dependency_type": "type import", + "is_external": false, + "line_number": 5, + "name": "FeedsStoreType", + "path": "../stores/feeds.svelte", + "version": null + }, + { + "dependency_type": "type import", + "is_external": false, + "line_number": 6, + "name": "ReaderStoreType", + "path": "../stores/reader.svelte", + "version": null + }, + { + "dependency_type": "type import", + "is_external": false, + "line_number": 7, + "name": "AISpriteStore", + "path": "../stores/sprite.svelte", + "version": null + } + ], + "detailed_description": "该组件是一个类型定义文件,专门用于声明前端UI组件之间的共享类型接口。它导入多个Svelte store的类型,并定义了如FeedsListProps、ArticlesListProps等组件属性接口,以及ArticlesGroup这样的数据分组结构。同时定义了一个联合类型ArticleReadMode来表示文章阅读模式。所有类型均通过export type导出,供其他组件引用,确保类型安全和一致性。", + "interfaces": [ + { + "description": null, + "interface_type": "interface", + "name": "FeedsListProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "store", + "param_type": "FeedsStoreType" + }, + { + "description": null, + "is_optional": true, + "name": "selectedFeedId", + "param_type": "string | undefined" + }, + { + "description": null, + "is_optional": false, + "name": "onFeedPressed", + "param_type": "(feedId: string) => void" + }, + { + "description": null, + "is_optional": false, + "name": "onSelectToday", + "param_type": "() => void" + }, + { + "description": null, + "is_optional": false, + "name": "onSelectWeekend", + "param_type": "() => void" + }, + { + "description": null, + "is_optional": false, + "name": "isTodaySelected", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": false, + "name": "isWeekendSelected", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": false, + "name": "onSelectFavorite", + "param_type": "() => void" + }, + { + "description": null, + "is_optional": false, + "name": "isFavoriteSelected", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": false, + "name": "onSelectUnread", + "param_type": "() => void" + }, + { + "description": null, + "is_optional": false, + "name": "isUnreadSelected", + "param_type": "boolean" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "interface", + "name": "SearchBarProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "store", + "param_type": "SearchStoreType" + }, + { + "description": null, + "is_optional": false, + "name": "articles_store", + "param_type": "ListStoreType" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "interface", + "name": "ArticleReaderProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "articleId", + "param_type": "number" + }, + { + "description": null, + "is_optional": false, + "name": "store", + "param_type": "ReaderStoreType" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "interface", + "name": "ArticlesGroup", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "name", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "articles", + "param_type": "Article[]" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "interface", + "name": "ArticlesListProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "store", + "param_type": "ListStoreType" + }, + { + "description": null, + "is_optional": false, + "name": "markAsRead", + "param_type": "(articleId: number) => Promise" + }, + { + "description": null, + "is_optional": false, + "name": "isFilterActived", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": false, + "name": "isFeedSpecified", + "param_type": "boolean" + }, + { + "description": null, + "is_optional": false, + "name": "selectedArticle", + "param_type": "Article | null" + }, + { + "description": null, + "is_optional": false, + "name": "onArticlePressed", + "param_type": "(article: Article) => void" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "interface", + "name": "FooterProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "tasksStore", + "param_type": "TasksStoreType" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "interface", + "name": "AISpriteProps", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "store", + "param_type": "AISpriteStore" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": null, + "interface_type": "type", + "name": "ArticleReadMode", + "parameters": [], + "return_type": "'optimized' | 'melted' | 'original'", + "visibility": "exported" + } + ], + "responsibilities": [ + "定义UI组件间通信的属性接口", + "统一管理前端组件依赖的状态store类型", + "提供数据结构类型定义(如ArticlesGroup)", + "定义可选值的联合类型(如阅读模式)", + "促进类型安全的组件间交互" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "页脚UI组件,显示任务加载状态并提供弹窗详情展示", + "file_path": "app/src/routes/main/widgets/Footer.svelte", + "functions": [ + "popoverClose" + ], + "importance_score": 1.0, + "interfaces": [ + "FooterProps" + ], + "name": "Footer.svelte", + "source_summary": "\n\n
\n\t\n\t\n\t\n\t
\n\n\t (openState = e.open)}\n\t\tpositioning={{ placement: 'top' }}\n\t\ttriggerBase=\"p-0\"\n\t\tcontentBase=\"card shadow-[0px_0px_10px_1px_rgba(0,0,0,0.3)] preset-filled-surface-50-950 p-4 min-w-[320px]\"\n\t\tarrow\n\t\tarrowBackground=\"!bg-surface-50 dark:!bg-surface-950\"\n\t>\n\t\t{#snippet trigger()}\n\t\t\t\n\t\t\t\t{#if tasksStore.pendingStatus === Status.Loading}\n\t\t\t\t\t\n\t\t\t\t{/if}\n\n\t\t\t\t{tasksStore.pendingStatusText}\n\t\t\t\n\t\t{/snippet}\n\t\t{#snippet content()}\n\t\t\t
\n\t\t\t\t

{$_('main.footer.tasks.label')}

\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t
\n\t\t\t\t{#if tasksStore.pendings?.length > 0}\n\t\t\t\t\t
\n\t\t\t\t\t{#each tasksStore.pendings as pending (pending.description)}\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{pending.loadingStore.statusText}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t{pending.description}\n\t\t\t\t\t\t
\n\t\t\t\t\t{/each}\n\t\t\t\t{:else}\n\t\t\t\t\t{$_('main.footer.tasks.idle')}\n\t\t\t\t{/if}\n\t\t\t
\n\t\t{/snippet}\n\t\n
\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 7.0, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 74, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 2, + "name": "svelte-i18n", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 3, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + }, + { + "dependency_type": "ui_component", + "is_external": true, + "line_number": 4, + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "version": null + }, + { + "dependency_type": "icon", + "is_external": true, + "line_number": 5, + "name": "lucide-svelte", + "path": null, + "version": null + }, + { + "dependency_type": "ui_component", + "is_external": true, + "line_number": 6, + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "version": null + }, + { + "dependency_type": "store", + "is_external": false, + "line_number": 7, + "name": "../stores/loading.svelte", + "path": "../stores/loading.svelte", + "version": null + }, + { + "dependency_type": "type_definition", + "is_external": false, + "line_number": 8, + "name": "./types", + "path": "./types", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte前端UI组件,用于渲染页面底部的进度状态栏。它通过Popover展示当前待处理任务列表及其状态描述。当有任务处于加载中时,显示ProgressRing动画;否则显示空闲提示。用户可点击区域展开弹窗查看详细任务信息,并通过关闭按钮收起。支持右键菜单禁用以提升用户体验。", + "interfaces": [ + { + "description": "定义传递给Footer组件的数据结构", + "interface_type": "type", + "name": "FooterProps", + "parameters": [ + { + "description": "包含pendingStatus、pendingStatusText和pendings等任务状态数据", + "is_optional": false, + "name": "tasksStore", + "param_type": "TasksStore" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "Popover触发区域的UI渲染逻辑", + "interface_type": "snippet", + "name": "trigger", + "parameters": [], + "return_type": "Element", + "visibility": "private" + } + ], + "responsibilities": [ + "渲染任务状态指示器(加载动画或文本)", + "管理Popover弹窗的打开/关闭状态", + "展示待处理任务的详细列表信息", + "集成国际化文本支持", + "防止默认右键上下文菜单行为" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "负责应用配置的初始化、读取与持久化,确保系统启动时具备有效的配置数据。", + "file_path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "functions": [ + "call", + "sync_to", + "default_app_config" + ], + "importance_score": 0.9, + "interfaces": [ + "call", + "sync_to" + ], + "name": "init_app_config.rs", + "source_summary": "use tokio::{\n fs::File,\n io::{AsyncReadExt, AsyncWriteExt},\n};\n\nuse recorder::path::get_appdata_file;\nuse types::{\n AppConfig, GLMLLMProvider, LLMInstructOption, LLMSection, OllamaLLMProvider, OpenAILLMProvider,\n PlatformLLMProvider, ScrapSection,\n};\n\nuse super::task::{InitTask, TaskInitializer};\n\nconst FILE_NAME_APP_CONFIG: &str = \"app_config.toml\";\n\npub async fn call() -> anyhow::Result> {\n let mut task = InitTask::default();\n task.start(\"app_config\", || async {\n let app_config_path = get_appdata_file(FILE_NAME_APP_CONFIG);\n Ok(match File::open(app_config_path).await {\n Ok(mut file) => {\n let mut data_raw = String::new();\n file.read_to_string(&mut data_raw).await?;\n toml::from_str(data_raw.as_str())?\n }\n Err(_) => {\n let app_config = default_app_config();\n sync_to(&app_config).await?;\n app_config\n }\n })\n })\n .await?;\n Ok(task)\n}\n\npub async fn sync_to(app_config: &AppConfig) -> anyhow::Result<()> {\n let user_config_path = get_appdata_file(FILE_NAME_APP_CONFIG);\n let mut file = File::create(user_config_path).await?;\n let json_raw = toml::to_string(app_config)?;\n file.write_all(json_raw.as_bytes()).await?;\n Ok(())\n}\n\nfn default_app_config() -> AppConfig {\n AppConfig {\n llm: LLMSection {\n provider_ollama: OllamaLLMProvider {\n endpoint: Default::default(),\n },\n provider_platform: PlatformLLMProvider {\n template_path: \"\".to_string(),\n model_path: \"\".to_string(),\n },\n provider_glm: GLMLLMProvider {\n model_name: \"GLM-4.5-Flash\".to_string(),\n api_base_url: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\".to_string(),\n api_key: \"\".to_string(),\n },\n provider_openai: OpenAILLMProvider {\n model_name: \"\".to_string(),\n api_base_url: \"\".to_string(),\n api_key: \"\".to_string(),\n },\n active_provider_type: Default::default(),\n instruct: LLMInstructOption::default(),\n max_parallel: Some(5),\n },\n scrap: ScrapSection {\n provider: Default::default(),\n },\n log: Default::default(),\n daemon: Default::default(),\n diagnostic: Default::default(),\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.4, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 76, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "async_runtime", + "is_external": true, + "line_number": 1, + "name": "tokio", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": true, + "line_number": 5, + "name": "recorder", + "path": null, + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 7, + "name": "types", + "path": "crates/types", + "version": null + }, + { + "dependency_type": "serialization", + "is_external": true, + "line_number": null, + "name": "toml", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是应用程序启动流程中的关键初始化模块,主要职责为加载或创建默认的应用配置(AppConfig)。它首先尝试从指定路径读取 TOML 格式的配置文件 `app_config.toml`,若文件不存在或读取失败,则生成一个包含默认值的 AppConfig 对象,并将其同步写入磁盘。配置内容涵盖 LLM 提供商设置(如 Ollama、OpenAI、GLM 等)、爬虫模块、日志、守护进程及诊断选项。通过调用 `InitTask` 异步任务机制,保证初始化过程的可追踪性和错误处理能力。`sync_to` 函数支持运行时动态保存配置,实现配置的持久化管理。", + "interfaces": [ + { + "description": "主入口函数,启动配置初始化任务,返回封装了结果的异步任务对象。", + "interface_type": "function", + "name": "call", + "parameters": [], + "return_type": "anyhow::Result>", + "visibility": "public" + }, + { + "description": "将给定的 AppConfig 对象序列化为 TOML 并写入磁盘文件。", + "interface_type": "function", + "name": "sync_to", + "parameters": [ + { + "description": "待持久化的配置引用", + "is_optional": false, + "name": "app_config", + "param_type": "&AppConfig" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "构建并返回一个具有默认字段值的应用配置实例。", + "interface_type": "function", + "name": "default_app_config", + "parameters": [], + "return_type": "AppConfig", + "visibility": "private" + } + ], + "responsibilities": [ + "初始化并加载应用配置文件(TOML格式)", + "在配置缺失时提供结构完整且合理的默认配置", + "将内存中的配置对象持久化写入文件系统", + "集成到异步初始化任务框架中,支持可组合的任务执行流程", + "管理多LLM提供商的默认参数设置" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "定义LLM服务端点结构,支持Ollama API兼容的聊天和生成接口。", + "file_path": "crates/types/src/llm_endpoint.rs", + "functions": [ + "get_api_chat_completion", + "get_api_generate_completion" + ], + "importance_score": 0.8, + "interfaces": [ + "LLMEndPoint" + ], + "name": "llm_endpoint.rs", + "source_summary": "use serde::{Deserialize, Serialize};\n\nconst DEFAULT_API_CHAT_COMPLETION: &str = \"/api/chat\";\nconst DEFAULT_API_GENERATE_COMPLETION: &str = \"/api/generate\";\n\nconst DEFAULT_MODEL_NAME: &str = \"default_adaptived_llm\";\n\nconst DEFAULT_LOCAL_BASE_URL: &str = \"http://localhost:11434\";\n\n/// LLM EndPoint信息,目前只支持Ollama\n///\n/// 接口定义见\n#[derive(Serialize, Deserialize, Clone)]\npub struct LLMEndPoint {\n /// 加一个type\n /// 服务基地址\n pub api_base_url: String,\n /// Completion接口的path\n pub api_path_generate_completion: String,\n /// Chat接口的path\n pub api_path_chat_completion: String,\n /// 模型名称\n pub model: String,\n}\n\nimpl Default for LLMEndPoint {\n fn default() -> Self {\n LLMEndPoint {\n api_base_url: DEFAULT_LOCAL_BASE_URL.into(),\n api_path_generate_completion: DEFAULT_API_GENERATE_COMPLETION.into(),\n api_path_chat_completion: DEFAULT_API_CHAT_COMPLETION.into(),\n model: DEFAULT_MODEL_NAME.into(),\n }\n }\n}\n\nimpl LLMEndPoint {\n /// 获得chat接口的全地址\n pub fn get_api_chat_completion(&self) -> String {\n [\n self.api_base_url.as_str(),\n self.api_path_chat_completion.as_str(),\n ]\n .join(\"\")\n }\n\n /// 获得completion接口的全地址\n pub fn get_api_generate_completion(&self) -> String {\n [\n self.api_base_url.as_str(),\n self.api_path_generate_completion.as_str(),\n ]\n .join(\"\")\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.2, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 55, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 1, + "name": "serde", + "path": null, + "version": null + } + ], + "detailed_description": "该组件定义了与LLM(如Ollama)交互所需的端点配置结构体LLMEndPoint,包含API基础URL、聊天和生成接口路径以及模型名称。通过实现Default trait提供本地开发默认配置,并提供两个方法用于拼接完整的API请求地址。主要用于解耦LLM服务配置与具体调用逻辑,提升可配置性和可测试性。", + "interfaces": [ + { + "description": "表示LLM服务端点的配置信息", + "interface_type": "struct", + "name": "LLMEndPoint", + "parameters": [ + { + "description": "服务基地址", + "is_optional": false, + "name": "api_base_url", + "param_type": "String" + }, + { + "description": "Completion接口的path", + "is_optional": false, + "name": "api_path_generate_completion", + "param_type": "String" + }, + { + "description": "Chat接口的path", + "is_optional": false, + "name": "api_path_chat_completion", + "param_type": "String" + }, + { + "description": "模型名称", + "is_optional": false, + "name": "model", + "param_type": "String" + } + ], + "return_type": null, + "visibility": "pub" + } + ], + "responsibilities": [ + "定义LLM服务的连接配置参数", + "提供默认本地Ollama服务配置", + "构建完整的API请求URL", + "支持序列化与反序列化以便配置传递", + "保持与Ollama API规范的兼容性" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义了系统核心数据模型,包括文章、配置、用户订阅和对话消息等结构体。", + "file_path": "crates/types/src/lib.rs", + "functions": [ + "rename_feed", + "change_feed_data", + "remove_feed", + "find_feeds_package", + "find_feeds_package_mut", + "find_feed", + "add_feeds_packages", + "remove_feeds_package", + "rename_feeds_package", + "search_feeds_package_inner" + ], + "importance_score": 0.8, + "interfaces": [ + "Article", + "LLMInstructOption", + "AppConfigLogSection", + "DiagnosticSection", + "OutputType", + "ScrapProviderType", + "LLMProviderType", + "LLMProvider", + "PlatformLLMProvider", + "GLMLLMProvider", + "OpenAILLMProvider", + "OllamaLLMProvider", + "LLMSection", + "DaemonSection", + "ScrapSection", + "AppConfig", + "UserConfig", + "FeedsPackage", + "FeedTargetDescription", + "ConversationMessageRoleType", + "ConversationMessagePayloadType", + "ConversationMessage" + ], + "name": "lib.rs", + "source_summary": "use std::cmp::Ordering;\n\nuse serde::{Deserialize, Serialize};\nuse strum::{Display, EnumString};\n\nuse crate::llm_endpoint::LLMEndPoint;\n\npub mod llm_endpoint;\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct Article {\n pub title: String,\n pub head_read: Option,\n pub source_link: String,\n pub summary: Option,\n pub content: Option,\n pub date_created: String,\n pub date_read: Option,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct LLMInstructOption {\n pub lang: String,\n pub emphasis: Option,\n}\n\nimpl Default for LLMInstructOption {\n fn default() -> Self {\n Self {\n lang: \"Chinese\".to_string(),\n emphasis: None,\n }\n }\n}\n\n/// 日志配置节点,用于指定日志的的开启、输出模式等行为。\n/// 该配置的应用详见[init_logger][feed_api_rs::startup::init_logger]\n#[derive(Serialize, Deserialize, Clone, Default)]\npub struct AppConfigLogSection {\n /// 是否启用日志功能,仅当未true时才会采纳log section中设定的属性。\n pub enable: bool,\n /// 日志输出类型,包括'stdout' or 'disk',分别对应stdout和日志文件模式。\n pub output_type: OutputType,\n\n pub log_name_tail: String,\n}\n\n#[derive(Serialize, Deserialize, Clone, Default)]\npub struct DiagnosticSection {\n pub flame_whole: bool,\n}\n\n#[derive(Serialize, Deserialize, EnumString, Clone, Default)]\npub enum OutputType {\n #[default]\n #[strum(disabled)]\n UnSpecified,\n\n #[strum(serialize = \"stdout\")]\n #[serde(rename = \"stdout\")]\n Stdout,\n\n #[strum(serialize = \"disk\")]\n #[serde(rename = \"disk\")]\n Disk,\n}\n\n#[derive(Serialize, Deserialize, EnumString, Clone, Default)]\npub enum ScrapProviderType {\n #[strum(serialize = \"baidu\")]\n #[serde(rename = \"baidu\")]\n Baidu,\n\n #[default]\n #[strum(serialize = \"bing\")]\n #[serde(rename = \"bing\")]\n Bing,\n}\n\n#[derive(Serialize, Deserialize, EnumString, Clone, Default)]\npub enum LLMProviderType {\n #[strum(serialize = \"ollama\")]\n #[serde(rename = \"ollama\")]\n Ollama,\n\n #[strum(serialize = \"platform\")]\n #[serde(rename = \"platform\")]\n Platform,\n\n #[default]\n #[strum(serialize = \"glm\")]\n #[serde(rename = \"glm\")]\n GLM,\n\n #[strum(serialize = \"openai\")]\n #[serde(rename = \"openai\")]\n OpenAI,\n\n #[strum(serialize = \"mistral\")]\n #[serde(rename = \"mistral\")]\n Mistral,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct LLMProvider {\n pub provider_type: LLMProviderType,\n pub template_path: String,\n pub model_path: String,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct PlatformLLMProvider {\n pub template_path: String,\n pub model_path: String,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct GLMLLMProvider {\n pub model_name: String,\n pub api_base_url: String,\n pub api_key: String,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct OpenAILLMProvider {\n pub model_name: String,\n pub api_base_url: String,\n pub api_key: String,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct OllamaLLMProvider {\n pub endpoint: LLMEndPoint,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct LLMSection {\n pub provider_ollama: OllamaLLMProvider,\n pub provider_platform: PlatformLLMProvider,\n pub provider_glm: GLMLLMProvider,\n pub provider_openai: OpenAILLMProvider,\n pub active_provider_type: LLMProviderType,\n #[serde(default)]\n pub instruct: LLMInstructOption,\n pub max_parallel: Option\n}\n\n#[derive(Serialize, Deserialize, Clone, Default)]\npub struct DaemonSection {\n pub frequency_feeds_update: bool,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct ScrapSection {\n pub provider: ScrapProviderType,\n}\n\n/// 端侧应用配置节点,包括LLM配置、日志配置等。\n/// 应用内会包含一套默认的应用配置作为初始化。\n#[derive(Serialize, Deserialize, Clone)]\npub struct AppConfig {\n pub llm: LLMSection,\n pub scrap: ScrapSection,\n pub log: AppConfigLogSection,\n pub daemon: DaemonSection,\n pub diagnostic: DiagnosticSection,\n}\n\n/// 端侧用户配置节点,订阅包与订阅信息。\n/// 应用内会包含一套默认的应用配置作为初始化。\n#[derive(Serialize, Deserialize, Clone)]\npub struct UserConfig {\n pub feeds_packages: Vec,\n}\n\nimpl UserConfig {\n /// 重命名feed\n /// 该操作仅更高内存数据本身。\n /// 如果无法找到对应的订阅包或订阅会返回false。\n pub fn rename_feed(&mut self, package_id: &str, feed_id: &str, new_name: &str) -> bool {\n match self.find_feeds_package_mut(package_id) {\n Some(package) => match search_feed_by_inner(feed_id, &package.feeds) {\n Ok(index) => {\n let feed = package.feeds.get_mut(index).unwrap();\n feed.name = new_name.into();\n true\n }\n Err(_) => false,\n },\n None => false,\n }\n }\n\n pub fn change_feed_data(&mut self, package_id: &str, feed_id: &str, data: Vec) -> bool {\n match self.find_feeds_package_mut(package_id) {\n Some(package) => match search_feed_by_inner(feed_id, &package.feeds) {\n Ok(index) => {\n let feed = package.feeds.get_mut(index).unwrap();\n feed.data = data;\n true\n }\n Err(_) => false,\n },\n None => false,\n }\n }\n\n /// 移除feed\n /// 该操作仅更高内存数据本身。\n /// 如果无法找到对应的订阅包或订阅会返回false。\n pub fn remove_feed(&mut self, package_id: &str, feed_id: &str) -> bool {\n match self.find_feeds_package_mut(package_id) {\n Some(package) => match search_feed_by_inner(feed_id, &package.feeds) {\n Ok(index) => {\n package.feeds.remove(index);\n true\n }\n Err(_) => false,\n },\n None => false,\n }\n }\n\n /// 查找订阅包并返回一个副本\n pub fn find_feeds_package(&self, package_id: &str) -> Option {\n match self.search_feeds_package_inner(package_id) {\n Ok(index) => Some(self.feeds_packages.get(index).unwrap().clone()),\n Err(_) => None,\n }\n }\n\n /// 查找订阅包并返回可变引用\n pub fn find_feeds_package_mut(&mut self, package_id: &str) -> Option<&mut FeedsPackage> {\n match self.search_feeds_package_inner(package_id) {\n Ok(index) => self.feeds_packages.get_mut(index),\n Err(_) => None,\n }\n }\n\n /// 查找订阅并返回一个副本\n pub fn find_feed(&self, package_id: &str, feed_id: &str) -> Option {\n match self.search_feeds_package_inner(package_id) {\n Ok(index) => match self.feeds_packages.get(index) {\n Some(feeds_package) => match search_feed_by_inner(feed_id, &feeds_package.feeds) {\n Ok(ftd_index) => Some(feeds_package.feeds.get(ftd_index).unwrap().clone()),\n Err(_) => None,\n },\n None => None,\n },\n Err(_) => None,\n }\n }\n\n /// 增加一个订阅包,如果订阅包已存在则返回false。\n pub fn add_feeds_packages(&mut self, feeds_package: FeedsPackage) -> bool {\n if self.search_feeds_package_inner(&feeds_package.id).is_ok() {\n return false;\n }\n self.feeds_packages.push(feeds_package);\n true\n }\n\n /// 移除一个订阅包,如果订阅包已存在则返回false。\n pub fn remove_feeds_package(&mut self, package_id: &str) -> bool {\n match self.search_feeds_package_inner(package_id) {\n Ok(index) => {\n self.feeds_packages.remove(index);\n true\n }\n Err(_) => false,\n }\n }\n\n /// 移重命名一个订阅包,如果订阅包不存在则返回false。\n pub fn rename_feeds_package(&mut self, package_id: &str, new_name: &str) -> bool {\n match self.search_feeds_package_inner(package_id) {\n Ok(index) => {\n let feeds_package = self.feeds_packages.get_mut(index).unwrap();\n feeds_package.name = new_name.to_owned();\n true\n }\n Err(_) => false,\n }\n }\n\n /// 查找订阅包的索引辅助函数\n fn search_feeds_package_inner(&self, package_id: &str) -> Result {\n match self\n .feeds_packages\n .iter()\n .position(|probe| package_id.cmp(&probe.id) == Ordering::Equal)\n {\n None => Err(0),\n Some(idx) => Ok(idx),\n }\n }\n}\n\nfn search_feed_by_inner(feed_id: &str, feeds: &[FeedTargetDescription]) -> Result {\n match feeds\n .iter()\n .position(|prob| feed_id.cmp(&prob.id) == Ordering::Equal)\n {\n None => Err(0),\n Some(idx) => Ok(idx),\n }\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct FeedsPackage {\n pub id: String,\n pub name: String,\n pub feeds: Vec,\n pub is_flat_on_root: bool,\n}\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct FeedTargetDescription {\n // 用于做查询用的group id。\n pub id: String,\n pub name: String,\n pub fetcher_id: String,\n pub data: Vec,\n}\n\n#[derive(Serialize, Deserialize, EnumString, Clone, Default, Display)]\npub enum ConversationMessageRoleType {\n #[default]\n #[strum(disabled)]\n UnSpecified,\n\n #[strum(serialize = \"system\")]\n #[serde(rename = \"system\")]\n System,\n\n #[strum(serialize = \"user\")]\n #[serde(rename = \"user\")]\n User,\n\n #[strum(serialize = \"assistant\")]\n #[serde(rename = \"assistant\")]\n Assistant,\n}\n\n#[derive(Serialize, Deserialize, EnumString, Clone, Default, Display)]\npub enum ConversationMessagePayloadType {\n #[default]\n #[strum(disabled)]\n UnSpecified,\n\n #[strum(serialize = \"text\")]\n #[serde(rename = \"text\")]\n Text,\n\n #[strum(serialize = \"image\")]\n #[serde(rename = \"image\")]\n Image,\n\n #[strum(serialize = \"video\")]\n #[serde(rename = \"video\")]\n Video,\n\n #[strum(serialize = \"audio\")]\n #[serde(rename = \"audio\")]\n Audio,\n\n #[strum(serialize = \"file\")]\n #[serde(rename = \"file\")]\n File,\n}\n\n#[derive(Serialize, Deserialize, Clone, Default)]\npub struct ConversationMessage {\n pub role: ConversationMessageRoleType,\n pub mtype: ConversationMessagePayloadType,\n pub payload: String,\n pub created_at: String,\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.15, + "cyclomatic_complexity": 18.0, + "depth_of_inheritance": 0, + "lines_of_code": 378, + "number_of_classes": 24, + "number_of_functions": 10 + }, + "dependencies": [ + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 3, + "name": "serde", + "path": null, + "version": null + }, + { + "dependency_type": "enum_utils", + "is_external": true, + "line_number": 4, + "name": "strum", + "path": null, + "version": null + }, + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 1, + "name": "std::cmp::Ordering", + "path": null, + "version": null + }, + { + "dependency_type": "internal_module", + "is_external": false, + "line_number": 6, + "name": "crate::llm_endpoint::LLMEndPoint", + "path": "crates/types/src/llm_endpoint.rs", + "version": null + } + ], + "detailed_description": "该组件是系统的核心数据模型层,定义了多个用于配置管理、内容处理和用户交互的数据结构。主要包括:1) 配置相关模型(AppConfig, UserConfig)用于管理应用和用户的配置信息;2) LLM相关模型(LLMProviderType, LLMSection等)用于支持多种大语言模型提供商的配置和切换;3) 订阅管理模型(FeedsPackage, FeedTargetDescription)用于管理用户订阅包和订阅项;4) 对话消息模型(ConversationMessage)用于表示聊天会话中的消息。组件通过Serde实现序列化/反序列化,支持JSON等格式的持久化和传输。", + "interfaces": [ + { + "description": "用户配置主结构体,包含订阅包列表", + "interface_type": "struct", + "name": "UserConfig", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "重命名指定的订阅项", + "interface_type": "method", + "name": "rename_feed", + "parameters": [ + { + "description": "订阅包ID", + "is_optional": false, + "name": "package_id", + "param_type": "&str" + }, + { + "description": "订阅项ID", + "is_optional": false, + "name": "feed_id", + "param_type": "&str" + }, + { + "description": "新名称", + "is_optional": false, + "name": "new_name", + "param_type": "&str" + } + ], + "return_type": "bool", + "visibility": "public" + }, + { + "description": "支持的LLM提供商枚举", + "interface_type": "enum", + "name": "LLMProviderType", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "定义系统核心数据结构和模型", + "提供配置管理和序列化支持", + "支持多LLM提供商的类型安全枚举", + "实现用户订阅包的增删改查操作", + "确保数据结构的可扩展性和类型安全性" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "实现基于平台的LLM服务调用代理,封装请求参数并完成与远程模型的交互。", + "file_path": "crates/llm/src/providers/llm_platform.rs", + "functions": [ + "new", + "completion" + ], + "importance_score": 0.8, + "interfaces": [ + "CompletionService" + ], + "name": "llm_platform.rs", + "source_summary": "use reqwest::Client;\nuse serde::Serialize;\n\nuse types::PlatformLLMProvider;\n\nuse crate::connector;\nuse crate::providers::types::{AITargetOption, CompletionService};\n\n#[derive(Serialize)]\npub struct RequestParameters {\n prompt: String,\n}\n\npub struct PlatformAgentService {\n #[allow(dead_code)]\n config: PlatformLLMProvider,\n client: Client,\n}\n\nimpl PlatformAgentService {\n pub fn new(config: &PlatformLLMProvider, _system_prompt: String, _options: AITargetOption) -> anyhow::Result {\n Ok(\n PlatformAgentService {\n config: config.clone(),\n client: connector::new()?,\n }\n )\n }\n}\n\nimpl CompletionService for PlatformAgentService {\n async fn completion(&self, prompt: String) -> anyhow::Result {\n // TODO: 启动服务\n let parameter = RequestParameters {\n prompt\n };\n let response =\n self.client\n .post(\"\".to_owned())\n .json(¶meter)\n .send().await?;\n let text = response.text().await?;\n Ok(text)\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 5.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 45, + "number_of_classes": 2, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "http_client", + "is_external": true, + "line_number": 1, + "name": "reqwest::Client", + "path": null, + "version": null + }, + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 2, + "name": "serde::Serialize", + "path": null, + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 4, + "name": "types::PlatformLLMProvider", + "path": "types", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 6, + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 7, + "name": "crate::providers::types::AITargetOption", + "path": null, + "version": null + }, + { + "dependency_type": "interface", + "is_external": false, + "line_number": 7, + "name": "crate::providers::types::CompletionService", + "path": null, + "version": null + } + ], + "detailed_description": "该组件实现了PlatformAgentService结构体,用于封装对特定LLM平台的调用逻辑。它通过reqwest客户端发送JSON格式的请求到目标平台,并接收文本响应。当前硬编码了空URL(需配置),使用RequestParameters序列化提示内容。其主要作用是作为AI能力提供者的适配层,对接外部大模型服务。", + "interfaces": [ + { + "description": "定义LLM补全服务的标准接口", + "interface_type": "trait", + "name": "CompletionService", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "创建PlatformAgentService实例", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": "平台配置信息引用", + "is_optional": false, + "name": "config", + "param_type": "&PlatformLLMProvider" + }, + { + "description": "系统提示词(当前未使用)", + "is_optional": false, + "name": "_system_prompt", + "param_type": "String" + }, + { + "description": "AI目标选项(当前未使用)", + "is_optional": false, + "name": "_options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "异步执行文本补全请求", + "interface_type": "function", + "name": "completion", + "parameters": [ + { + "description": "用户输入提示", + "is_optional": false, + "name": "prompt", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "初始化HTTP客户端与配置信息", + "构造标准化的请求参数对象", + "执行远程LLM补全请求并处理响应", + "实现CompletionService接口以统一调用契约", + "管理与外部LLM平台的通信细节" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现基于 Ollama LLM 的文本补全功能,封装请求参数并调用远程 API 完成生成任务", + "file_path": "crates/llm/src/providers/llm_ollama.rs", + "functions": [ + "OllamaCompletionService::new", + "OllamaCompletionService::completion" + ], + "importance_score": 0.8, + "interfaces": [ + "CompletionService" + ], + "name": "llm_ollama.rs", + "source_summary": "use reqwest::Client;\nuse serde::{Deserialize, Serialize};\n\nuse types::llm_endpoint::LLMEndPoint;\nuse types::OllamaLLMProvider;\n\nuse crate::connector;\nuse crate::providers::types::{AITargetOption, CompletionService};\n\n#[derive(Serialize, Deserialize)]\nstruct RequestParameter {\n model: String,\n system: String,\n prompt: String,\n options: AITargetOption,\n images: Option,\n format: Option,\n keep_alive: String,\n stream: bool,\n}\n\n#[derive(Deserialize)]\nstruct CompletionReply {\n response: String,\n}\n\npub struct OllamaCompletionService {\n endpoint: LLMEndPoint,\n options: AITargetOption,\n client: Client,\n system_prompt: String,\n}\n\nimpl OllamaCompletionService {\n pub fn new(config: &OllamaLLMProvider, system_prompt: String, options: AITargetOption) -> anyhow::Result {\n let endpoint = config.endpoint.clone();\n Ok(\n OllamaCompletionService {\n endpoint,\n options,\n system_prompt,\n client: connector::new()?,\n }\n )\n }\n}\n\nimpl CompletionService for OllamaCompletionService {\n async fn completion(&self, content: String) -> anyhow::Result {\n let parameter = RequestParameter {\n model: self.endpoint.model.to_string(),\n system: self.system_prompt.to_string(),\n prompt: content,\n options: self.options.clone(),\n images: None,\n format: None,\n keep_alive: \"5m\".to_string(),\n stream: false,\n };\n let url = self.endpoint.get_api_generate_completion();\n let response = self.client.post(url).json(¶meter).send().await?;\n let reply: CompletionReply = response.json().await?;\n Ok(reply.response)\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.38, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 65, + "number_of_classes": 2, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "http_client", + "is_external": true, + "line_number": 1, + "name": "reqwest::Client", + "path": null, + "version": null + }, + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 2, + "name": "serde", + "path": null, + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 4, + "name": "types::llm_endpoint::LLMEndPoint", + "path": "types/llm_endpoint.rs", + "version": null + }, + { + "dependency_type": "config", + "is_external": false, + "line_number": 5, + "name": "types::OllamaLLMProvider", + "path": "types/mod.rs", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 7, + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 8, + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "version": null + } + ], + "detailed_description": "该组件实现了针对 Ollama 大语言模型的补全服务。通过封装请求体(RequestParameter)和解析响应(CompletionReply),利用 reqwest 发送 POST 请求至指定 endpoint 执行 completion 调用。系统提示词、模型配置和 AI 目标选项均在初始化时注入,确保可配置性与复用性。主要服务于需要与本地或私有部署的 Ollama 模型交互的功能模块。", + "interfaces": [ + { + "description": "创建一个新的 Ollama 补全服务实例", + "interface_type": "constructor", + "name": "OllamaCompletionService::new", + "parameters": [ + { + "description": "包含 endpoint 等配置信息", + "is_optional": false, + "name": "config", + "param_type": "OllamaLLMProvider" + }, + { + "description": "系统级提示语", + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": "AI 推理目标相关选项", + "is_optional": false, + "name": "options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "执行一次补全请求并返回生成结果", + "interface_type": "method", + "name": "OllamaCompletionService::completion", + "parameters": [ + { + "description": "用户输入内容", + "is_optional": false, + "name": "content", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "统一的补全服务接口契约", + "interface_type": "trait", + "name": "CompletionService", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "用于序列化为 JSON 的请求体结构", + "interface_type": "struct", + "name": "RequestParameter", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "用于反序列化响应体的结果结构", + "interface_type": "struct", + "name": "CompletionReply", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "Ollama 补全服务主结构体", + "interface_type": "struct", + "name": "OllamaCompletionService", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "为 Ollama 实现通用补全接口", + "interface_type": "implementation", + "name": "impl CompletionService for OllamaCompletionService", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "初始化 Ollama 补全服务所需的客户端与配置参数", + "构造符合 Ollama API 规范的请求数据结构", + "调用远程 /api/generate 接口完成文本生成任务", + "解析返回结果并提取生成文本", + "管理 HTTP 客户端生命周期及超时设置(间接依赖 connector)" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现与类OpenAI API兼容的LLM完成服务,支持通过HTTP请求调用远程模型进行对话补全。", + "file_path": "crates/llm/src/providers/llm_openaibase_like.rs", + "functions": [ + "OpenAILikeCompletionService::new", + "OpenAILikeCompletionService::completion" + ], + "importance_score": 0.8, + "interfaces": [ + "CompletionService" + ], + "name": "llm_openaibase_like.rs", + "source_summary": "use reqwest::Client;\nuse serde::{Deserialize, Serialize};\nuse types::OpenAILLMProvider;\n\nuse crate::connector;\nuse crate::providers::types::{AITargetOption, CompletionService};\n\n#[derive(Serialize)]\npub struct RequestParameters {\n pub(crate) model: String,\n pub(crate) messages: Vec,\n}\n\n#[derive(Serialize, Deserialize)]\npub struct Message {\n role: String,\n content: String,\n}\n\n#[derive(Deserialize)]\npub struct Response {\n pub(crate) choices: Vec,\n}\n\n#[derive(Deserialize)]\npub struct ChoiceChunk {\n #[allow(dead_code)]\n finish_reason: Option,\n message: Option,\n}\n\npub struct OpenAILikeCompletionService {\n pub(crate) config: OpenAILLMProvider,\n pub(crate) system_prompt: String,\n pub(crate) client: Client,\n}\n\nimpl OpenAILikeCompletionService {\n pub fn new(\n config: &OpenAILLMProvider,\n system_prompt: String,\n _options: AITargetOption,\n ) -> anyhow::Result {\n Ok(OpenAILikeCompletionService {\n system_prompt,\n config: config.clone(),\n client: connector::new()?,\n })\n }\n}\n\nimpl CompletionService for OpenAILikeCompletionService {\n async fn completion(&self, content: String) -> anyhow::Result {\n let sys_prompt = Message {\n role: \"system\".to_string(),\n content: self.system_prompt.to_string(),\n };\n\n let message = Message {\n role: \"user\".to_string(),\n content,\n };\n let parameter = RequestParameters {\n model: self.config.model_name.clone(),\n messages: vec![sys_prompt, message],\n };\n let response = self\n .client\n .post(self.config.api_base_url.clone())\n .header(\n \"Authorization\",\n format!(\"Bearer {}\", self.config.api_key.clone()),\n )\n .json(¶meter)\n .send()\n .await?;\n let resp: Response = response.json().await?;\n let content = match &resp.choices[0].message {\n Some(m) => m.content.clone(),\n None => String::new(),\n };\n Ok(content)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.87, + "coupling_factor": 0.59, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 84, + "number_of_classes": 5, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "http_client", + "is_external": true, + "line_number": 1, + "name": "reqwest::Client", + "path": null, + "version": null + }, + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 2, + "name": "serde", + "path": null, + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 3, + "name": "types::OpenAILLMProvider", + "path": "./types.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 5, + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 6, + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "version": null + }, + { + "dependency_type": "trait", + "is_external": false, + "line_number": 6, + "name": "crate::providers::types::CompletionService", + "path": "./crates/llm/src/providers/types.rs", + "version": null + } + ], + "detailed_description": "该组件实现了与OpenAI风格API兼容的语言模型调用逻辑。它封装了请求构造(RequestParameters、Message)、响应解析(Response、ChoiceChunk),并通过reqwest客户端发送POST请求到指定API端点。核心功能由OpenAILikeCompletionService结构体提供,遵循CompletionService trait接口,支持注入系统提示词和动态用户输入,适用于构建基于大语言模型的智能服务。", + "interfaces": [ + { + "description": "定义语言模型补全服务的标准接口,本组件为其提供具体实现。", + "interface_type": "trait", + "name": "CompletionService", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "用于序列化为JSON请求体的参数结构", + "interface_type": "struct", + "name": "RequestParameters", + "parameters": [ + { + "description": "指定使用的模型名称", + "is_optional": false, + "name": "model", + "param_type": "String" + }, + { + "description": "对话消息序列", + "is_optional": false, + "name": "messages", + "param_type": "Vec" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "表示单条对话消息的数据结构", + "interface_type": "struct", + "name": "Message", + "parameters": [ + { + "description": "角色类型:system/user/assistant", + "is_optional": false, + "name": "role", + "param_type": "String" + }, + { + "description": "消息内容", + "is_optional": false, + "name": "content", + "param_type": "String" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "用于反序列化API响应的结构体", + "interface_type": "struct", + "name": "Response", + "parameters": [ + { + "description": "模型返回的候选结果列表", + "is_optional": false, + "name": "choices", + "param_type": "Vec" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "表示单个生成选项的结果块", + "interface_type": "struct", + "name": "ChoiceChunk", + "parameters": [ + { + "description": "生成结束原因", + "is_optional": true, + "name": "finish_reason", + "param_type": "Option" + }, + { + "description": "返回的消息内容", + "is_optional": true, + "name": "message", + "param_type": "Option" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "实现CompletionService的核心服务结构体", + "interface_type": "struct", + "name": "OpenAILikeCompletionService", + "parameters": [ + { + "description": "LLM提供者配置", + "is_optional": false, + "name": "config", + "param_type": "OpenAILLMProvider" + }, + { + "description": "系统级提示词", + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": "HTTP客户端实例", + "is_optional": false, + "name": "client", + "param_type": "Client" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "构造新的服务实例,初始化HTTP客户端", + "interface_type": "function", + "name": "OpenAILikeCompletionService::new", + "parameters": [ + { + "description": "引用配置对象", + "is_optional": false, + "name": "config", + "param_type": "&OpenAILLMProvider" + }, + { + "description": "系统提示词", + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": "目标选项(当前未使用)", + "is_optional": false, + "name": "_options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "执行一次完整的LLM补全过程,返回生成文本", + "interface_type": "function", + "name": "OpenAILikeCompletionService::completion", + "parameters": [ + { + "description": "用户输入内容", + "is_optional": false, + "name": "content", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "封装与OpenAI兼容API的通信协议", + "构造符合规范的请求数据结构", + "处理HTTP响应并提取生成文本", + "管理LLM调用所需的配置与认证信息", + "实现统一的补全服务接口" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现基于GLM大语言模型的补全服务,通过适配OpenAI兼容接口完成请求。", + "file_path": "crates/llm/src/providers/llm_glm.rs", + "functions": [ + "new", + "completion" + ], + "importance_score": 0.8, + "interfaces": [ + "CompletionService" + ], + "name": "llm_glm.rs", + "source_summary": "use types::{GLMLLMProvider, OpenAILLMProvider};\n\nuse crate::connector;\nuse crate::providers::llm_openaibase_like::OpenAILikeCompletionService;\nuse crate::providers::types::{AITargetOption, CompletionService};\n\npub struct GLMCompletionService {\n inner: OpenAILikeCompletionService\n}\n\nimpl GLMCompletionService {\n pub fn new(config: &GLMLLMProvider, system_prompt: String, _options: AITargetOption) -> anyhow::Result {\n Ok(\n GLMCompletionService {\n inner: OpenAILikeCompletionService {\n system_prompt,\n config: OpenAILLMProvider {\n model_name: config.model_name.clone(),\n api_base_url: config.api_base_url.clone(),\n api_key: config.api_key.clone(),\n },\n client: connector::new()?,\n }\n }\n )\n }\n}\n\nimpl CompletionService for GLMCompletionService {\n async fn completion(&self, content: String) -> anyhow::Result {\n self.inner.completion(content).await\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.57, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 33, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": false, + "line_number": 1, + "name": "types", + "path": "types::{GLMLLMProvider, OpenAILLMProvider}", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 3, + "name": "connector", + "path": "crate::connector", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 4, + "name": "llm_openaibase_like", + "path": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 5, + "name": "types", + "path": "crate::providers::types::{AITargetOption, CompletionService}", + "version": null + } + ], + "detailed_description": "该组件实现了针对智谱AI GLM系列大模型的补全功能。它通过封装一个通用的OpenAI类接口(OpenAILikeCompletionService),将GLMProvider配置转换为OpenAILLMProvider格式,从而复用已有的OpenAI兼容逻辑进行HTTP通信。其主要作用是作为适配层,使系统能够以统一方式调用不同厂商但协议相似的大模型服务。", + "interfaces": [ + { + "description": "创建新的GLM补全服务实例", + "interface_type": "constructor", + "name": "GLMCompletionService::new", + "parameters": [ + { + "description": "GLM模型配置信息", + "is_optional": false, + "name": "config", + "param_type": "&GLMLLMProvider" + }, + { + "description": "系统提示词", + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": "目标选项(当前未使用)", + "is_optional": false, + "name": "_options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "执行补全请求并返回结果", + "interface_type": "trait_method", + "name": "CompletionService::completion", + "parameters": [ + { + "description": "用户输入内容", + "is_optional": false, + "name": "content", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "将GLM模型提供商配置适配为OpenAI兼容格式", + "构建并初始化GLM补全服务实例", + "代理调用底层OpenAI-like服务完成文本补全", + "处理GLM特有的初始化参数并传递至通用服务层", + "确保与系统中其他LLM提供者的一致性接口" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "Mistral Qino Agent服务,基于Mistral AI API实现聊天补全功能的智能Agent组件", + "file_path": "crates/llm/src/providers/llm_mistral.rs", + "functions": [ + "new", + "completion" + ], + "importance_score": 0.8, + "interfaces": [ + "CompletionService" + ], + "name": "llm_mistral.rs", + "source_summary": "use serde::Serialize;\nuse types::OpenAILLMProvider;\n\nuse crate::connector;\nuse crate::providers::llm_openaibase_like::OpenAILikeCompletionService;\nuse crate::providers::types::{AITargetOption, CompletionService};\n\nconst API_AGENT_QINO_COMPLETIONS_FULL: &str = \"https://api.mistral.ai/v1/chat/completions\";\nconst MISTRAL_AGENT_QINO_ID: &str = \"\";\nconst MISTRAL_AGENT_QINO_KEY: &str = \"\";\n\n#[derive(Serialize)]\npub struct RequestParameters {\n messages: Vec,\n agent_id: String,\n}\n\n#[derive(Serialize)]\npub struct Message {\n role: String,\n content: String,\n}\n\npub struct MistralQinoAgentService {\n inner: OpenAILikeCompletionService\n}\n\nimpl MistralQinoAgentService {\n pub fn new(system_prompt: String, _options: AITargetOption) -> anyhow::Result {\n Ok(\n MistralQinoAgentService {\n inner: OpenAILikeCompletionService {\n config: OpenAILLMProvider {\n model_name: MISTRAL_AGENT_QINO_ID.to_string(),\n api_base_url: API_AGENT_QINO_COMPLETIONS_FULL.to_string(),\n api_key: MISTRAL_AGENT_QINO_KEY.to_string(),\n },\n system_prompt,\n client: connector::new()?,\n }\n }\n )\n }\n}\n\nimpl CompletionService for MistralQinoAgentService {\n async fn completion(&self, content: String) -> anyhow::Result {\n self.inner.completion(content).await\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.6, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 50, + "number_of_classes": 3, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 1, + "name": "serde", + "path": null, + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "types::OpenAILLMProvider", + "path": "types", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 4, + "name": "crate::connector", + "path": "./crates/llm/src/connector.rs", + "version": null + }, + { + "dependency_type": "service", + "is_external": false, + "line_number": 5, + "name": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "path": "./crates/llm/src/providers/llm_openaibase_like.rs", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 6, + "name": "crate::providers::types::AITargetOption", + "path": "./crates/llm/src/providers/types.rs", + "version": null + } + ], + "detailed_description": "该组件实现了针对Mistral AI平台的聊天补全服务代理。通过封装OpenAILikeCompletionService,复用OpenAI兼容的接口逻辑,适配Mistral API的特定端点和认证信息。支持系统提示词配置,并通过reqwest客户端发送请求。主要处理流程包括:初始化服务时设置模型配置和系统提示,调用completion方法时转发请求至底层OpenAI类服务。", + "interfaces": [ + { + "description": "定义语言模型补全服务的标准接口", + "interface_type": "trait", + "name": "CompletionService", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "构造一个新的MistralQinoAgentService实例", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": "系统提示词,用于初始化AI的行为模式", + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": "目标选项参数(当前未使用)", + "is_optional": false, + "name": "_options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "执行一次对话补全请求并返回AI响应", + "interface_type": "function", + "name": "completion", + "parameters": [ + { + "description": "用户输入内容", + "is_optional": false, + "name": "content", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "API请求参数结构体", + "interface_type": "struct", + "name": "RequestParameters", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "messages", + "param_type": "Vec" + }, + { + "description": null, + "is_optional": false, + "name": "agent_id", + "param_type": "String" + } + ], + "return_type": null, + "visibility": "pub" + }, + { + "description": "对话消息结构体", + "interface_type": "struct", + "name": "Message", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "role", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "content", + "param_type": "String" + } + ], + "return_type": null, + "visibility": "pub" + }, + { + "description": "Mistral服务主结构体", + "interface_type": "struct", + "name": "MistralQinoAgentService", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "为MistralQinoAgentService实现CompletionService trait", + "interface_type": "impl", + "name": "impl CompletionService for MistralQinoAgentService", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "作为Mistral AI服务的适配层,提供统一的CompletionService接口", + "管理Mistral API的连接配置(URL、模型ID、密钥)", + "封装请求参数结构体(RequestParameters, Message)用于序列化", + "通过OpenAILikeCompletionService复用通用LLM交互逻辑", + "提供系统级提示词注入能力以引导AI行为" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "LLM服务代理组件,封装多种LLM提供商的调用逻辑,提供统一的completion接口。", + "file_path": "crates/llm/src/llm_agent.rs", + "functions": [ + "new", + "completion" + ], + "importance_score": 0.8, + "interfaces": [ + "CompletionAgent" + ], + "name": "llm_agent.rs", + "source_summary": "use types::{LLMProviderType, LLMSection};\n\nuse crate::providers::llm_glm::GLMCompletionService;\nuse crate::providers::llm_mistral::MistralQinoAgentService;\nuse crate::providers::llm_ollama::OllamaCompletionService;\nuse crate::providers::llm_openaibase_like::OpenAILikeCompletionService;\nuse crate::providers::llm_platform::PlatformAgentService;\nuse crate::providers::types::{AITargetOption, CompletionService};\n\nenum CompletionServiceEnums {\n Ollama(OllamaCompletionService),\n Mistral(MistralQinoAgentService),\n Platform(PlatformAgentService),\n GLM(GLMCompletionService),\n OpenAI(OpenAILikeCompletionService),\n}\n\n/// LLM Generate服务代理\npub struct CompletionAgent {\n provider: CompletionServiceEnums,\n // 还不能用box,box的trait需要对象安全,即函数中不能使用async、self、泛型等。\n}\n\nimpl CompletionAgent {\n pub fn new(llm_section: LLMSection, system_prompt: String, options: AITargetOption) -> anyhow::Result {\n let provider_type = llm_section.active_provider_type;\n\n match provider_type {\n LLMProviderType::Ollama => {\n let provider = OllamaCompletionService::new(&llm_section.provider_ollama, system_prompt, options)?;\n Ok(\n CompletionAgent {\n provider: CompletionServiceEnums::Ollama(provider),\n }\n )\n }\n LLMProviderType::Mistral => {\n let provider = MistralQinoAgentService::new(system_prompt, options)?;\n Ok(\n CompletionAgent {\n provider: CompletionServiceEnums::Mistral(provider),\n }\n )\n }\n LLMProviderType::Platform => {\n let provider = PlatformAgentService::new(&llm_section.provider_platform, system_prompt, options)?;\n Ok(\n CompletionAgent {\n provider: CompletionServiceEnums::Platform(provider),\n }\n )\n }\n LLMProviderType::GLM => {\n let provider = GLMCompletionService::new(&llm_section.provider_glm, system_prompt, options)?;\n Ok(\n CompletionAgent {\n provider: CompletionServiceEnums::GLM(provider),\n }\n )\n }\n LLMProviderType::OpenAI => {\n let provider = OpenAILikeCompletionService::new(&llm_section.provider_openai, system_prompt, options)?;\n Ok(\n CompletionAgent {\n provider: CompletionServiceEnums::OpenAI(provider),\n }\n )\n }\n }\n }\n\n /// 调用LLM Completion能力,参数`message`会被作为user prompt传递给LLM。\n pub async fn completion(&self, message: String) -> anyhow::Result {\n match &self.provider {\n CompletionServiceEnums::Ollama(p) => p.completion(message).await,\n CompletionServiceEnums::Mistral(p) => p.completion(message).await,\n CompletionServiceEnums::Platform(p) => p.completion(message).await,\n CompletionServiceEnums::GLM(p) => p.completion(message).await,\n CompletionServiceEnums::OpenAI(p) => p.completion(message).await\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 7.0, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 82, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": false, + "line_number": 1, + "name": "types", + "path": "types", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 3, + "name": "crate::providers::llm_glm::GLMCompletionService", + "path": "crates/llm/src/providers/llm_glm.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 4, + "name": "crate::providers::llm_mistral::MistralQinoAgentService", + "path": "crates/llm/src/providers/llm_mistral.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 5, + "name": "crate::providers::llm_ollama::OllamaCompletionService", + "path": "crates/llm/src/providers/llm_ollama.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 6, + "name": "crate::providers::llm_openaibase_like::OpenAILikeCompletionService", + "path": "crates/llm/src/providers/llm_openaibase_like.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 7, + "name": "crate::providers::llm_platform::PlatformAgentService", + "path": "crates/llm/src/providers/llm_platform.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 8, + "name": "crate::providers::types::CompletionService", + "path": "crates/llm/src/providers/types.rs", + "version": null + } + ], + "detailed_description": "该组件实现了一个面向多种LLM(大语言模型)提供商的代理模式。通过枚举类型CompletionServiceEnums封装了Ollama、Mistral、Platform、GLM和OpenAI等不同提供商的具体服务实现,并在CompletionAgent结构体中根据配置动态选择实际的服务实例。其主要功能是屏蔽底层不同LLM提供商的接口差异,向上层提供统一的文本生成能力(completion)。构造函数new根据LLMSection中的active_provider_type字段初始化对应的服务实例,而异步方法completion则负责将用户输入的消息转发给对应提供商并返回结果。", + "interfaces": [ + { + "description": "LLM生成服务代理,负责调用不同提供商的completion服务。", + "interface_type": "struct", + "name": "CompletionAgent", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "创建一个新的CompletionAgent实例,根据提供的LLMSection配置选择具体的LLM服务实现。", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": "包含LLM配置信息的结构体", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + }, + { + "description": "系统提示词", + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": "AI目标选项", + "is_optional": false, + "name": "options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "pub" + }, + { + "description": "调用底层LLM服务进行文本生成,将用户消息作为prompt传递。", + "interface_type": "function", + "name": "completion", + "parameters": [ + { + "description": "用户输入的消息", + "is_optional": false, + "name": "message", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "pub" + }, + { + "description": "内部枚举类型,用于持有不同类型LLM服务的实例。", + "interface_type": "enum", + "name": "CompletionServiceEnums", + "parameters": [], + "return_type": null, + "visibility": "private" + } + ], + "responsibilities": [ + "作为多种LLM服务的统一入口,实现服务路由", + "根据配置动态初始化对应的LLM服务提供者", + "转发用户请求到具体的LLM服务并处理响应", + "封装底层LLM服务的差异性,提供一致的API接口" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现Feeds功能的核心业务逻辑,包括订阅管理、内容抓取、文章处理管道和用户交互。", + "file_path": "crates/feed_api_rs/src/features/impl_default.rs", + "functions": [ + "new", + "sync_user_profile", + "process_article_pipelines", + "create_futures_for_update_feeds", + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "importance_score": 0.8, + "interfaces": [ + "FeaturesAPI" + ], + "name": "impl_default.rs", + "source_summary": "use std::sync::Arc;\n\nuse chrono::{Datelike, NaiveDate, Utc, Weekday};\nuse spdlog::{error, info};\nuse tauri::{AppHandle, Runtime};\nuse tokio::sync::RwLock;\n\nuse intelligent::article_processor::assistant::Assistant;\nuse intelligent::article_processor::llm_processor::{\n ArticleLLMProcessor, IPresetArticleLLMProcessor,\n};\nuse intelligent::article_processor::melt::Melt;\nuse intelligent::article_processor::optimizer::Optimizer;\nuse intelligent::article_processor::purge::Purge;\nuse intelligent::article_processor::types::IArticleProcessor;\nuse ollama::{query_platform, ProgramStatus};\nuse recorder::article_recorder_service::ArticleRecorderService;\nuse recorder::entity::article_record::{Model as ArticleRecord, Model};\nuse scrap::rss::RSSFetcher;\nuse scrap::search::utils::trim_html_with_script_and_style;\nuse scrap::search::{baidu, bing, ScrapProviderEnums};\nuse scrap::types::IFetcher;\nuse types::{AppConfig, Article, ConversationMessage, FeedTargetDescription, FeedsPackage, LLMInstructOption, ScrapProviderType, UserConfig, LLMSection};\n\nuse crate::startup::init_app_config::sync_to;\nuse crate::{application_context::ApplicationContext, startup::init_user_profile};\nuse crate::utils::do_parallel_with_limit;\n\nuse super::api::FeaturesAPI;\n\nconst SPECIFY_FEED_IDSET_TODAY_FILTER: &str = \"TODAY_FILTER\";\nconst SPECIFY_FEED_IDSET_WEEKEND_FILTER: &str = \"WEEKEND_FILTER\";\n\nconst SPECIFY_FEED_IDSET_FAVORITE_FILTER: &str = \"FAVORITE_FILTER\";\nconst SPECIFY_FEED_IDSET_UNREAD_FILTER: &str = \"UNREAD_FILTER\";\n\npub struct FeaturesAPIImpl {\n pub context: Arc>,\n scrap_provider: ScrapProviderEnums,\n article_recorder_service: Arc,\n}\n\nimpl FeaturesAPIImpl {\n // 创建FeaturesAPIImpl实例\n pub async fn new(ctx: ApplicationContext) -> anyhow::Result {\n // 基础配置信息\n let app_config = &ctx.app_config;\n let llm_section = app_config.llm.clone();\n\n // 初始化ArticleRecorderService实例\n let mut ars = ArticleRecorderService::default();\n ars.initialize().await?;\n let article_recorder_service = Arc::new(ars);\n\n\n // 初始化爬虫实例\n let scrap_provider = &app_config.scrap.provider;\n let scrap_provider = match scrap_provider {\n ScrapProviderType::Baidu => {\n ScrapProviderEnums::Baidu(baidu::Provider::new(llm_section)?)\n }\n ScrapProviderType::Bing => ScrapProviderEnums::Bing(bing::Provider::new(llm_section)?),\n };\n let context = Arc::new(RwLock::new(ctx));\n\n Ok(FeaturesAPIImpl {\n context,\n scrap_provider,\n article_recorder_service,\n })\n }\n\n async fn sync_user_profile(&self, user_config: &UserConfig) -> anyhow::Result<()> {\n init_user_profile::sync_to(user_config).await\n }\n\n async fn process_article_pipelines(\n article: &mut Article,\n purge: &ArticleLLMProcessor,\n optimizer: &ArticleLLMProcessor,\n melt: &ArticleLLMProcessor,\n opt: &LLMInstructOption,\n ) -> anyhow::Result<(Article, Article, Article)> {\n let out_purged_article = purge.process(article, opt.clone()).await?;\n info!(\n \"article purged, title = {}, source_link = {}, optimizing\",\n article.title, article.source_link\n );\n\n let out_optimized_article = optimizer.process(&out_purged_article, opt.clone()).await?;\n info!(\n \"purged article optimized, title = {}, melting\",\n out_purged_article.title\n );\n if let Some(optimized_content) = out_optimized_article.content.clone() {\n if optimized_content.contains(\"QINO-AGENTIC-EXECUTION-FAILURE\") {\n return Err(anyhow::Error::msg(\"QINO-AGENTIC-EXECUTION-FAILURE\"));\n }\n }\n\n let out_melted_article = melt.process(&out_optimized_article, opt.clone()).await?;\n info!(\n \"optimized article melted, title = {}, recording\",\n out_melted_article.title\n );\n\n Ok((\n out_purged_article,\n out_optimized_article,\n out_melted_article,\n ))\n }\n\n async fn create_futures_for_update_feeds(article_recorder_service: Arc, mut article: Article, feed_id: String, purge: Arc, optimizer: Arc, melt: Arc, package_id: String, llm_section: LLMSection) -> anyhow::Result<()> {\n match Self::process_article_pipelines(&mut article, &purge, &optimizer, &melt, &llm_section.instruct).await {\n Ok((out_purged_article, out_optimized_article, out_melted_article)) => {\n article_recorder_service\n .insert(vec![ArticleRecord {\n id: 0,\n source_link: out_melted_article.source_link,\n title: out_melted_article.title,\n purged_content: out_purged_article.content.unwrap_or_default(),\n head_read: out_purged_article.head_read.unwrap_or_default(),\n optimized_content: out_optimized_article.content.unwrap_or_default(),\n melted_content: out_melted_article.content.unwrap_or_default(),\n published_at: Utc::now().date_naive(),\n created_at: Utc::now().date_naive(),\n has_read: false,\n is_favorite: false,\n group_id: feed_id.to_owned(),\n }])\n .await?;\n info!(\n \"article recorded to the feed_id = {}, title = {}\",\n &feed_id, article.title\n );\n }\n Err(e) => error!(\n \"process_article_pipelines execution failure, the requirements of package_id = {}, feed_id = {}, source_link = {}, error = {}\",\n package_id,\n &feed_id,\n article.source_link,\n e)\n };\n Ok(())\n }\n}\n\n// 在 FeaturesAPIImpl 结构体上实现 FeaturesAPI 接口的所有方法\nimpl FeaturesAPI for FeaturesAPIImpl {\n // #[macro_api_interceptor::monitor]\n async fn add_feeds_package(&self, feeds_package: FeedsPackage) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n if user_config.add_feeds_packages(feeds_package) {\n return self.sync_user_profile(user_config).await;\n }\n Err(anyhow::Error::msg(\n \"add_feeds_package failure, may be the feeds package already existed\",\n ))\n }\n\n async fn remove_feeds_package(&self, package_id: &str) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n if user_config.remove_feeds_package(package_id) {\n return self.sync_user_profile(user_config).await;\n }\n Err(anyhow::Error::msg(\n format!(\n \"remove_feeds_package failure, the feeds package was not found, the requirements of package_id = {}\",\n package_id,\n )\n ))\n }\n\n async fn rename_feeds_package(&self, package_id: &str, new_name: &str) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n if user_config.rename_feeds_package(package_id, new_name) {\n self.sync_user_profile(user_config).await?;\n Ok(())\n } else {\n Err(anyhow::Error::msg(format!(\n \"rename_feeds_package failure, the feeds package was not found, the requirements of package_id = {}\",\n package_id,\n )))\n }\n }\n\n async fn add_feed(&self, package_id: &str, ftd: FeedTargetDescription) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n match user_config.find_feeds_package_mut(package_id) {\n Some(package) => {\n package.feeds.push(ftd);\n self.sync_user_profile(user_config).await\n }\n None => Err(anyhow::Error::msg(\n format!(\n \"add_feed failure, the feeds package was not found, the requirements of package_id = {}, feed_name = {}, feed_id = {}\",\n package_id,\n ftd.name.as_str(),\n ftd.id.as_str()\n )\n ))\n }\n }\n\n async fn remove_feed(&self, package_id: &str, feed_id: &str) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n match user_config.remove_feed(package_id, feed_id) {\n true => self.sync_user_profile(user_config).await,\n false => Err(anyhow::Error::msg(\n format!(\n \"remove_feed failure, the feeds package was not found, the requirements of package_id = {}, feed_id = {}\",\n package_id,\n feed_id\n )\n ))\n }\n }\n\n async fn rename_feed(\n &self,\n package_id: &str,\n feed_id: &str,\n new_name: &str,\n ) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n match user_config.rename_feed(package_id, feed_id, new_name) {\n true => self.sync_user_profile(user_config).await,\n false => Err(anyhow::Error::msg(\n format!(\n \"rename_feed failure, the feeds package was not found, the requirements of package_id = {}, feed_id = {}\",\n package_id,\n feed_id\n )\n ))\n }\n }\n\n async fn change_feed_data(\n &self,\n package_id: &str,\n feed_id: &str,\n data: Vec,\n ) -> anyhow::Result<()> {\n let context_guarded = &mut self.context.write().await;\n let user_config = &mut context_guarded.user_config;\n match user_config.change_feed_data(package_id, feed_id, data) {\n true => self.sync_user_profile(user_config).await,\n false => Err(anyhow::Error::msg(\n format!(\n \"change_feed_data failure, the feeds package was not found, the requirements of package_id = {}, feed_id = {}\",\n package_id,\n feed_id\n )\n ))\n }\n }\n\n async fn get_feeds_packages(&self) -> Vec {\n let context_guarded = &self.context.read().await;\n context_guarded.user_config.feeds_packages.clone()\n }\n\n async fn get_feeds_by_package(&self, package_id: &str) -> Option {\n let context_guarded = &self.context.read().await;\n context_guarded.user_config.find_feeds_package(package_id)\n }\n\n async fn update_feed_contents(\n &self,\n package_id: &str,\n feed_id: &str,\n app_handle: Option>,\n ) -> anyhow::Result<()> {\n let user_config;\n let llm_section;\n {\n let context_guarded = self.context.read().await;\n user_config = context_guarded.user_config.clone();\n llm_section = context_guarded.app_config.llm.clone();\n }\n if let Some(ftd) = user_config.find_feed(package_id, feed_id) {\n // #region begin\n let articles = match ftd.fetcher_id.as_str() {\n \"scrap\" => {\n self.scrap_provider\n .fetch(app_handle, &llm_section, ftd.clone())\n .await?\n }\n \"rss\" => {\n RSSFetcher::default()\n .fetch(app_handle, &llm_section, ftd.clone())\n .await?\n }\n _ => vec![],\n };\n let article_recorder_service = &self.article_recorder_service;\n let purge = Arc::new(Purge::new_processor(llm_section.clone())?);\n let optimizer = Arc::new(Optimizer::new_processor(llm_section.clone())?);\n let melt = Arc::new(Melt::new_processor(llm_section.clone())?);\n let mut articles_process_futures = vec![];\n\n for article in articles.iter() {\n if article_recorder_service\n .exists_by_source(&article.source_link)\n .await?\n {\n info!(\n \"article existed, title = {}, source_link = {}\",\n article.title, article.source_link\n );\n continue;\n }\n\n let future = Self::create_futures_for_update_feeds(\n Arc::clone(&article_recorder_service),\n article.clone(),\n feed_id.to_owned(),\n Arc::clone(&purge),\n Arc::clone(&optimizer),\n Arc::clone(&melt),\n package_id.to_owned(),\n llm_section.clone()\n );\n articles_process_futures.push(future);\n }\n do_parallel_with_limit(articles_process_futures, llm_section.max_parallel.unwrap_or(5)).await;\n return Ok(());\n }\n let error_msg = format!(\n \"update_feed_contents failure, the feed was not found, the requirements of package_id = {}, feed_id = {}\",\n package_id,\n feed_id\n );\n error!(\"{}\", error_msg);\n Err(anyhow::Error::msg(error_msg))\n }\n\n /// 读取订阅中的内容,支持分页。\n async fn read_feed_contents(\n &self,\n feed_id: &str,\n offset: u64,\n count: u64,\n ) -> anyhow::Result> {\n if feed_id == SPECIFY_FEED_IDSET_TODAY_FILTER {\n let now: NaiveDate = Utc::now().date_naive();\n return self\n .article_recorder_service\n .query_backward_in_duration(offset, count, now, now)\n .await;\n }\n if feed_id == SPECIFY_FEED_IDSET_WEEKEND_FILTER {\n let end: NaiveDate = Utc::now().date_naive();\n let monday_days_from_now = ((end.weekday() as i64 - Weekday::Mon as i64) % 7) as u64;\n let start = end\n .checked_sub_days(chrono::Days::new(monday_days_from_now))\n .expect(\"SPECIFY_FEED_IDSET_WEEKEND_FILTER:日期转换错误,找不到本周周一的日期。\");\n return self\n .article_recorder_service\n .query_backward_in_duration(offset, count, start, end)\n .await;\n }\n if feed_id == SPECIFY_FEED_IDSET_FAVORITE_FILTER {\n return self\n .article_recorder_service\n .query_favorite(offset, count)\n .await;\n }\n if feed_id == SPECIFY_FEED_IDSET_UNREAD_FILTER {\n return self\n .article_recorder_service\n .query_unread(offset, count)\n .await;\n }\n self.article_recorder_service\n .query_backward(Some(feed_id), offset, count)\n .await\n }\n\n async fn query_by_id(&self, id: i32) -> anyhow::Result> {\n self.article_recorder_service.query_by_id(id).await\n }\n\n async fn mark_as_read(&self, id: i32) -> anyhow::Result<()> {\n self.article_recorder_service.mark_as_read(id).await?;\n Ok(())\n }\n\n async fn set_favorite(&self, id: i32, is_favorite: bool) -> anyhow::Result<()> {\n self.article_recorder_service\n .set_favorite(id, is_favorite)\n .await?;\n Ok(())\n }\n\n async fn get_app_config(&self) -> anyhow::Result {\n let context_guarded = self.context.read().await;\n Ok(context_guarded.app_config.clone())\n }\n\n async fn set_app_config(&self, app_config: AppConfig) -> anyhow::Result<()> {\n let mut context_guarded = self.context.write().await;\n context_guarded.app_config = app_config;\n sync_to(&context_guarded.app_config).await?;\n Ok(())\n }\n\n /// 获得Ollama实例状态\n async fn get_ollama_status(&self) -> anyhow::Result {\n let llm_section = {\n self.context\n .read()\n .await\n .app_config\n .llm\n .provider_ollama\n .clone()\n };\n match query_platform(&llm_section.endpoint).await {\n Ok(information) => Ok(information.status),\n Err(_) => Ok(ProgramStatus::Uninstall),\n }\n }\n\n /// 下载Ollama\n async fn download_ollama(&self) -> anyhow::Result<()> {\n open::that(\"https://ollama.com/download\")?;\n Ok(())\n }\n\n /// 启动Ollama实例\n async fn launch_ollama(&self) -> anyhow::Result<()> {\n ollama::launch().await\n }\n\n async fn open_article_external(&self, url: &str) -> anyhow::Result<()> {\n open::that(url)?;\n Ok(())\n }\n\n async fn update_article_by_source(\n &self,\n article_id: i32,\n source_text: String,\n ) -> anyhow::Result {\n let sharked_html = trim_html_with_script_and_style(source_text.as_str());\n let llm_section = { self.context.read().await.app_config.llm.clone() };\n\n let article_recorder_service = &self.article_recorder_service;\n let purge = Purge::new_processor(llm_section.clone())?;\n let optimizer = Optimizer::new_processor(llm_section.clone())?;\n let melt = Melt::new_processor(llm_section.clone())?;\n\n let article_opt = article_recorder_service.query_by_id(article_id).await?;\n match article_opt {\n None => Ok(false),\n Some(article_model) => {\n let mut article = Article {\n title: article_model.title.to_owned(),\n head_read: Some(article_model.head_read.to_owned()),\n source_link: article_model.source_link.to_owned(),\n summary: None,\n content: Some(sharked_html),\n date_created: \"\".to_string(),\n date_read: None,\n };\n match Self::process_article_pipelines(\n &mut article,\n &purge,\n &optimizer,\n &melt,\n &llm_section.instruct,\n )\n .await\n {\n Ok((out_purged_article, out_optimized_article, out_melted_article)) => {\n let purged_content = out_purged_article.content.unwrap_or_default();\n let optimized_content = out_optimized_article.content.unwrap_or_default();\n let melted_content = out_melted_article.content.unwrap_or_default();\n article_recorder_service\n .update_content(\n article_model,\n purged_content,\n optimized_content,\n melted_content,\n )\n .await?;\n info!(\"article updated, article_id = {}\", article_id);\n Ok(true)\n }\n Err(e) => {\n error!(\n \"process_article_pipelines execution failure, the requirements of article_id = {}, error = {}\",\n article_id,\n e);\n Ok(false)\n }\n }\n }\n }\n }\n\n async fn chat_with_article_assistant(\n &self,\n article_id: i32,\n user_prompt: &str,\n history: Vec,\n ) -> anyhow::Result {\n let llm_section = { self.context.read().await.app_config.llm.clone() };\n let assistant = Assistant::new(llm_section.clone());\n\n let article_opt = self\n .article_recorder_service\n .query_by_id(article_id)\n .await?;\n if let Some(article) = article_opt {\n return assistant\n .chat(article.optimized_content, user_prompt, history)\n .await;\n }\n Ok(format!(\n \"文章不存在, article_id = {}, user_prompt = {}\",\n article_id, user_prompt\n ))\n }\n\n async fn search_contents_by_keyword(\n &self,\n keyword: &str,\n offset: u64,\n count: u64,\n ) -> anyhow::Result> {\n self.article_recorder_service\n .search_contents_by_keyword(keyword, offset, count)\n .await\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.65, + "coupling_factor": 0.73, + "cyclomatic_complexity": 25.0, + "depth_of_inheritance": 0, + "lines_of_code": 544, + "number_of_classes": 1, + "number_of_functions": 22 + }, + "dependencies": [ + { + "dependency_type": "std", + "is_external": false, + "line_number": null, + "name": "std::sync::Arc", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "chrono", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "tokio::sync::RwLock", + "path": null, + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::assistant::Assistant", + "path": "crates/intelligent/src/article_processor/assistant/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::llm_processor::ArticleLLMProcessor", + "path": "crates/intelligent/src/article_processor/llm_processor/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crates/intelligent/src/article_processor/llm_processor/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::melt::Melt", + "path": "crates/intelligent/src/article_processor/melt/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::optimizer::Optimizer", + "path": "crates/intelligent/src/article_processor/optimizer/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::purge::Purge", + "path": "crates/intelligent/src/article_processor/purge/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "intelligent::article_processor::types::IArticleProcessor", + "path": "crates/intelligent/src/article_processor/types.rs", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "ollama", + "path": null, + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "recorder::article_recorder_service::ArticleRecorderService", + "path": "crates/recorder/src/article_recorder_service/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "recorder::entity::article_record::Model", + "path": "crates/recorder/src/entity/article_record.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "scrap::rss::RSSFetcher", + "path": "crates/scrap/src/rss/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "scrap::search::baidu", + "path": "crates/scrap/src/search/baidu.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "scrap::search::bing", + "path": "crates/scrap/src/search/bing.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "scrap::search::ScrapProviderEnums", + "path": "crates/scrap/src/search/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "scrap::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "types", + "path": "crates/types/src/lib.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "crate::startup::init_app_config::sync_to", + "path": "crates/feed_api_rs/src/startup/init_app_config.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "crate::application_context::ApplicationContext", + "path": "crates/feed_api_rs/src/application_context.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "crate::startup::init_user_profile", + "path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "crate::utils::do_parallel_with_limit", + "path": "crates/feed_api_rs/src/utils/mod.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "super::api::FeaturesAPI", + "path": "crates/feed_api_rs/src/features/api.rs", + "version": null + } + ], + "detailed_description": "该组件是Feed系统的核心业务实现。它通过`FeaturesAPIImpl`结构体实现了`FeaturesAPI`接口,提供了对订阅包(FeedsPackage)和单个订阅源(Feed)的全生命周期管理(增删改查)。其核心功能在于内容更新管道:当调用`update_feed_contents`时,会根据配置选择`scrap`或`rss`作为抓取器获取原始文章列表。对于每篇新文章,会启动一个异步处理流程,依次通过Purge、Optimizer、Melt三个LLM处理器进行内容净化、优化和融合,并将最终结果存入数据库。此外,该组件还提供读取已存档内容(支持多种过滤条件如今日、周末、收藏夹)、与文章助手对话、搜索等功能,并封装了对Ollama服务的启停控制。", + "interfaces": [ + { + "description": "定义了所有前端或系统其他部分需要调用的Feed相关功能的接口。", + "interface_type": "trait", + "name": "FeaturesAPI", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "管理用户订阅包和订阅源的元数据配置", + "协调并执行从外部源抓取和处理文章内容的完整管道", + "提供对已存档文章的查询、标记和搜索等用户交互功能", + "作为应用配置和用户配置的中央访问点", + "集成和管理外部AI服务(Ollama)的生命周期" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "功能模块的门面API定义,提供统一接口供外部调用者访问核心功能。", + "file_path": "crates/feed_api_rs/src/features/api.rs", + "functions": [ + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "importance_score": 0.8, + "interfaces": [ + "FeaturesAPI" + ], + "name": "api.rs", + "source_summary": "use ollama::ProgramStatus;\nuse recorder::entity::article_record::Model;\nuse tauri::{AppHandle, Runtime};\nuse types::{AppConfig, ConversationMessage, FeedTargetDescription, FeedsPackage};\n\n/// 功能模块的门面API定义\npub trait FeaturesAPI {\n /// 用于添加订阅包,会同步到用户配置存储模块\n /// 如果订阅包已经存在,函数将返回一个错误\n fn add_feeds_package(\n &self,\n feeds_package: FeedsPackage,\n ) -> impl std::future::Future>;\n\n /// 用于删除订阅包,会同步到用户配置存储模块\n /// 如果订阅包不存在,函数将返回一个错误\n fn remove_feeds_package(\n &self,\n package_id: &str,\n ) -> impl std::future::Future>;\n\n /// 用于重命名订阅包,会同步到用户配置存储模块\n /// 如果订阅包不存在,函数将返回一个错误\n fn rename_feeds_package(\n &self,\n package_id: &str,\n new_name: &str,\n ) -> impl std::future::Future>;\n\n /// 用于添加订阅到订阅包,会同步到用户配置存储模块\n /// 如果订阅已经存在,函数将返回一个错误\n fn add_feed(\n &self,\n package_id: &str,\n ftd: FeedTargetDescription,\n ) -> impl std::future::Future>;\n\n /// 用于移除订阅包中的订阅,会同步到用户配置存储模块\n /// 如果订阅不存在,函数将返回一个错误\n fn remove_feed(\n &self,\n package_id: &str,\n feed_id: &str,\n ) -> impl std::future::Future>;\n\n /// 用于重命名订阅包中的订阅,会同步到用户配置存储模块\n /// 如果订阅不存在,函数将返回一个错误\n fn rename_feed(\n &self,\n package_id: &str,\n feed_id: &str,\n new_name: &str,\n ) -> impl std::future::Future>;\n fn change_feed_data(\n &self,\n package_id: &str,\n feed_id: &str,\n data: Vec,\n ) -> impl std::future::Future>;\n\n /// 获得所有的订阅包信息\n fn get_feeds_packages(&self) -> impl std::future::Future>;\n\n /// 获得制定订阅包中的订阅信息\n fn get_feeds_by_package(\n &self,\n package_id: &str,\n ) -> impl std::future::Future>;\n\n /// 更新订阅内容,将爬取数据源并做内容提取和总结、同步到数据存储模块。\n fn update_feed_contents(\n &self,\n package_id: &str,\n feed_id: &str,\n app_handle: Option>,\n ) -> impl std::future::Future>;\n\n fn read_feed_contents(\n &self,\n feed_id: &str,\n offset: u64,\n count: u64,\n ) -> impl std::future::Future>>;\n\n fn query_by_id(\n &self,\n id: i32,\n ) -> impl std::future::Future>>;\n fn mark_as_read(&self, id: i32) -> impl std::future::Future>;\n fn set_favorite(\n &self,\n id: i32,\n is_favorite: bool,\n ) -> impl std::future::Future>;\n\n /// 读取AppConfig\n fn get_app_config(&self) -> impl std::future::Future>;\n\n /// 覆盖存储AppConfig\n fn set_app_config(\n &self,\n app_config: AppConfig,\n ) -> impl std::future::Future>;\n\n fn get_ollama_status(&self)\n -> impl std::future::Future>;\n\n fn download_ollama(&self) -> impl std::future::Future>;\n\n fn launch_ollama(&self) -> impl std::future::Future>;\n\n fn open_article_external(\n &self,\n url: &str,\n ) -> impl std::future::Future>;\n\n fn update_article_by_source(\n &self,\n article_id: i32,\n source_text: String,\n ) -> impl std::future::Future>;\n\n fn chat_with_article_assistant(\n &self,\n article_id: i32,\n user_prompt: &str,\n history: Vec,\n ) -> impl std::future::Future>;\n\n fn search_contents_by_keyword(\n &self,\n keyword: &str,\n offset: u64,\n count: u64,\n ) -> impl std::future::Future>>;\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 4.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 136, + "number_of_classes": 1, + "number_of_functions": 22 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "ollama", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "recorder", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": null, + "name": "types", + "path": null, + "version": null + } + ], + "detailed_description": "该组件定义了系统中所有核心功能的统一接口契约(FeaturesAPI trait),作为系统的门面层对外暴露异步操作方法。涵盖了订阅管理、内容更新与读取、用户配置操作、本地AI模型(Ollama)控制、文章交互及搜索等完整业务流程。所有方法均返回impl Future,支持非阻塞异步调用,适配现代Rust应用架构。", + "interfaces": [ + { + "description": "功能模块的门面API定义,集中暴露系统核心能力。", + "interface_type": "trait", + "name": "FeaturesAPI", + "parameters": [], + "return_type": null, + "visibility": "pub" + } + ], + "responsibilities": [ + "提供统一的功能访问接口(门面模式)", + "管理用户订阅包和订阅项的增删改查", + "协调内容抓取、存储与用户阅读状态", + "封装对本地AI服务(Ollama)的控制逻辑", + "支持基于关键词的文章内容搜索与交互式问答" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "初始化用户配置文件,支持从本地TOML文件加载或创建默认配置", + "file_path": "crates/feed_api_rs/src/startup/init_user_profile.rs", + "functions": [ + "call", + "sync_to", + "default_user_profile" + ], + "importance_score": 0.8, + "interfaces": [ + "call", + "sync_to", + "default_user_profile" + ], + "name": "init_user_profile.rs", + "source_summary": "use tokio::{\n fs::File,\n io::{AsyncReadExt, AsyncWriteExt},\n};\n\nuse recorder::path::get_appdata_file;\nuse types::{FeedsPackage, FeedTargetDescription, UserConfig};\n\nuse super::task::{InitTask, TaskInitializer};\n\nconst FILE_NAME_USER_CONFIG: &str = \"user_config.toml\";\n\npub async fn call() -> anyhow::Result> {\n let mut task = InitTask::default();\n task.start(\"user_profile\", || async {\n let user_config_path = get_appdata_file(FILE_NAME_USER_CONFIG);\n Ok(match File::open(user_config_path).await {\n Ok(mut file) => {\n let mut data_raw = String::new();\n file.read_to_string(&mut data_raw).await?;\n toml::from_str(data_raw.as_str())?\n }\n Err(_) => {\n let user_profile = default_user_profile();\n sync_to(&user_profile).await?;\n user_profile\n }\n })\n })\n .await?;\n Ok(task)\n}\n\npub async fn sync_to(user_config: &UserConfig) -> anyhow::Result<()> {\n let user_config_path = get_appdata_file(FILE_NAME_USER_CONFIG);\n let mut file = File::create(user_config_path).await?;\n let data_raw = toml::to_string(user_config)?;\n file.write_all(data_raw.as_bytes()).await?;\n Ok(())\n}\n\nfn default_user_profile() -> UserConfig {\n UserConfig {\n feeds_packages: vec![FeedsPackage {\n name: \"未分类\".into(),\n feeds: vec![FeedTargetDescription {\n id: \"default_flat_on_root\".into(),\n fetcher_id: \"scrap\".into(),\n name: \"\".into(),\n data: vec![\"英伟达\".into(), \"投资\".into()],\n }],\n is_flat_on_root: true,\n id: \"\".into(),\n }],\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.5, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 56, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "async_runtime", + "is_external": true, + "line_number": 1, + "name": "tokio", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 6, + "name": "recorder::path::get_appdata_file", + "path": "recorder::path", + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 7, + "name": "types", + "path": "types", + "version": null + } + ], + "detailed_description": "该组件负责在应用启动时初始化用户个人资料。主要逻辑包括:尝试从指定路径读取user_config.toml配置文件,若文件不存在则生成默认用户配置并持久化到磁盘。提供异步加载和写入功能,确保非阻塞I/O操作。默认配置包含一个预设的订阅包,用于新用户引导体验。", + "interfaces": [ + { + "description": "启动用户配置初始化任务,返回可执行的异步任务", + "interface_type": "function", + "name": "call", + "parameters": [], + "return_type": "anyhow::Result>", + "visibility": "public" + }, + { + "description": "将给定的用户配置同步保存到磁盘文件", + "interface_type": "function", + "name": "sync_to", + "parameters": [ + { + "description": "要持久化的用户配置引用", + "is_optional": false, + "name": "user_config", + "param_type": "&UserConfig" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "生成系统默认的用户配置实例", + "interface_type": "function", + "name": "default_user_profile", + "parameters": [], + "return_type": "UserConfig", + "visibility": "private" + } + ], + "responsibilities": [ + "管理用户配置的生命周期初始化", + "实现用户配置的持久化存储与读取", + "提供默认用户配置的生成逻辑", + "协调异步文件I/O操作" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "初始化LLM提供者,根据配置启动相应的本地大模型服务。", + "file_path": "crates/feed_api_rs/src/startup/init_llm.rs", + "functions": [ + "call" + ], + "importance_score": 0.8, + "interfaces": [ + "call" + ], + "name": "init_llm.rs", + "source_summary": "use spdlog::error;\nuse ollama::{ProgramStatus, query_platform};\nuse types::{LLMProviderType, LLMSection};\n\nuse super::task::{InitTask, TaskInitializer};\n\npub async fn call(llm_section: &LLMSection) -> anyhow::Result<()> {\n match llm_section.active_provider_type {\n LLMProviderType::Ollama => {\n let mut task = InitTask::default();\n task.start(\"llm_provider_ollama\", || async {\n match query_platform(&llm_section.provider_ollama.endpoint).await {\n Ok(ollama_information) => {\n match ollama_information.status {\n // 在启动环节如果未安装Ollama不自动引导安装,只记录状态。\n ProgramStatus::Uninstall => {}\n // 在启动环节如果已安装Ollama但未运行则唤起Ollama。\n ProgramStatus::InstallButNotRunning => ollama::launch().await?,\n ProgramStatus::Running => {}\n };\n Ok(ollama_information.status)\n }\n Err(_) => {\n error!(\"The Ollama instance is unavailable.\");\n Ok(ProgramStatus::Uninstall)\n }\n }\n })\n .await?;\n Ok(())\n }\n _ => {\n let mut task = InitTask::default();\n task.start(\"llm_provider_others\", || async { Ok(()) }).await?;\n Ok(())\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.15, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 38, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "logging", + "is_external": true, + "line_number": 1, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "service_client", + "is_external": true, + "line_number": 2, + "name": "ollama", + "path": null, + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 3, + "name": "types", + "path": null, + "version": null + }, + { + "dependency_type": "framework", + "is_external": false, + "line_number": 5, + "name": "super::task::InitTask", + "path": "crates/feed_api_rs/src/startup/task.rs", + "version": null + } + ], + "detailed_description": "该组件负责在应用启动时初始化指定的大型语言模型(LLM)提供程序。当前主要支持Ollama作为后端运行时,通过查询其平台状态并采取相应措施:若未安装则记录信息;若已安装但未运行,则尝试唤醒服务;若正在运行则不做操作。对于非Ollama的其他提供者类型,执行空初始化任务以保持流程一致性。", + "interfaces": [ + { + "description": "异步初始化LLM提供者,依据配置激活对应的服务准备逻辑", + "interface_type": "function", + "name": "call", + "parameters": [ + { + "description": "包含LLM配置信息的引用", + "is_optional": false, + "name": "llm_section", + "param_type": "&LLMSection" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "pub" + } + ], + "responsibilities": [ + "检测并处理Ollama服务的运行状态", + "根据LLM配置决定是否需要唤醒本地模型服务", + "统一不同LLM提供者的初始化流程", + "集成到系统启动任务框架中,保证可扩展性和可观测性" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "初始化日志系统,根据配置决定日志输出方式(stdout或磁盘文件),并设置统一的日志格式。", + "file_path": "crates/feed_api_rs/src/startup/init_logger.rs", + "functions": [ + "call", + "init_by", + "specify_logger_format" + ], + "importance_score": 0.8, + "interfaces": [ + "call", + "init_by", + "specify_logger_format" + ], + "name": "init_logger.rs", + "source_summary": "use std::sync::Arc;\nuse std::time::Duration;\n\nuse spdlog::{\n Logger,\n prelude::*,\n sink::{RotatingFileSink, RotationPolicy},\n};\nuse spdlog::formatter::{pattern, PatternFormatter};\n\nuse recorder::path::get_appdata_file_in_dir;\nuse types::{AppConfig, AppConfigLogSection, OutputType};\n\npub fn call(app_config: &AppConfig) -> anyhow::Result<()> {\n let log_section = &app_config.log;\n init_by(log_section)\n}\n\npub fn init_by(log_section: &AppConfigLogSection) -> anyhow::Result<()> {\n if cfg!(debug_assertions) {\n specify_logger_format(&spdlog::default_logger());\n spdlog::default_logger().set_level_filter(LevelFilter::All);\n info!(\"auto turn log on because of debug_assertions is active\");\n return Ok(());\n }\n if !log_section.enable {\n spdlog::default_logger().set_level_filter(LevelFilter::Off);\n return Ok(());\n }\n match log_section.output_type {\n OutputType::Stdout => {\n specify_logger_format(&spdlog::default_logger());\n info!(\"the log was enabled and would be output to stdout\");\n Ok(())\n }\n OutputType::Disk => {\n let path = get_appdata_file_in_dir(\"logs\", format!(\"app{}.log\", log_section.log_name_tail));\n info!(\"the log was enabled in disk mode and would be recorded in {:?} with date-named mode\", path);\n let new_logger = spdlog::default_logger().fork_with(|new| {\n let file_sink = Arc::new(\n RotatingFileSink::builder()\n .base_path(path)\n .rotation_policy(RotationPolicy::Daily { hour: 0, minute: 0 })\n .build()?,\n );\n new.sinks_mut().push(file_sink);\n Ok(())\n })?;\n new_logger.set_flush_period(Some(Duration::from_secs(3)));\n spdlog::set_default_logger(new_logger);\n specify_logger_format(&spdlog::default_logger());\n info!(\"the log was enabled and would be recorded in the log file\");\n Ok(())\n }\n OutputType::UnSpecified => {\n specify_logger_format(&spdlog::default_logger());\n info!(\"the log was enabled and would be output to stdout\");\n Ok(())\n }\n }\n}\n\n/// 指定logger的format。\n///\n/// formatter格式定义见[源码](https://github.com/SpriteOvO/spdlog-rs/blob/aa10020e305352a77f302e6737ecf114548013bb/spdlog-internal/src/pattern_parser/mod.rs#L88)\nfn specify_logger_format(logger: &Arc) {\n let new_formatter = Box::new(PatternFormatter::new(pattern!(\n \"[{date} {time}.{millisecond}] [thread-{tid}] [{^{level}}] {payload}{eol}\"\n )));\n\n for sink in logger.sinks() {\n sink.set_formatter(new_formatter.clone())\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.88, + "coupling_factor": 0.65, + "cyclomatic_complexity": 5.0, + "depth_of_inheritance": 0, + "lines_of_code": 74, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "std", + "is_external": false, + "line_number": 1, + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "version": null + }, + { + "dependency_type": "std", + "is_external": false, + "line_number": 2, + "name": "std::time::Duration", + "path": "std::time::Duration", + "version": null + }, + { + "dependency_type": "third_party", + "is_external": true, + "line_number": 4, + "name": "spdlog", + "path": "spdlog", + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 9, + "name": "recorder::path::get_appdata_file_in_dir", + "path": "recorder::path::get_appdata_file_in_dir", + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 10, + "name": "types::AppConfig", + "path": "types::AppConfig", + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 10, + "name": "types::AppConfigLogSection", + "path": "types::AppConfigLogSection", + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 10, + "name": "types::OutputType", + "path": "types::OutputType", + "version": null + } + ], + "detailed_description": "该组件负责应用程序启动时的日志系统初始化。它读取应用配置中的日志部分(AppConfigLogSection),根据是否启用日志、输出类型(标准输出或磁盘)以及调试模式状态来动态配置全局日志行为。在磁盘模式下,使用按天轮转的策略将日志写入指定路径,并设置3秒的刷新周期以平衡性能与持久性。同时,为所有日志记录器统一设置包含时间、线程ID、日志级别和消息内容的可读格式。", + "interfaces": [ + { + "description": "入口函数,接收整体应用配置并调用实际初始化逻辑", + "interface_type": "function", + "name": "call", + "parameters": [ + { + "description": "应用完整配置,从中提取日志配置部分", + "is_optional": false, + "name": "app_config", + "param_type": "&AppConfig" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "核心初始化函数,根据日志配置执行具体的日志系统设置", + "interface_type": "function", + "name": "init_by", + "parameters": [ + { + "description": "日志模块的配置节", + "is_optional": false, + "name": "log_section", + "param_type": "&AppConfigLogSection" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "内部辅助函数,为指定日志器设置统一的输出格式", + "interface_type": "function", + "name": "specify_logger_format", + "parameters": [ + { + "description": "待格式化的日志记录器实例", + "is_optional": false, + "name": "logger", + "param_type": "&Arc" + } + ], + "return_type": null, + "visibility": "private" + } + ], + "responsibilities": [ + "解析日志配置并决定日志启用策略", + "根据输出类型初始化对应的目标sink(stdout或文件)", + "设置统一的日志格式以增强可读性和一致性", + "支持调试模式下的自动日志开启机制", + "管理日志刷新频率和文件轮转策略" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "定义了初始化任务的执行器和状态管理,用于异步启动并监控系统启动阶段的任务。", + "file_path": "crates/feed_api_rs/src/startup/task.rs", + "functions": [ + "start", + "dump" + ], + "importance_score": 0.8, + "interfaces": [ + "TaskInitializer", + "InitTask" + ], + "name": "task.rs", + "source_summary": "use std::future::Future;\n\nuse spdlog::{error, info};\nuse tokio::time::Instant;\n\nuse super::types::{Status, TaskDump};\n\npub trait TaskInitializer {\n fn start Fut, Fut: Future>>(\n &mut self,\n task_name: &str,\n function: F,\n ) -> impl Future>;\n\n fn dump(&self) -> TaskDump;\n}\n\npub struct InitTask {\n pub result: Option,\n pub task_cost: u128,\n pub task_status: Status,\n}\n\nimpl Default for InitTask {\n fn default() -> Self {\n InitTask {\n result: None,\n task_cost: 0,\n task_status: Status::UnLaunch,\n }\n }\n}\n\nimpl TaskInitializer, TData> for InitTask {\n async fn start Fut, Fut: Future>>(\n &mut self,\n task_name: &str,\n function: F,\n ) -> anyhow::Result<()> {\n let duration_elapse = Instant::now();\n self.task_status = Status::Running;\n match function().await {\n Ok(result) => {\n self.result = Some(result);\n self.task_status = Status::Completed;\n self.task_cost = duration_elapse.elapsed().as_millis();\n info!(\"the task {} execute completed, cost {}ms\", task_name, self.task_cost);\n Ok(())\n }\n Err(err) => {\n self.task_status = Status::Error;\n error!(\"the task {} execute error...{}\", task_name, err);\n Err(err)\n }\n }\n }\n\n fn dump(&self) -> super::types::TaskDump {\n TaskDump {\n status: self.task_status,\n duration: self.task_cost,\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.88, + "coupling_factor": 0.57, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 64, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "std", + "is_external": false, + "line_number": 1, + "name": "std::future::Future", + "path": "std::future::Future", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": 3, + "name": "spdlog", + "path": "spdlog", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": 4, + "name": "tokio::time::Instant", + "path": "tokio::time::Instant", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": 6, + "name": "anyhow::Result", + "path": "anyhow", + "version": null + } + ], + "detailed_description": "该组件实现了系统启动过程中关键任务的异步执行与状态追踪功能。通过 `TaskInitializer` trait 提供统一接口,允许对任意返回 `anyhow::Result` 的异步函数进行封装执行,并记录执行耗时、状态(运行中、完成、错误)以及结果数据。`InitTask` 结构体作为具体实现,具备默认初始化能力,支持在执行失败时记录错误日志,在成功时输出耗时信息,增强了可观测性。", + "interfaces": [ + { + "description": "定义任务初始化器的核心行为,包括启动任务和导出状态快照", + "interface_type": "trait", + "name": "TaskInitializer", + "parameters": [ + { + "description": "任务结果的包装类型", + "is_optional": false, + "name": "TResult", + "param_type": "generic" + }, + { + "description": "任务实际产出的数据类型", + "is_optional": false, + "name": "TData", + "param_type": "generic" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "异步执行传入的任务闭包,自动记录耗时和状态变化", + "interface_type": "method", + "name": "start", + "parameters": [ + { + "description": "任务名称,用于日志标记", + "is_optional": false, + "name": "task_name", + "param_type": "&str" + }, + { + "description": "返回 Future 的可调用对象", + "is_optional": false, + "name": "function", + "param_type": "F" + } + ], + "return_type": "impl Future>", + "visibility": "public" + }, + { + "description": "导出当前任务的状态摘要", + "interface_type": "method", + "name": "dump", + "parameters": [], + "return_type": "TaskDump", + "visibility": "public" + }, + { + "description": "具体任务执行容器,持有执行结果、耗时和状态", + "interface_type": "struct", + "name": "InitTask", + "parameters": [ + { + "description": "任务执行结果", + "is_optional": true, + "name": "result", + "param_type": "Option" + }, + { + "description": "任务执行耗时(毫秒)", + "is_optional": false, + "name": "task_cost", + "param_type": "u128" + }, + { + "description": "当前任务状态", + "is_optional": false, + "name": "task_status", + "param_type": "Status" + } + ], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "封装异步任务的执行流程,确保统一的启动逻辑", + "监控任务执行时间并记录性能指标", + "维护任务的生命周期状态(未启动、运行中、完成、出错)", + "提供任务状态转储接口以供外部查询", + "处理任务执行中的异常并进行日志记录" + ] + }, + { + "code_dossier": { + "code_purpose": "other", + "description": "应用启动模块,负责初始化核心组件并构建应用上下文。实现分阶段(Tiger0/1/2)的启动流程控制。", + "file_path": "crates/feed_api_rs/src/startup/mod.rs", + "functions": [ + "tiger0_1", + "tiger2", + "launch" + ], + "importance_score": 0.8, + "interfaces": [ + "Startup", + "ContextHost" + ], + "name": "mod.rs", + "source_summary": "use spdlog::{error, info};\n\nuse crate::application_context::{ApplicationContext, ContextHost};\n\npub mod init_app_config;\npub mod init_logger;\npub mod init_llm;\npub mod init_user_profile;\npub mod task;\nmod types;\n\npub struct Startup {\n context: ApplicationContext,\n}\n\nimpl Startup {\n pub async fn launch() -> anyhow::Result {\n let context = tiger0_1().await?;\n Ok(Startup::new(context))\n }\n}\n\nimpl ContextHost for Startup {\n fn new(context: ApplicationContext) -> Self {\n Startup { context }\n }\n\n fn get_context(&self) -> &ApplicationContext {\n &self.context\n }\n\n fn copy_context(&self) -> ApplicationContext {\n self.context.clone()\n }\n}\n\npub async fn tiger0_1() -> anyhow::Result {\n // 初始化Tiger0,即应用启动环节所必须且同步初始化的模块,如读取应用配置。\n // 获得应用配置\n let app_config = init_app_config::call().await?.result.unwrap();\n\n // 应用运行的初始化必要组件,如日志、监控等。\n init_logger::call(&app_config)?;\n info!(\"starting up...tiger0_1, application configuration and logger initialized\");\n\n // 初始化Tiger1,即应用启动环节必须但可并行初始化的模块,如用户配置、依赖服务。\n info!(\"starting up...tiger0_1, begin initialize user configuration and ollama program status\");\n let llm_section = &app_config.llm;\n let (r1, r2) = tokio::join!(\n // 初始化用户订阅数据\n init_user_profile::call(),\n // 初始化依赖服务\n init_llm::call(llm_section)\n );\n if r1.is_err() || r2.is_err() {\n error!(\"starting up...tiger0_1, error occurs...{:?}, {:?}\", r1.as_ref().err(), r2.as_ref().err());\n return Err(anyhow::Error::msg(\n format!(\"error in startup..., {:?}, {:?}\", r1.as_ref().err(), r2.as_ref().err())\n ));\n }\n\n info!(\"starting up...tiger0_1, end initialize\");\n Ok(ApplicationContext {\n app_config,\n user_config: r1?.result.unwrap(),\n })\n}\n\n// 初始化Tiger2为应用启动环节可延迟初始化的模块,不再这里运行。\npub async fn tiger2(_context: ApplicationContext) -> anyhow::Result {\n todo!();\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.88, + "coupling_factor": 0.45, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 72, + "number_of_classes": 1, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "logging", + "is_external": true, + "line_number": 1, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "crate::application_context", + "path": "crates/feed_api_rs/src/application_context", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 9, + "name": "types", + "path": "./crates/llm/src/providers/types.rs", + "version": null + } + ], + "detailed_description": "该组件是应用程序的启动中枢,采用分阶段策略进行初始化:Tiger0_1同步初始化关键配置和日志系统,随后并行初始化用户配置与LLM服务依赖。通过`tokio::join!`实现并发加载以提升启动效率,并具备错误聚合处理机制。支持延迟初始化(Tiger2预留接口),体现阶段性启动设计思想。实现了`ContextHost` trait以统一管理`ApplicationContext`的生命周期。", + "interfaces": [ + { + "description": "应用启动器主结构体,持有应用上下文实例", + "interface_type": "struct", + "name": "Startup", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "上下文宿主接口,定义了上下文获取与克隆的标准方法", + "interface_type": "trait", + "name": "ContextHost", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "异步启动入口点,执行初始化并返回启动器实例", + "interface_type": "function", + "name": "launch", + "parameters": [], + "return_type": "anyhow::Result", + "visibility": "pub" + }, + { + "description": "执行Tiger0/Tiger1阶段的初始化工作,包括配置、日志、用户数据和LLM服务", + "interface_type": "function", + "name": "tiger0_1", + "parameters": [], + "return_type": "anyhow::Result", + "visibility": "pub" + }, + { + "description": "预留的延迟初始化接口,用于Tiger2阶段的异步任务", + "interface_type": "function", + "name": "tiger2", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "_context", + "param_type": "ApplicationContext" + } + ], + "return_type": "anyhow::Result", + "visibility": "pub" + } + ], + "responsibilities": [ + "协调应用启动时的核心组件初始化顺序", + "实现Tiger0/Tiger1阶段的同步与并发初始化逻辑", + "构建并返回完整的应用上下文(ApplicationContext)", + "提供结构化的启动日志与错误报告机制", + "实现ContextHost接口以支持上下文传递" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "智能助手组件,负责基于LLM的对话处理和文章内容分析。", + "file_path": "crates/intelligent/src/article_processor/assistant.rs", + "functions": [ + "new", + "chat" + ], + "importance_score": 0.8, + "interfaces": [ + "Assistant" + ], + "name": "assistant.rs", + "source_summary": "use llm::llm_agent::CompletionAgent;\nuse llm::providers::types::AITargetOption;\nuse types::{ConversationMessage, LLMSection};\n\nconst SYSTEM_PROMPT: &str = include_str!(\"prompts/assistant_sys.prompt\");\nconst USER_PROMPT_COMMAND_PURGE: &str = include_str!(\"prompts/assistant_suffix.prompt\");\n\npub struct Assistant {\n agent: CompletionAgent,\n user_prompt_command: String,\n}\n\nimpl Assistant {\n pub fn new(llm_section: LLMSection) -> Assistant {\n let options = AITargetOption {\n temperature: Some(0.7),\n ..Default::default()\n };\n Assistant {\n agent: CompletionAgent::new(llm_section.clone(), SYSTEM_PROMPT.into(), options).unwrap(),\n user_prompt_command: USER_PROMPT_COMMAND_PURGE.into(),\n }\n }\n\n pub async fn chat(&self, article: String, user_prompt: &str, history: Vec) -> anyhow::Result {\n let conversation_description = history.iter().map(|message| {\n format!(\"{}说:{}\", message.role, message.payload)\n }).collect::>().join(\"\\n\");\n let mut chat = format!(\n \"### 文章正文:\\\n {} \\\n ### 用户会话历史记录\\\n {} \\\n ### 用户本次的提问 \\\n {} \\\n \",\n article, conversation_description, user_prompt\n );\n chat.push_str(self.user_prompt_command.as_str());\n let output = self.agent.completion(chat).await?;\n Ok(output)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.4, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 43, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": true, + "line_number": null, + "name": "llm::llm_agent::CompletionAgent", + "path": "llm::llm_agent::CompletionAgent", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": null, + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types::AITargetOption", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": null, + "name": "types::ConversationMessage", + "path": "types::ConversationMessage", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": null, + "name": "types::LLMSection", + "path": "types::LLMSection", + "version": null + } + ], + "detailed_description": "该组件实现了一个智能助手(Assistant),封装了与大型语言模型(LLM)交互的能力。它通过CompletionAgent与底层LLM服务通信,接收文章内容、用户提问和会话历史,构造结构化提示(prompt)并获取模型回复。系统提示(SYSTEM_PROMPT)和用户指令后缀(USER_PROMPT_COMMAND_PURGE)从外部文件加载,增强了可配置性。chat方法负责将输入数据格式化为模型可理解的上下文,并返回生成的响应。", + "interfaces": [ + { + "description": "智能助手的主要数据结构,包含LLM代理和用户提示命令。", + "interface_type": "struct", + "name": "Assistant", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "创建一个新的Assistant实例,初始化LLM代理和默认选项。", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": "指定使用的LLM配置区域", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "Assistant", + "visibility": "public" + }, + { + "description": "执行与LLM的对话交互,生成针对文章内容的回答。", + "interface_type": "function", + "name": "chat", + "parameters": [ + { + "description": "待分析的文章正文", + "is_optional": false, + "name": "article", + "param_type": "String" + }, + { + "description": "用户当前的提问内容", + "is_optional": false, + "name": "user_prompt", + "param_type": "&str" + }, + { + "description": "之前的会话消息历史", + "is_optional": false, + "name": "history", + "param_type": "Vec" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "管理LLM代理实例的生命周期", + "构造包含文章、会话历史和用户提问的完整对话上下文", + "调用LLM完成文本生成任务", + "封装与大型语言模型的交互逻辑" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "基于LLM的文章处理器,利用生成式AI模型对文章内容进行处理和转换。", + "file_path": "crates/intelligent/src/article_processor/llm_processor.rs", + "functions": [ + "new", + "process" + ], + "importance_score": 0.8, + "interfaces": [ + "IArticleProcessor", + "IPresetArticleLLMProcessor" + ], + "name": "llm_processor.rs", + "source_summary": "use llm::llm_agent::CompletionAgent;\nuse llm::providers::types::AITargetOption;\nuse types::{Article, LLMInstructOption, LLMSection};\n\nuse crate::article_processor::types::IArticleProcessor;\nuse sys_locale::get_locale;\n\n/// 基于LLM的文章处理器。\npub struct ArticleLLMProcessor {\n /// Agent化的生成式服务实例。\n agent: CompletionAgent,\n /// 用于与Agent交互的user prompt。\n user_prompt_command: String,\n}\n\n/// 预设文章处理器创建trait,所有文章预处理器都通过impl此trait创建[ArticleLLMProcessor][ArticleLLMProcessor]的实例以支持框架层面调度。\npub trait IPresetArticleLLMProcessor {\n fn new_processor(llm_section: LLMSection) -> anyhow::Result;\n}\n\nimpl IArticleProcessor for ArticleLLMProcessor {\n async fn process(&self, input: &Article, opt: LLMInstructOption) -> anyhow::Result
{\n let mut output = input.clone();\n let content = output.content.as_ref().unwrap();\n let lang = {\n if opt.lang.as_str() == \"system\" {\n get_locale().unwrap_or_else(|| String::from(\"en-US\"))\n } else {\n opt.lang.to_owned()\n }\n };\n\n let prompt_spec_lang = format!(\n \"## 语言要求:\\n请使用{}语种输出内容,如果原文中存在其他语言则同样翻译为这个语种,代码块、姓名、英文简写除外。\",\n lang\n );\n let chat = format!(\n r#\"## 原内容\\n\"{}\"\\n{}\\n{}\"#,\n content,\n self.user_prompt_command.as_str(),\n prompt_spec_lang\n );\n let content = self.agent.completion(chat).await?;\n output.content.replace(content);\n Ok(output)\n }\n}\n\nimpl ArticleLLMProcessor {\n pub fn new(\n llm_section: LLMSection,\n system_prompt: String,\n user_prompt_command: String,\n options: AITargetOption,\n ) -> anyhow::Result {\n Ok(ArticleLLMProcessor {\n agent: CompletionAgent::new(llm_section, system_prompt, options)?,\n user_prompt_command,\n })\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 7.0, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 61, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": false, + "line_number": 1, + "name": "llm::llm_agent::CompletionAgent", + "path": "llm::llm_agent::CompletionAgent", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types::AITargetOption", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 3, + "name": "types::Article", + "path": "types::Article", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 3, + "name": "types::LLMInstructOption", + "path": "types::LLMInstructOption", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 3, + "name": "types::LLMSection", + "path": "types::LLMSection", + "version": null + }, + { + "dependency_type": "trait", + "is_external": false, + "line_number": 5, + "name": "crate::article_processor::types::IArticleProcessor", + "path": "crate::article_processor::types::IArticleProcessor", + "version": null + }, + { + "dependency_type": "function", + "is_external": true, + "line_number": 6, + "name": "sys_locale::get_locale", + "path": "sys_locale::get_locale", + "version": null + } + ], + "detailed_description": "该组件是一个基于大型语言模型(LLM)的文章处理器,负责将输入的文章内容通过预设的系统提示和用户指令发送给LLM代理进行处理,并返回经过LLM生成或修改后的内容。它支持多语言处理,能够根据配置的语言选项自动适配输出语种。组件通过CompletionAgent与底层LLM服务交互,封装了prompt构造、语言处理逻辑以及结果注入等流程。", + "interfaces": [ + { + "description": "文章处理器统一接口,定义process方法用于处理文章。", + "interface_type": "trait", + "name": "IArticleProcessor", + "parameters": [], + "return_type": "anyhow::Result
", + "visibility": "public" + }, + { + "description": "预设LLM处理器创建trait,用于框架层面统一创建ArticleLLMProcessor实例。", + "interface_type": "trait", + "name": "IPresetArticleLLMProcessor", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "构造一个新的ArticleLLMProcessor实例,接受LLM配置、系统提示、用户命令和AI目标选项。", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + }, + { + "description": null, + "is_optional": false, + "name": "system_prompt", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "user_prompt_command", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "options", + "param_type": "AITargetOption" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "异步处理输入文章,调用LLM完成内容生成并返回新文章。", + "interface_type": "function", + "name": "process", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "input", + "param_type": "&Article" + }, + { + "description": null, + "is_optional": false, + "name": "opt", + "param_type": "LLMInstructOption" + } + ], + "return_type": "anyhow::Result
", + "visibility": "public" + } + ], + "responsibilities": [ + "作为LLM代理的前端接口,协调文章内容与AI模型之间的交互", + "构建符合要求的Prompt指令,包括原文、用户命令和语言规范", + "处理多语言需求,根据系统或指定语言设置输出语种", + "实现文章内容的异步生成式处理,保持输入结构不变仅替换内容", + "提供可扩展的构造接口以支持不同场景下的实例化" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现网页内容抓取与智能重定向处理的核心组件,支持基于LLM的页面跳转检测", + "file_path": "crates/scrap/src/article_reader.rs", + "functions": [ + "read", + "read_inner", + "acquire_html", + "read_inner_from_response" + ], + "importance_score": 0.8, + "interfaces": [ + "read", + "read_inner" + ], + "name": "article_reader.rs", + "source_summary": "use reqwest::redirect::Policy;\nuse scraper::{Html, Selector};\nuse spdlog::{error, info};\n\nuse llm::llm_agent::CompletionAgent;\nuse llm::providers::types::AITargetOption;\nuse types::LLMSection;\n\nuse crate::connector;\nuse crate::connector::ClientOption;\nuse crate::search::selector_extensions::ElementSelector;\nuse crate::search::utils::trim_html_with_script_and_style;\n\npub async fn read(\n url_str: &str,\n source_search_host: Option,\n llm_section: LLMSection,\n) -> anyhow::Result<(String, String)> {\n read_inner(url_str, true, source_search_host, llm_section).await\n}\n\nasync fn read_inner(\n url_str: &str,\n auto_redirect: bool,\n source_search_host: Option,\n llm_section: LLMSection,\n) -> anyhow::Result<(String, String)> {\n let url = reqwest::Url::parse(url_str)?;\n if let Some(host) = url.domain() {\n let (html_text, final_url) = acquire_html(url_str, auto_redirect, &source_search_host, &llm_section, host).await?;\n return read_inner_from_response(&final_url,\n auto_redirect,\n source_search_host,\n llm_section,\n html_text).await;\n }\n Err(anyhow::Error::msg(\"article.read_inner occurs error, selector parse error for body\"))\n}\n\nasync fn acquire_html(url_str: &str, auto_redirect: bool, source_search_host: &Option, llm_section: &LLMSection, host: &str) -> anyhow::Result<(String, String)> {\n info!(\"article.read,网页抓取中...{}\", url_str);\n let connector_builder = connector::new_builder(ClientOption {\n host: host.into(),\n user_agent: None,\n })?.redirect(Policy::none());\n let client = connector_builder.build()?;\n let response = client.get(url_str).send().await?;\n let response_status = response.status();\n if response_status.is_client_error() || response_status.is_server_error() {\n let err_msg = format!(\n \"article.read_inner failure, status code is {}\",\n response.status()\n );\n error!(\"{}, {}\", err_msg, url_str);\n return Err(anyhow::Error::msg(err_msg));\n }\n if response_status.is_redirection() {\n let redirect_location = response.headers().get(\"location\").unwrap().to_str()?;\n info!(\"detect the redirection from {} to {}\", url_str, redirect_location);\n let redirected_url = reqwest::Url::parse(redirect_location)?;\n let redirected_host = redirected_url.domain().unwrap();\n return Box::pin(acquire_html(redirect_location, auto_redirect, source_search_host, llm_section, redirected_host)).await;\n }\n Ok((response.text().await?, url_str.into()))\n}\n\nasync fn read_inner_from_response(url_str: &str, auto_redirect: bool, source_search_host: Option, llm_section: LLMSection, html_text: String) -> anyhow::Result<(String, String)> {\n let gs = CompletionAgent::new(llm_section.clone(), \"\".into(), AITargetOption::default())?;\n // 如果是auto_redirect进入校准模式。\n // 校准模式下\n // 如果搜索源为空则开始纠正。\n // 如果搜索源不为空则先判定是否来自搜索源,如果不来自搜索源则不修正,来自搜索源则修正。\n if auto_redirect {\n if let Some(source_search_host_str) = source_search_host {\n if url_str.contains(source_search_host_str.as_str()) {\n let mut chat = format!(r#\"\"{}\"\"#, html_text);\n chat.push_str(\"\\n上述代码中是否包括一个通过window.location.href重定向的新页面链接,如果有则只告诉我这个链接地址且不要携带其他说明信息,如果没有和我说“没有”且不要携带其他说明信息。\");\n let url_detected = gs.completion(chat).await?;\n let url_detected = url_detected.replace('`', \"\");\n if url_detected.starts_with(\"http\") {\n info!(\"article.read,网页抓取遇到重定向指示并尝试重定向到...{}, 原链接为{}\", url_detected, url_str);\n return Box::pin(read_inner(url_detected.as_str(), false, None, llm_section.clone())).await;\n }\n }\n }\n }\n\n return if let Ok(selector) = Selector::parse(\"body\") {\n let sharked_html = trim_html_with_script_and_style(html_text.as_str());\n let document = Html::parse_document(&sharked_html);\n let scraped_content = document.select_text(&selector)?;\n info!(\"article.read,成功抓取网页内容...{}, length = {}\", url_str, scraped_content.len());\n Ok((scraped_content, url_str.into()))\n } else {\n Err(anyhow::Error::msg(\"article.read_inner occurs error, selector parse error for body\"))\n };\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 10.0, + "cyclomatic_complexity": 11.0, + "depth_of_inheritance": 0, + "lines_of_code": 97, + "number_of_classes": 0, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "http_client", + "is_external": true, + "line_number": 1, + "name": "reqwest", + "path": null, + "version": null + }, + { + "dependency_type": "html_parser", + "is_external": true, + "line_number": 2, + "name": "scraper", + "path": null, + "version": null + }, + { + "dependency_type": "logging", + "is_external": true, + "line_number": 3, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "ai_service", + "is_external": false, + "line_number": 5, + "name": "llm::llm_agent::CompletionAgent", + "path": "crates/llm/src/llm_agent.rs", + "version": null + }, + { + "dependency_type": "ai_config", + "is_external": false, + "line_number": 6, + "name": "llm::providers::types::AITargetOption", + "path": "crates/llm/src/providers/types.rs", + "version": null + }, + { + "dependency_type": "config_struct", + "is_external": false, + "line_number": 7, + "name": "types::LLMSection", + "path": "crates/types/src/lib.rs", + "version": null + }, + { + "dependency_type": "network_connector", + "is_external": false, + "line_number": 9, + "name": "crate::connector", + "path": "crates/scrap/src/connector.rs", + "version": null + }, + { + "dependency_type": "config_struct", + "is_external": false, + "line_number": 10, + "name": "crate::connector::ClientOption", + "path": "crates/scrap/src/connector.rs", + "version": null + }, + { + "dependency_type": "extension_trait", + "is_external": false, + "line_number": 11, + "name": "crate::search::selector_extensions::ElementSelector", + "path": "crates/scrap/src/search/selector_extensions.rs", + "version": null + }, + { + "dependency_type": "utility_function", + "is_external": false, + "line_number": 12, + "name": "crate::search::utils::trim_html_with_script_and_style", + "path": "crates/scrap/src/search/utils.rs", + "version": null + } + ], + "detailed_description": "该组件负责从指定URL抓取网页内容,并通过HTML解析提取正文文本。其核心流程包括:1) 发起HTTP请求获取原始HTML;2) 处理重定向响应(状态码3xx);3) 利用scraper库选择body标签内容并去除脚本和样式;4) 在自动重定向模式下,使用LLM分析是否存在JavaScript跳转链接并递归抓取目标页面。特别地,当启用了auto_redirect且来源主机匹配时,会调用大模型服务判断是否存在window.location.href跳转,从而实现对前端重定向的智能化处理。", + "interfaces": [ + { + "description": "公共入口函数,启动网页读取流程", + "interface_type": "function", + "name": "read", + "parameters": [ + { + "description": "目标网页URL字符串引用", + "is_optional": false, + "name": "url_str", + "param_type": "&str" + }, + { + "description": "源搜索网站主机名,用于判定是否来自搜索引擎结果页", + "is_optional": true, + "name": "source_search_host", + "param_type": "Option" + }, + { + "description": "大语言模型配置节,用于初始化CompletionAgent", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result<(String, String)>", + "visibility": "public" + }, + { + "description": "内部实现函数,包含完整的抓取与重定向逻辑", + "interface_type": "function", + "name": "read_inner", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "url_str", + "param_type": "&str" + }, + { + "description": "是否启用智能重定向检测", + "is_optional": false, + "name": "auto_redirect", + "param_type": "bool" + }, + { + "description": null, + "is_optional": true, + "name": "source_search_host", + "param_type": "Option" + }, + { + "description": null, + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result<(String, String)>", + "visibility": "private" + } + ], + "responsibilities": [ + "发起HTTP请求并安全获取网页HTML内容", + "处理HTTP重定向及递归抓取最终页面", + "利用LLM智能识别前端JavaScript重定向链接", + "清洗HTML内容并提取纯文本正文", + "集成日志记录与错误处理机制" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "RSS 内容抓取器实现,用于从 RSS 源提取文章信息并调用内容读取服务获取正文。", + "file_path": "crates/scrap/src/rss/mod.rs", + "functions": [ + "fetch" + ], + "importance_score": 0.8, + "interfaces": [ + "IFetcher" + ], + "name": "mod.rs", + "source_summary": "use crate::types::IFetcher;\nuse rss::Channel;\nuse tauri::{AppHandle, Runtime};\nuse types::{Article, FeedTargetDescription, LLMSection};\nuse crate::article_reader;\n\n#[derive(Default)]\npub struct RSSFetcher {}\n\nimpl IFetcher for RSSFetcher {\n async fn fetch(\n &self,\n _app_handle: Option>,\n llm_section: &LLMSection,\n ftd: FeedTargetDescription,\n ) -> anyhow::Result> {\n let llm_section = llm_section.clone();\n match ftd.data.get(0) {\n Some(url) => {\n let content = reqwest::get(url).await?.bytes().await?;\n let channel = Channel::read_from(&content[..])?;\n\n let mut articles = vec![];\n\n for item in channel.items().iter() {\n let title = item.title().unwrap_or(\"\").to_string();\n let source_link = item.link().unwrap_or(\"\").to_string();\n let head_read = item.description().unwrap_or(\"\").to_string();\n\n match article_reader::read(\n &source_link,\n None,\n llm_section.clone(),\n ).await {\n Ok(c) => {\n articles.push(Article {\n title,\n source_link,\n head_read: Some(head_read),\n content: Some(c.0),\n date_created: \"\".to_string(),\n summary: None,\n date_read: None,\n });\n }\n Err(_) => {}\n };\n }\n Ok(articles)\n }\n None => Err(anyhow::Error::msg(\"bad rss feed, the url is missing\")),\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.67, + "cyclomatic_complexity": 5.0, + "depth_of_inheritance": 0, + "lines_of_code": 54, + "number_of_classes": 1, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "trait", + "is_external": false, + "line_number": 1, + "name": "crate::types::IFetcher", + "path": "crates/scrap/src/types/mod.rs", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 2, + "name": "rss::Channel", + "path": null, + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 3, + "name": "tauri::AppHandle", + "path": null, + "version": null + }, + { + "dependency_type": "trait", + "is_external": true, + "line_number": 3, + "name": "tauri::Runtime", + "path": null, + "version": null + }, + { + "dependency_type": "struct", + "is_external": false, + "line_number": 4, + "name": "types::Article", + "path": "crates/scrap/src/types/mod.rs", + "version": null + }, + { + "dependency_type": "struct", + "is_external": false, + "line_number": 4, + "name": "types::FeedTargetDescription", + "path": "crates/scrap/src/types/mod.rs", + "version": null + }, + { + "dependency_type": "struct", + "is_external": false, + "line_number": 4, + "name": "types::LLMSection", + "path": "crates/scrap/src/types/mod.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 5, + "name": "crate::article_reader", + "path": "crates/scrap/src/article_reader.rs", + "version": null + }, + { + "dependency_type": "library", + "is_external": true, + "line_number": null, + "name": "reqwest", + "path": null, + "version": null + }, + { + "dependency_type": "library", + "is_external": true, + "line_number": null, + "name": "anyhow", + "path": null, + "version": null + } + ], + "detailed_description": "该组件实现了 IFetcher trait,专门用于处理 RSS 源的抓取逻辑。它接收一个 FeedTargetDescription,从中提取 URL,使用 reqwest 发起 HTTP 请求获取 RSS XML 数据,并通过 rss crate 解析 Channel 结构。随后遍历其中的 item 条目,提取标题、链接和摘要信息,并调用 article_reader 模块异步读取每篇文章的完整正文内容。最终将这些信息组装成 Article 对象列表返回。整个过程在失败时会进行适当的错误处理,例如缺失 URL 或解析失败。", + "interfaces": [ + { + "description": "定义通用抓取器接口,RSSFetcher 提供其具体实现。", + "interface_type": "trait", + "name": "IFetcher", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "执行 RSS 抓取主流程,返回文章列表或错误", + "interface_type": "function", + "name": "fetch", + "parameters": [ + { + "description": "Tauri 应用句柄,当前未实际使用", + "is_optional": true, + "name": "_app_handle", + "param_type": "Option>" + }, + { + "description": "指定用于内容处理的 LLM 配置区域", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + }, + { + "description": "包含待抓取源数据(如 URL)的目标描述", + "is_optional": false, + "name": "ftd", + "param_type": "FeedTargetDescription" + } + ], + "return_type": "anyhow::Result>", + "visibility": "public" + } + ], + "responsibilities": [ + "解析 RSS feed 并提取基础文章元数据(标题、链接、摘要)", + "协调对远程文章页面的内容抓取与正文提取", + "实现 IFetcher 接口以支持统一的数据获取策略", + "处理 RSS 解析过程中的错误情况并提供有意义的错误反馈" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现Bing搜索引擎的网页抓取与内容解析功能,支持通过关键词搜索并提取文章摘要和正文内容。", + "file_path": "crates/scrap/src/search/bing.rs", + "functions": [ + "Provider::new", + "Provider::prepare_target_sources", + "Provider::convert", + "IProvider::search_by_words" + ], + "importance_score": 0.8, + "interfaces": [ + "IProvider" + ], + "name": "bing.rs", + "source_summary": "use reqwest::Client;\nuse scraper::{Html, Selector};\nuse spdlog::{debug, error, info};\nuse tauri::{AppHandle, Runtime};\nuse urlencoding::encode;\n\nuse types::{Article, LLMSection};\n\nuse crate::connector::ClientOption;\nuse crate::search::selector_extensions::ElementSelector;\nuse crate::search::types::IProvider;\nuse crate::search::utils::{trim_head_read_days_ago, trim_html_with_script_and_style};\nuse crate::simulator::scrap_text_by_url;\nuse crate::{article_reader as article, connector};\n\nconst SEARCH_HOST: &str = \"www.bing.com\";\n\npub struct Provider {\n client: Client,\n llm_section: LLMSection,\n selector_item_layout: Selector,\n selector_item_title: Selector,\n selector_item_head_read: Selector,\n selector_item_link: Selector,\n}\n\nimpl Provider {\n pub fn new(llm_section: LLMSection) -> anyhow::Result {\n let client = connector::new(ClientOption {\n host: String::from(SEARCH_HOST),\n user_agent: None,\n })?;\n Ok(Provider {\n client,\n llm_section,\n selector_item_layout: Selector::parse(\".b_algo\").unwrap(),\n selector_item_title: Selector::parse(\"h2\").unwrap(),\n selector_item_head_read: Selector::parse(\".b_caption\").unwrap(),\n selector_item_link: Selector::parse(\"h2 > a\").unwrap(),\n })\n }\n\n fn prepare_target_sources(&self, html_text: &str) -> anyhow::Result> {\n let sharked_html =\n trim_html_with_script_and_style(html_text);\n let _watcher = sharked_html.as_str();\n let document = Html::parse_document(sharked_html.as_str());\n\n let mut pending_result: Vec
= Vec::new();\n for element in document.select(&self.selector_item_layout) {\n let title = element.select_text(&self.selector_item_title)?;\n let head_read = trim_head_read_days_ago(\n element\n .select_text(&self.selector_item_head_read)\n .unwrap_or_default(),\n );\n if let Ok(source_link) = element.select_attr_text(&self.selector_item_link, \"href\") {\n pending_result.push(Article {\n title,\n head_read: Some(head_read),\n date_created: String::new(),\n source_link,\n summary: None,\n content: None,\n date_read: None,\n });\n } else {\n debug!(\"the tag a or the attribute href not found when execute bing::prepare_target_sources, title = {}, head_read = {}\", title, head_read);\n }\n }\n Ok(pending_result)\n }\n\n async fn convert(&self, html_text: String) -> anyhow::Result> {\n let mut result: Vec
= Vec::new();\n let pending_result = self.prepare_target_sources(&html_text)?;\n\n for pending_article in pending_result {\n let title = pending_article.title;\n let head_read = pending_article.head_read;\n let source_link = pending_article.source_link;\n match article::read(\n &source_link,\n Some(String::from(\"bing.com\")),\n self.llm_section.clone(),\n )\n .await\n {\n Ok(c) => {\n result.push(Article {\n title,\n head_read,\n date_created: String::new(),\n source_link: c.1,\n summary: None,\n content: Some(c.0),\n date_read: None,\n });\n }\n Err(e) => error!(\n \"read article failure...title = {}, source_link = {}, error = {}\",\n title, source_link, e\n ),\n };\n }\n Ok(result)\n }\n}\n\nimpl IProvider for Provider {\n async fn search_by_words(\n &self,\n words: Vec<&str>,\n app_handle: Option>,\n ) -> anyhow::Result> {\n info!(\"内容清单搜索中...{:?}\", words);\n let search_word = words\n .iter()\n .map(|word| encode(word).to_string())\n .collect::>()\n .join(\"+\")\n .to_string();\n let url = format!(\n r#\"https://www.bing.com/search?ensearch=1&q={}&filters=ex1:%22ez2%22&rdr=1\"#,\n search_word\n );\n let html_text = match app_handle {\n Some(ap) => scrap_text_by_url(ap, url.as_str()).await?,\n None => self.client.get(url).send().await?.text().await?,\n };\n info!(\"已获得搜索数据,清单解析中\");\n self.convert(html_text).await\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 12.0, + "cyclomatic_complexity": 7.0, + "depth_of_inheritance": 0, + "lines_of_code": 134, + "number_of_classes": 1, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "http_client", + "is_external": true, + "line_number": 1, + "name": "reqwest::Client", + "path": null, + "version": null + }, + { + "dependency_type": "html_parser", + "is_external": true, + "line_number": 2, + "name": "scraper", + "path": null, + "version": null + }, + { + "dependency_type": "logging", + "is_external": true, + "line_number": 3, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "framework", + "is_external": true, + "line_number": 4, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": true, + "line_number": 5, + "name": "urlencoding", + "path": null, + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 7, + "name": "types::Article", + "path": "types", + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 7, + "name": "types::LLMSection", + "path": "types", + "version": null + }, + { + "dependency_type": "config", + "is_external": false, + "line_number": 9, + "name": "crate::connector::ClientOption", + "path": "crate::connector", + "version": null + }, + { + "dependency_type": "extension", + "is_external": false, + "line_number": 10, + "name": "crate::search::selector_extensions::ElementSelector", + "path": "crate::search::selector_extensions", + "version": null + }, + { + "dependency_type": "interface", + "is_external": false, + "line_number": 11, + "name": "crate::search::types::IProvider", + "path": "crate::search::types", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 12, + "name": "crate::search::utils::trim_head_read_days_ago", + "path": "crate::search::utils", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 12, + "name": "crate::search::utils::trim_html_with_script_and_style", + "path": "crate::search::utils", + "version": null + }, + { + "dependency_type": "service", + "is_external": false, + "line_number": 13, + "name": "crate::simulator::scrap_text_by_url", + "path": "crate::simulator", + "version": null + }, + { + "dependency_type": "service", + "is_external": false, + "line_number": 14, + "name": "crate::article_reader", + "path": "crate::", + "version": null + }, + { + "dependency_type": "service", + "is_external": false, + "line_number": 15, + "name": "crate::connector", + "path": "crate::", + "version": null + } + ], + "detailed_description": "该组件实现了针对 Bing 搜索引擎的爬虫功能,主要职责是根据用户输入的关键词发起搜索请求,解析返回的 HTML 页面以提取搜索结果列表,并进一步抓取每个结果页面的正文内容。组件使用 reqwest 发起 HTTP 请求,scraper 进行 HTML 解析,结合自定义的选择器定位关键元素(如标题、链接、摘要等)。同时集成 LLMSection 实现内容智能处理,并通过 article_reader 模块异步读取目标网页全文。整个流程支持 Tauri 应用上下文调用或独立客户端模式。", + "interfaces": [ + { + "description": "定义通用搜索提供者的接口规范", + "interface_type": "trait", + "name": "IProvider", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "创建一个新的 Bing 搜索提供者实例", + "interface_type": "function", + "name": "Provider::new", + "parameters": [ + { + "description": "用于内容理解的 LLM 分区配置", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "从 HTML 中提取初步的文章元数据(标题、链接、摘要)", + "interface_type": "function", + "name": "Provider::prepare_target_sources", + "parameters": [ + { + "description": "原始的 Bing 搜索结果 HTML 文本", + "is_optional": false, + "name": "html_text", + "param_type": "&str" + } + ], + "return_type": "anyhow::Result>", + "visibility": "private" + }, + { + "description": "将搜索结果转换为包含完整内容的文章对象列表", + "interface_type": "function", + "name": "Provider::convert", + "parameters": [ + { + "description": "Bing 搜索结果页面的 HTML 内容", + "is_optional": false, + "name": "html_text", + "param_type": "String" + } + ], + "return_type": "anyhow::Result>", + "visibility": "private" + }, + { + "description": "执行关键词搜索并返回结构化文章列表", + "interface_type": "function", + "name": "IProvider::search_by_words", + "parameters": [ + { + "description": "待搜索的关键词列表", + "is_optional": false, + "name": "words", + "param_type": "Vec<&str>" + }, + { + "description": "Tauri 应用句柄,用于在应用环境中执行网络请求", + "is_optional": true, + "name": "app_handle", + "param_type": "Option>" + } + ], + "return_type": "anyhow::Result>", + "visibility": "public" + }, + { + "description": "HTTP 客户端实例,用于发送网络请求", + "interface_type": "field", + "name": "Provider::client", + "parameters": [], + "return_type": "reqwest::Client", + "visibility": "private" + } + ], + "responsibilities": [ + "封装 Bing 搜索接口并构造合规请求 URL", + "解析 Bing 搜索结果页的 HTML 结构,提取标题、链接和摘要信息", + "调用文章阅读器抓取目标网页的完整内容", + "将原始搜索结果转换为标准化的文章对象列表", + "提供统一的 IProvider 接口供上层模块调用" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "搜索功能的聚合模块,封装了多种搜索引擎提供商的统一接口。", + "file_path": "crates/scrap/src/search/mod.rs", + "functions": [ + "search_by_words", + "fetch" + ], + "importance_score": 0.8, + "interfaces": [ + "IProvider", + "IFetcher" + ], + "name": "mod.rs", + "source_summary": "use ::types::{Article, FeedTargetDescription, LLMSection};\nuse spdlog::info;\nuse tauri::{AppHandle, Runtime};\n\nuse crate::search::types::IProvider;\nuse crate::types::IFetcher;\n\npub mod baidu;\npub mod bing;\npub(crate) mod selector_extensions;\npub mod types;\npub mod utils;\n\npub enum ScrapProviderEnums {\n Baidu(baidu::Provider),\n Bing(bing::Provider),\n}\n\nimpl IProvider for ScrapProviderEnums {\n async fn search_by_words(\n &self,\n words: Vec<&str>,\n app_handle: Option>,\n ) -> anyhow::Result> {\n match self {\n ScrapProviderEnums::Baidu(p) => p.search_by_words(words, app_handle).await,\n ScrapProviderEnums::Bing(p) => p.search_by_words(words, app_handle).await,\n }\n }\n}\n\nimpl IFetcher for ScrapProviderEnums {\n async fn fetch(\n &self,\n app_handle: Option>,\n _llm_section: &LLMSection,\n ftd: FeedTargetDescription,\n ) -> anyhow::Result> {\n let words: Vec<&str> = ftd.data.iter().map(|x| x.as_str()).collect();\n info!(\"scraping, via the words...{:?}\", words);\n let articles = self.search_by_words(words, app_handle).await?;\n info!(\n \"found {} articles for the feed_id = {}, feed_name = {}\",\n articles.len(),\n ftd.id,\n ftd.name\n );\n Ok(articles)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.6, + "cyclomatic_complexity": 5.0, + "depth_of_inheritance": 0, + "lines_of_code": 50, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": false, + "line_number": 1, + "name": "::types", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 2, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 3, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 5, + "name": "crate::search::types::IProvider", + "path": "crates/scrap/src/search/types.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 6, + "name": "crate::types::IFetcher", + "path": "crates/scrap/src/types.rs", + "version": null + } + ], + "detailed_description": "该组件是搜索功能的核心聚合模块,通过枚举类型ScrapProviderEnums统一管理不同的搜索引擎实现(如百度、必应)。它实现了IProvider和IFetcher两个核心接口,提供了基于关键词搜索和内容抓取的功能。组件采用代理模式,将具体的搜索请求转发给内部封装的实际提供商实例,并记录关键日志信息用于调试和监控。", + "interfaces": [ + { + "description": "定义搜索引擎提供商的基本行为契约", + "interface_type": "trait", + "name": "IProvider", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "定义内容抓取器的标准接口", + "interface_type": "trait", + "name": "IFetcher", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "根据关键词执行搜索并返回文章列表", + "interface_type": "method", + "name": "search_by_words", + "parameters": [ + { + "description": "搜索关键词列表", + "is_optional": false, + "name": "words", + "param_type": "Vec<&str>" + }, + { + "description": "应用句柄,用于跨平台操作", + "is_optional": true, + "name": "app_handle", + "param_type": "Option>" + } + ], + "return_type": "anyhow::Result>", + "visibility": "public" + } + ], + "responsibilities": [ + "统一管理多种搜索引擎提供商的实例", + "提供标准化的搜索接口供上层调用", + "实现基于关键词的文章搜索功能", + "集成日志记录与监控能力", + "协调搜索结果的获取与返回" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "百度搜索引擎结果抓取与内容提取组件,支持关键词搜索、时间范围过滤和文章正文抽取", + "file_path": "crates/scrap/src/search/baidu.rs", + "functions": [ + "new", + "prepare_target_sources", + "convert", + "search_by_words", + "adjust_date_str" + ], + "importance_score": 0.8, + "interfaces": [ + "IProvider" + ], + "name": "baidu.rs", + "source_summary": "use chrono::{Datelike, Duration, Local, Utc};\nuse reqwest::Client;\nuse scraper::{Html, Selector};\nuse spdlog::{error, info};\n\nuse tauri::{AppHandle, Runtime};\nuse types::{Article, LLMSection};\n\nuse crate::connector::ClientOption;\nuse crate::search::types::IProvider;\nuse crate::search::utils::{trim_head_read_days_ago, trim_html_with_script_and_style};\nuse crate::simulator::scrap_text_by_url;\nuse crate::{article_reader as article, connector};\n\nconst SEARCH_HOST: &str = \"www.baidu.com\";\n\n///\n/// 目前仍存在的问题:\n/// 百度的link都是baidu的中间地址,访问时会做redirect,但reqwest在自动redirection时由于host自动沿用使用了baidu导致被目标网站反制。\n/// https://www.searchapi.io/docs/baidu\n/// wd--查询的关键词\n/// ie--查询输入文字的编码\n/// tn--提交搜索请求的来源站点。\n/// rn--搜索结果显示条数\npub struct Provider {\n client: Client,\n llm_section: LLMSection,\n selector_item_layout: Selector,\n selector_item_title: Selector,\n selector_item_head_read1: Selector,\n selector_item_head_read2: Selector,\n selector_item_date: Selector,\n selector_item_link: Selector,\n}\n\nimpl Provider {\n pub fn new(llm_section: LLMSection) -> anyhow::Result {\n let client = connector::new(ClientOption {\n host: String::from(SEARCH_HOST),\n user_agent: None,\n })\n .unwrap();\n Ok(Provider {\n client,\n llm_section,\n selector_item_layout: Selector::parse(\".result.c-container.xpath-log.new-pmd\").unwrap(),\n selector_item_title: Selector::parse(\".c-title\").unwrap(),\n selector_item_head_read1: Selector::parse(\".content-right_1THTn\").unwrap(),\n selector_item_head_read2: Selector::parse(\".content-right_2s-H4\").unwrap(),\n selector_item_date: Selector::parse(\".c-color-gray2\").unwrap(),\n selector_item_link: Selector::parse(\".c-title > a\").unwrap(),\n })\n }\n\n fn prepare_target_sources(&self, html_text: &str) -> anyhow::Result> {\n let mut pending_result: Vec
= Vec::new();\n let sharked_html = trim_html_with_script_and_style(html_text);\n let document = Html::parse_document(sharked_html.as_str());\n for element in document.select(&self.selector_item_layout) {\n let date_created_opt = match element.select(&self.selector_item_date).next() {\n None => None,\n Some(er) => {\n let lossy_date_str = er.text().collect::();\n Some(adjust_date_str(lossy_date_str))\n }\n };\n if date_created_opt.is_none() {\n continue;\n }\n\n let date_created = date_created_opt.unwrap();\n let title = element\n .select(&self.selector_item_title)\n .next()\n .unwrap()\n .text()\n .collect::();\n let mut head_read = String::new();\n\n {\n if let Some(head_read_block) = element.select(&self.selector_item_head_read1).next()\n {\n head_read = head_read_block.text().collect::();\n } else if let Some(head_read_block) =\n element.select(&self.selector_item_head_read2).next()\n {\n head_read = head_read_block.text().collect::();\n }\n head_read = trim_head_read_days_ago(head_read);\n }\n let a_html = element\n .select(&self.selector_item_link)\n .next()\n .unwrap()\n .html();\n let a_left_index = a_html.find(r#\"href=\"\"#).unwrap() + 6;\n let a_sub_string = &a_html[a_left_index..];\n let a_right_index = a_sub_string.find(r#\"\"\"#).unwrap();\n let source_link = a_sub_string[0..a_right_index].to_string();\n pending_result.push(Article {\n title,\n head_read: Some(head_read),\n date_created,\n source_link,\n summary: None,\n content: None,\n date_read: None,\n })\n }\n Ok(pending_result)\n }\n\n async fn convert(&self, html_text: String) -> anyhow::Result> {\n let mut result: Vec
= Vec::new();\n let pending_result = self.prepare_target_sources(&html_text)?;\n for pending_article in pending_result {\n let title = pending_article.title;\n let head_read = pending_article.head_read;\n let source_link = pending_article.source_link;\n if let Ok(c) = article::read(\n &source_link,\n Some(String::from(\"baidu.com\")),\n self.llm_section.clone(),\n )\n .await\n {\n result.push(Article {\n title,\n head_read,\n date_created: String::new(),\n source_link: c.1,\n summary: None,\n content: Some(c.0),\n date_read: None,\n })\n } else {\n error!(\n \"fetch article content failure, source_link = {}\",\n source_link\n );\n };\n }\n Ok(result)\n }\n}\n\nimpl IProvider for Provider {\n async fn search_by_words(\n &self,\n words: Vec<&str>,\n app_handle: Option>,\n ) -> anyhow::Result> {\n info!(\"内容清单搜索中...{:?}\", words);\n let search_word = words.join(\"%20\").to_string();\n let date_range_end = Utc::now().timestamp();\n let date_range_begin = Utc::now().timestamp() - 60 * 60 * 24 * 7;\n let url = format!(\"https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd={}&rn=20&gpc=stf%3D{}%2C{}%7Cstftype%3D1\", search_word, date_range_begin, date_range_end);\n let html_text = match app_handle {\n Some(ap) => scrap_text_by_url(ap, url.as_str()).await?,\n None => self.client.get(url).send().await?.text().await?,\n };\n info!(\"已获得搜索数据,清单解析中\");\n self.convert(html_text).await\n }\n}\n\nfn adjust_date_str(lossy_date_str: String) -> String {\n if !lossy_date_str.ends_with(\"天前\") {\n let sub_days: i64 = lossy_date_str[0..1].parse().unwrap();\n let now = Local::now().naive_local();\n let past = now.checked_sub_signed(Duration::days(sub_days)).unwrap();\n return past.format(\"%Y年%m月%d日\").to_string();\n }\n if !lossy_date_str.contains(\"年\") {\n let mut date = Local::now().year().to_string();\n date.push('年');\n date.push_str(lossy_date_str.as_str());\n return date;\n }\n lossy_date_str\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.61, + "cyclomatic_complexity": 12.0, + "depth_of_inheritance": 0, + "lines_of_code": 181, + "number_of_classes": 1, + "number_of_functions": 5 + }, + "dependencies": [ + { + "dependency_type": "external", + "is_external": true, + "line_number": 1, + "name": "chrono", + "path": null, + "version": null + }, + { + "dependency_type": "external", + "is_external": true, + "line_number": 2, + "name": "reqwest", + "path": null, + "version": null + }, + { + "dependency_type": "external", + "is_external": true, + "line_number": 3, + "name": "scraper", + "path": null, + "version": null + }, + { + "dependency_type": "external", + "is_external": true, + "line_number": 4, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "external", + "is_external": true, + "line_number": 6, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 7, + "name": "types", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 9, + "name": "crate::connector", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 10, + "name": "crate::search::types", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 11, + "name": "crate::search::utils", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 12, + "name": "crate::simulator::scrap_text_by_url", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 13, + "name": "crate::article_reader", + "path": null, + "version": null + } + ], + "detailed_description": "该组件实现了针对百度搜索结果页的爬虫功能,通过CSS选择器解析HTML结构提取文章标题、链接、发布时间等元信息,并进一步调用文章阅读器获取正文内容。支持按关键词搜索和最近7天的时间范围筛选,使用reqwest进行HTTP请求,scraper进行HTML解析,chrono处理日期转换。", + "interfaces": [ + { + "description": "搜索服务提供者接口,定义了通用的搜索方法契约", + "interface_type": "trait", + "name": "IProvider", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "创建百度搜索提供者实例", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": "语言模型分段配置", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "执行关键词搜索并返回文章列表", + "interface_type": "function", + "name": "search_by_words", + "parameters": [ + { + "description": "搜索关键词列表", + "is_optional": false, + "name": "words", + "param_type": "Vec<&str>" + }, + { + "description": "Tauri应用上下文句柄", + "is_optional": true, + "name": "app_handle", + "param_type": "Option>" + } + ], + "return_type": "anyhow::Result>", + "visibility": "public" + }, + { + "description": "从HTML中提取文章元数据", + "interface_type": "function", + "name": "prepare_target_sources", + "parameters": [ + { + "description": "原始HTML文本", + "is_optional": false, + "name": "html_text", + "param_type": "&str" + } + ], + "return_type": "anyhow::Result>", + "visibility": "private" + }, + { + "description": "转换搜索结果并获取文章内容", + "interface_type": "function", + "name": "convert", + "parameters": [ + { + "description": "HTML文本", + "is_optional": false, + "name": "html_text", + "param_type": "String" + } + ], + "return_type": "anyhow::Result>", + "visibility": "private" + }, + { + "description": "标准化日期字符串格式", + "interface_type": "function", + "name": "adjust_date_str", + "parameters": [ + { + "description": "原始日期字符串", + "is_optional": false, + "name": "lossy_date_str", + "param_type": "String" + } + ], + "return_type": "String", + "visibility": "private" + } + ], + "responsibilities": [ + "解析百度搜索结果页面的HTML结构并提取文章元数据", + "将相对模糊的发布日期(如'3天前')转换为标准日期格式", + "通过外部文章阅读器获取目标网页的正文内容", + "实现IProvider接口提供统一的搜索服务契约", + "管理HTTP客户端配置和请求参数构造" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "为scraper库的ElementRef和Html类型扩展便捷的选择器查询方法,支持文本和属性提取。", + "file_path": "crates/scrap/src/search/selector_extensions.rs", + "functions": [ + "select_text", + "select_attr_text" + ], + "importance_score": 0.8, + "interfaces": [ + "ElementSelector" + ], + "name": "selector_extensions.rs", + "source_summary": "use scraper::{ElementRef, Html, Selector};\n\npub trait ElementSelector<'a> {\n fn select_text(&self, selector: &Selector) -> anyhow::Result;\n\n fn select_attr_text(&self, selector: &Selector, attr: &str) -> anyhow::Result;\n}\n\nimpl<'a> ElementSelector<'a> for ElementRef<'a> {\n fn select_text(&self, selector: &Selector) -> anyhow::Result {\n match self\n .select(selector)\n .next() {\n None => Err(anyhow::Error::msg(\"ElementSelector::select_text for ElementRef occurs error, selector not found\")),\n Some(element_ref) => Ok(element_ref.text().collect::())\n }\n }\n\n fn select_attr_text(&self, selector: &Selector, attr: &str) -> anyhow::Result {\n match self\n .select(selector)\n .next() {\n None => Err(anyhow::Error::msg(\"ElementSelector::select_attr_text for ElementRef occurs error, selector not found\")),\n Some(element_ref) => {\n match element_ref.attr(attr) {\n None => Err(anyhow::Error::msg(format!(\"ElementSelector::select_attr_text for ElementRef occurs error, attr not found...{}\", attr))),\n Some(attr_str) => Ok(attr_str.into())\n }\n }\n }\n }\n}\n\nimpl<'a> ElementSelector<'a> for Html {\n fn select_text(&self, selector: &Selector) -> anyhow::Result {\n match self\n .select(selector)\n .next() {\n None => Err(anyhow::Error::msg(\"ElementSelector::select_text for Html occurs error, selector not found\")),\n Some(element_ref) => Ok(element_ref.text().collect::())\n }\n }\n\n fn select_attr_text(&self, selector: &Selector, attr: &str) -> anyhow::Result {\n match self\n .select(selector)\n .next() {\n None => Err(anyhow::Error::msg(\"ElementSelector::select_text for Html occurs error, selector not found\")),\n Some(element_ref) => {\n match element_ref.attr(attr) {\n None => Err(anyhow::Error::msg(format!(\"ElementSelector::select_text for Html occurs error, attr not found...{}\", attr))),\n Some(attr_str) => Ok(attr_str.into())\n }\n }\n }\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.25, + "cyclomatic_complexity": 15.0, + "depth_of_inheritance": 0, + "lines_of_code": 57, + "number_of_classes": 0, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "library", + "is_external": true, + "line_number": 1, + "name": "scraper", + "path": null, + "version": null + } + ], + "detailed_description": "该组件定义了一个名为ElementSelector的trait,并为scraper库中的ElementRef和Html类型实现了该trait。其主要功能是提供两个安全且带有错误提示的HTML选择器查询方法:select_text用于获取匹配元素的文本内容,select_attr_text用于获取匹配元素的指定属性值。两个实现均基于iterator的next()获取首个匹配项,若无匹配则返回语义化错误信息。代码使用anyhow进行错误处理,增强了调用链的可追溯性。", + "interfaces": [ + { + "description": "为HTML节点类型扩展选择器查询能力", + "interface_type": "trait", + "name": "ElementSelector", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "选择第一个匹配元素并返回其文本内容", + "interface_type": "method", + "name": "select_text", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "self", + "param_type": "&self" + }, + { + "description": "CSS选择器对象", + "is_optional": false, + "name": "selector", + "param_type": "&Selector" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "选择第一个匹配元素并返回其指定属性的文本值", + "interface_type": "method", + "name": "select_attr_text", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "self", + "param_type": "&self" + }, + { + "description": "CSS选择器对象", + "is_optional": false, + "name": "selector", + "param_type": "&Selector" + }, + { + "description": "要提取的HTML属性名", + "is_optional": false, + "name": "attr", + "param_type": "&str" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "为HTML元素查询操作提供统一的扩展接口", + "封装文本内容的安全提取逻辑", + "封装属性值的安全提取逻辑", + "提供清晰的错误反馈机制", + "增强scraper库API的易用性" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供用于文本和HTML内容清理的辅助函数,主要用于提取和标准化网页搜索结果中的信息。", + "file_path": "crates/scrap/src/search/utils.rs", + "functions": [ + "trim_head_read_days_ago", + "trim_html_with_script_and_style", + "trim_to" + ], + "importance_score": 0.8, + "interfaces": [ + "trim_head_read_days_ago", + "trim_html_with_script_and_style" + ], + "name": "utils.rs", + "source_summary": "use scraper::{Html, Selector};\n\npub fn trim_head_read_days_ago(head_read: String) -> String {\n let trimmed_head_read = trim_to(head_read, \"天之前\");\n let trimmed_head_read = trim_to(trimmed_head_read, \"天前\");\n let trimmed_head_read = trim_to(trimmed_head_read, \"days ago\");\n let trimmed_head_read = trim_to(trimmed_head_read, \"hours ago\");\n let trimmed_head_read = trim_to(trimmed_head_read, \"day ago\");\n let trimmed_head_read = trim_to(trimmed_head_read, \"hours ago\");\n trim_to(trimmed_head_read, \"days ago · \")\n}\n\npub fn trim_html_with_script_and_style(html_text: &str) -> String {\n let document = Html::parse_document(html_text);\n let root_selector = Selector::parse(\"body > *\").unwrap();\n\n let mut new_html_content = String::from(\"\");\n for element in document.select(&root_selector) {\n if !element.value().name().eq_ignore_ascii_case(\"script\")\n && !element.value().name().eq_ignore_ascii_case(\"style\")\n && !element.value().name().eq_ignore_ascii_case(\"meta\")\n && !element.value().name().eq_ignore_ascii_case(\"link\")\n && !element.value().name().eq_ignore_ascii_case(\"iframe\")\n && !element.value().name().eq_ignore_ascii_case(\"noscript\") {\n new_html_content.push_str(&element.html());\n }\n }\n new_html_content.push_str(\"\");\n\n new_html_content.into()\n}\n\nfn trim_to(text: String, redundant_prefix: &str) -> String {\n let offset = redundant_prefix.len();\n match text.find(redundant_prefix) {\n None => text,\n Some(index) => text.get(index + offset..).unwrap_or_else(|| panic!(\"text = {}, redundant_prefix = {}\", text, redundant_prefix)).to_string()\n }\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.5, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 39, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "library", + "is_external": true, + "line_number": 1, + "name": "scraper", + "path": null, + "version": null + } + ], + "detailed_description": "该组件包含三个函数,其中两个为公共接口。`trim_head_read_days_ago` 用于清理表示阅读时间的字符串,移除多种语言中表示相对时间的后缀(如“天之前”、“days ago”等),返回纯数字天数。`trim_html_with_script_and_style` 接收原始HTML文本,解析并过滤掉script、style、meta等非主体内容标签,保留body内主要可视元素,生成简化后的HTML结构。`trim_to` 是私有辅助函数,执行具体的子串截取逻辑,基于指定前缀进行删除。", + "interfaces": [ + { + "description": "移除多种语言的时间后缀,返回干净的天数文本", + "interface_type": "function", + "name": "trim_head_read_days_ago", + "parameters": [ + { + "description": "包含相对时间描述的输入字符串", + "is_optional": false, + "name": "head_read", + "param_type": "String" + } + ], + "return_type": "String", + "visibility": "public" + }, + { + "description": "解析HTML并移除脚本、样式等非主体标签,返回精简后的HTML", + "interface_type": "function", + "name": "trim_html_with_script_and_style", + "parameters": [ + { + "description": "原始HTML文档内容", + "is_optional": false, + "name": "html_text", + "param_type": "&str" + } + ], + "return_type": "String", + "visibility": "public" + } + ], + "responsibilities": [ + "清理和标准化时间相关的文本数据", + "从HTML中提取有意义的内容并去除干扰标签", + "提供可复用的字符串处理基础能力" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": null, + "file_path": "crates/scrap/src/simulator.rs", + "functions": [ + "scrap_text_by_url" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "simulator.rs", + "source_summary": "use once_cell::sync::Lazy;\nuse spdlog::error;\nuse std::sync::Arc;\nuse tauri::{\n async_runtime, AppHandle, Listener, Manager, Runtime, Url, WebviewUrl, WebviewWindowBuilder,\n};\nuse tokio::{\n sync::{oneshot, Mutex},\n time::{sleep, Duration},\n};\n\nconst WINDOW_SCRAP_HOST: &str = \"WINDOW_SCRAP_HOST\";\nstatic MUTEX: Lazy>> = Lazy::new(|| Arc::new(Mutex::new(())));\n\npub async fn scrap_text_by_url(\n app_handle: AppHandle,\n url: &str,\n) -> anyhow::Result {\n let _lock = MUTEX.lock().await;\n match app_handle.get_webview_window(WINDOW_SCRAP_HOST) {\n Some(_) => {\n error!(\"The scrap host for simulator was busy to use, scrap pages at the same time was not support currently!\");\n Err(anyhow::anyhow!(\"Scrap host is busy\"))\n }\n None => {\n let window = WebviewWindowBuilder::new(\n &app_handle,\n WINDOW_SCRAP_HOST,\n WebviewUrl::External(Url::parse(url)?),\n )\n .title(\"WINDOW_SCRAP_HOST\")\n .inner_size(1920.0, 1080.0)\n .visible(false)\n .build()?;\n\n let window_ref = Arc::new(window);\n let window_ref_disposer = Arc::clone(&window_ref);\n let (tx, rx) = oneshot::channel::();\n\n async_runtime::spawn(async move {\n sleep(Duration::from_secs(3)).await;\n window_ref\n .eval(r#\"var ecruos_oniq_value = document.documentElement.innerHTML;window.__TAURI__.event.emit(\"ecruos_oniq_tneve\", ecruos_oniq_value)\"#)\n .map_err(|e| error!(\"Failed to inspect: {}\", e))\n .ok();\n\n window_ref.once(\"ecruos_oniq_tneve\", move |event| {\n let payload = event.payload();\n let mut scraped_str = payload\n .chars()\n .skip(1)\n .take(payload.len() - 2)\n .collect::();\n scraped_str = scraped_str.replace(r#\"\\\"\"#, r#\"\"\"#);\n let _ = tx.send(scraped_str);\n });\n });\n\n let timeout_duration = Duration::from_secs(10);\n match tokio::time::timeout(timeout_duration, rx).await {\n Ok(r) => match r {\n Ok(result) => {\n window_ref_disposer\n .close()\n .expect(\"close scrap host panic!\");\n Ok(result)\n }\n Err(_) => {\n panic!(\"fatal error occurs, RecvError in simulator\");\n }\n },\n Err(_) => {\n window_ref_disposer\n .close()\n .expect(\"close scrap host panic!\");\n Err(anyhow::Error::msg(\"error occurs when execute simulator.scrap_text_by_url, nothing got when timeout.\"))\n }\n }\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 4.0, + "cyclomatic_complexity": 5.0, + "depth_of_inheritance": 0, + "lines_of_code": 81, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "once_cell", + "path": "once_cell::sync::Lazy", + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "spdlog", + "path": "spdlog::error", + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "tauri", + "path": "tauri::{async_runtime, AppHandle, Listener, Manager, Runtime, Url, WebviewUrl, WebviewWindowBuilder}", + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": null, + "name": "tokio", + "path": "tokio::{sync::{oneshot, Mutex}, time::{sleep, Duration}}", + "version": null + } + ], + "detailed_description": "该组件实现了一个基于Tauri框架的网页内容抓取模拟器,通过创建隐藏的Webview窗口加载指定URL,并在页面加载后执行JavaScript代码提取document.documentElement.innerHTML。使用异步通道接收事件响应结果,并支持超时控制和资源清理。核心机制利用了Tauri的eval与事件监听能力,在无头模式下完成DOM内容抓取。", + "interfaces": [], + "responsibilities": [ + "管理用于网页抓取的专用Webview窗口生命周期", + "执行远程页面内容提取并返回HTML源码", + "通过互斥锁确保同一时间仅运行一个抓取任务", + "处理页面加载超时及异常情况下的资源释放", + "与前端通过自定义事件通信获取执行结果" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供HTTP客户端构建工具,用于创建带有默认请求头和配置的reqwest Client实例。", + "file_path": "crates/scrap/src/connector.rs", + "functions": [ + "new_builder", + "new" + ], + "importance_score": 0.8, + "interfaces": [ + "ClientOption" + ], + "name": "connector.rs", + "source_summary": "use std::time::Duration;\n\nuse reqwest::{Client, ClientBuilder, header};\n\npub struct ClientOption {\n pub user_agent: Option,\n pub host: String,\n}\n\nconst DEFAULT_USER_AGENT: &str = \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0\";\nconst DEFAULT_ACCEPT: &str = \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\";\nconst DEFAULT_ACCEPT_ENCODING: &str = \"gzip, deflate\";\n\nconst DEFAULT_ACCEPT_LANGUAGE: &str = \"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7\";\nconst DEFAULT_CACHE_CONTROL: &str = \"no-cache\";\nconst DEFAULT_CONNECTION: &str = \"keep-alive\";\n\npub(crate) fn new_builder(option: ClientOption) -> anyhow::Result {\n Ok(\n Client::builder()\n .cookie_store(true)\n .timeout(Duration::from_secs(20))\n .gzip(true)\n .deflate(true)\n .default_headers({\n let mut headers = header::HeaderMap::new();\n headers.insert(header::USER_AGENT, option.user_agent.unwrap_or(DEFAULT_USER_AGENT.to_string()).parse()?);\n headers.insert(header::ACCEPT, DEFAULT_ACCEPT.to_string().parse()?);\n headers.insert(header::ACCEPT_ENCODING, DEFAULT_ACCEPT_ENCODING.to_string().parse()?);\n headers.insert(header::ACCEPT_LANGUAGE, DEFAULT_ACCEPT_LANGUAGE.to_string().parse()?);\n headers.insert(header::CACHE_CONTROL, DEFAULT_CACHE_CONTROL.to_string().parse()?);\n headers.insert(header::CONNECTION, DEFAULT_CONNECTION.to_string().parse()?);\n headers.insert(header::HOST, option.host.parse()?);\n headers.insert(header::DNT, \"1\".parse()?);\n headers\n })\n )\n}\n\npub(crate) fn new(option: ClientOption) -> anyhow::Result {\n let builder = new_builder(option)?;\n Ok(builder.build().unwrap())\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.0465, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 43, + "number_of_classes": 1, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "library", + "is_external": true, + "line_number": 3, + "name": "reqwest", + "path": null, + "version": null + }, + { + "dependency_type": "library", + "is_external": true, + "line_number": null, + "name": "anyhow", + "path": null, + "version": null + } + ], + "detailed_description": "该组件封装了HTTP客户端(reqwest::Client)的初始化逻辑,通过提供统一的默认请求头(如User-Agent、Accept、Encoding等)和基础配置(超时、Cookie存储、压缩支持),简化了网络请求客户端的创建过程。它接收一个包含主机地址和可选用户代理的配置结构体ClientOption,并据此构建出预设行为的ClientBuilder或直接生成Client实例。此设计有助于在爬虫或数据抓取场景中模拟真实浏览器行为,提高请求成功率。", + "interfaces": [ + { + "description": "客户端配置选项,用于指导ClientBuilder的构建过程", + "interface_type": "struct", + "name": "ClientOption", + "parameters": [ + { + "description": "自定义User-Agent字符串,若未提供则使用默认值", + "is_optional": true, + "name": "user_agent", + "param_type": "Option" + }, + { + "description": "目标请求主机名,用于设置Host请求头", + "is_optional": false, + "name": "host", + "param_type": "String" + } + ], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "封装HTTP客户端的创建逻辑", + "设置标准化的请求头以模拟浏览器行为", + "管理客户端基础配置(超时、压缩、Cookie等)", + "提供灵活但安全的客户端构建接口" + ] + }, + { + "code_dossier": { + "code_purpose": "database", + "description": "负责管理与SQLite数据库的连接,并提供对文章记录(entity::article_record)的CRUD操作封装。支持条件查询、分页、计数、存在性检查等核心数据访问功能。", + "file_path": "crates/recorder/src/operator.rs", + "functions": [ + "new", + "ensure_db_initialized", + "create_table_if_not_existed", + "initialize", + "count", + "dispose", + "insert", + "update", + "query", + "query_by_filters", + "exists", + "query_without_filter", + "query_by_id", + "delete" + ], + "importance_score": 0.8, + "interfaces": [ + "Operator" + ], + "name": "operator.rs", + "source_summary": "use std::time::Duration;\n\nuse sea_orm::{ActiveModelTrait, ConnectionTrait, ConnectOptions, Database, DatabaseConnection, DbBackend, DeleteResult, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, Schema};\nuse sea_orm::sea_query::IntoCondition;\n\nuse crate::entity::article_record;\nuse crate::entity::article_record::Column;\nuse crate::path::get_appdata_articles;\n\npub struct Operator {\n db: Option,\n}\n\nimpl Operator {\n pub fn new() -> Operator {\n Operator { db: None }\n }\n\n fn ensure_db_initialized(&self) -> &DatabaseConnection {\n match &self.db {\n None => panic!(\"database connection not initialized\"),\n Some(db_inst) => db_inst,\n }\n }\n\n pub async fn create_table_if_not_existed(&self) -> anyhow::Result<()> {\n let db = self.ensure_db_initialized();\n if article_record::Entity::find().count(db).await.is_ok() {\n return Ok(());\n }\n let db_sqlite = DbBackend::Sqlite;\n let schema = Schema::new(db_sqlite);\n let statement_create =\n db_sqlite.build(&schema.create_table_from_entity(article_record::Entity));\n db.execute(statement_create).await?;\n Ok(())\n }\n\n pub async fn initialize(&mut self) -> anyhow::Result<()> {\n let mut opt = ConnectOptions::new(format!(\n \"sqlite://{}?mode=rwc\",\n get_appdata_articles().to_str().expect(\"获取Recorder数据库文件路径失败\")\n ));\n opt.max_connections(10)\n .min_connections(2)\n .connect_timeout(Duration::from_secs(10))\n .acquire_timeout(Duration::from_secs(10))\n .idle_timeout(Duration::from_secs(16))\n .max_lifetime(Duration::from_secs(16))\n .sqlx_logging(true)\n .sqlx_logging_level(log::LevelFilter::Info);\n\n self.db = Some(Database::connect(opt).await?);\n self.create_table_if_not_existed().await?;\n Ok(())\n }\n\n pub async fn count(&self) -> anyhow::Result {\n let db = self.ensure_db_initialized();\n let count = article_record::Entity::find().count(db).await?;\n Ok(count)\n }\n\n pub async fn dispose(&mut self) -> anyhow::Result<()> {\n let disposing_db = self.db.take();\n match disposing_db {\n Some(db) => {\n db.close().await?;\n Ok(())\n }\n None => Ok(()),\n }\n }\n\n pub async fn insert(&self, entity: article_record::ActiveModel) -> anyhow::Result<()> {\n entity.insert(self.ensure_db_initialized()).await?;\n Ok(())\n }\n\n pub async fn update(\n &self,\n entity: article_record::ActiveModel,\n ) -> anyhow::Result {\n Ok(entity.update(self.ensure_db_initialized()).await?)\n }\n\n pub async fn query(\n &self,\n offset: Option,\n limit: Option,\n filter: F,\n ) -> anyhow::Result>\n where\n F: IntoCondition,\n {\n Ok(article_record::Entity::find()\n .filter(filter)\n .order_by_desc(Column::PublishedAt)\n .order_by_desc(Column::Id)\n .offset(offset)\n .limit(limit)\n .all(self.ensure_db_initialized())\n .await?)\n }\n\n pub async fn query_by_filters(\n &self,\n offset: Option,\n limit: Option,\n filters: Vec,\n ) -> anyhow::Result>\n where\n F: IntoCondition,\n {\n let mut finder = article_record::Entity::find();\n for filter in filters.into_iter() {\n finder = finder.filter(filter);\n }\n Ok(finder\n .order_by_desc(Column::PublishedAt)\n .order_by_desc(Column::Id)\n .offset(offset)\n .limit(limit)\n .all(self.ensure_db_initialized())\n .await?)\n }\n\n pub async fn exists(&self, filter: F) -> anyhow::Result\n where F: IntoCondition {\n let count = article_record::Entity::find().filter(filter).count(self.ensure_db_initialized()).await?;\n Ok(count > 0)\n }\n\n pub async fn query_without_filter(\n &self,\n offset: Option,\n limit: Option,\n ) -> anyhow::Result> {\n Ok(article_record::Entity::find()\n .offset(offset)\n .limit(limit)\n .order_by_desc(Column::PublishedAt)\n .order_by_desc(Column::Id)\n .all(self.ensure_db_initialized())\n .await?)\n }\n\n pub async fn query_by_id(&self, id: i32) -> anyhow::Result> {\n Ok(article_record::Entity::find_by_id(id)\n .one(self.ensure_db_initialized())\n .await?)\n }\n\n pub async fn delete(\n &self,\n entity: article_record::ActiveModel,\n ) -> anyhow::Result {\n Ok(entity.delete(self.ensure_db_initialized()).await?)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.6, + "cyclomatic_complexity": 5.0, + "depth_of_inheritance": 0, + "lines_of_code": 160, + "number_of_classes": 1, + "number_of_functions": 14 + }, + "dependencies": [ + { + "dependency_type": "std", + "is_external": false, + "line_number": null, + "name": "std::time::Duration", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "sea_orm", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "anyhow", + "path": null, + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "log", + "path": null, + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "article_record", + "path": "crates/recorder/src/entity/article_record.rs", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "get_appdata_articles", + "path": "crates/recorder/src/path.rs", + "version": null + } + ], + "detailed_description": "该组件是Recorder模块中用于持久化文章记录的核心数据库操作器。它封装了SeaORM框架对`article_record`实体的访问逻辑,通过内部持有可选的DatabaseConnection实例实现连接管理。组件在初始化时建立到SQLite数据库的连接池,并确保`t_article_record`表的存在。其主要行为包括:插入新文章记录、更新已有记录、根据ID或复杂过滤条件查询记录(支持分页和排序)、判断记录是否存在、删除记录以及获取总数量。所有操作均以异步方式执行,符合Rust异步编程模型。组件设计为单例模式使用,需先调用initialize完成初始化后方可执行其他操作。", + "interfaces": [ + { + "description": "数据库操作器主结构体,封装数据库连接与操作方法", + "interface_type": "struct", + "name": "Operator", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "创建一个新的Operator实例,初始状态无数据库连接", + "interface_type": "function", + "name": "new", + "parameters": [], + "return_type": "Operator", + "visibility": "public" + }, + { + "description": "异步初始化数据库连接并创建必要数据表", + "interface_type": "function", + "name": "initialize", + "parameters": [], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "异步释放数据库连接资源", + "interface_type": "function", + "name": "dispose", + "parameters": [], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "插入一条新的文章记录", + "interface_type": "function", + "name": "insert", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "entity", + "param_type": "article_record::ActiveModel" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "更新一条已有文章记录并返回更新后的模型", + "interface_type": "function", + "name": "update", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "entity", + "param_type": "article_record::ActiveModel" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "根据过滤条件分页查询文章记录,按发布时间和ID降序排列", + "interface_type": "function", + "name": "query", + "parameters": [ + { + "description": null, + "is_optional": true, + "name": "offset", + "param_type": "Option" + }, + { + "description": null, + "is_optional": true, + "name": "limit", + "param_type": "Option" + }, + { + "description": "实现了IntoCondition trait的过滤条件", + "is_optional": false, + "name": "filter", + "param_type": "F" + } + ], + "return_type": "anyhow::Result>", + "visibility": "public" + }, + { + "description": "获取文章记录总数", + "interface_type": "function", + "name": "count", + "parameters": [], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "检查满足特定条件的文章记录是否存在", + "interface_type": "function", + "name": "exists", + "parameters": [ + { + "description": "实现了IntoCondition trait的过滤条件", + "is_optional": false, + "name": "filter", + "param_type": "F" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "根据ID精确查询单条文章记录", + "interface_type": "function", + "name": "query_by_id", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "id", + "param_type": "i32" + } + ], + "return_type": "anyhow::Result>", + "visibility": "public" + }, + { + "description": "删除指定的文章记录", + "interface_type": "function", + "name": "delete", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "entity", + "param_type": "article_record::ActiveModel" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "管理数据库连接生命周期(初始化、关闭)", + "确保数据表结构存在", + "提供对文章记录的增删改查操作接口", + "支持基于条件和分页的数据查询", + "保证数据操作的安全性和事务一致性" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "文章记录服务,负责对文章记录进行增删改查、状态管理及搜索等业务操作。", + "file_path": "crates/recorder/src/article_recorder_service.rs", + "functions": [ + "initialize", + "update_content", + "insert", + "exists_by_source", + "query_backward", + "query_favorite", + "query_unread", + "query_backward_in_duration", + "count", + "mark_as_read", + "set_favorite", + "query_by_id", + "dispose", + "search_contents_by_keyword" + ], + "importance_score": 0.8, + "interfaces": [ + "ArticleRecorderService" + ], + "name": "article_recorder_service.rs", + "source_summary": "use chrono::NaiveDate;\nuse sea_orm::{ColumnTrait, Condition, IntoActiveModel};\nuse sea_orm::ActiveValue::Set;\nuse sea_orm::prelude::Expr;\n\nuse crate::entity::article_record;\nuse crate::entity::article_record::Model;\nuse crate::operator::Operator;\n\npub struct ArticleRecorderService {\n operator: Operator,\n}\n\nimpl Default for ArticleRecorderService {\n fn default() -> Self {\n let operator = Operator::new();\n ArticleRecorderService { operator }\n }\n}\n\nimpl ArticleRecorderService {\n pub async fn initialize(&mut self) -> anyhow::Result<()> {\n self.operator.initialize().await\n }\n\n pub async fn update_content(&self, record: Model, purged_content: String, optimized_content: String, melted_content: String) -> anyhow::Result {\n let operator = &self.operator;\n let mut active_model = record.into_active_model();\n active_model.purged_content = Set(purged_content);\n active_model.optimized_content = Set(optimized_content);\n active_model.melted_content = Set(melted_content);\n operator.update(active_model).await\n }\n\n pub async fn insert(&self, records: Vec) -> anyhow::Result {\n // 剔除掉已有的且未读过的,插入掉其他情况的。\n let mut inserted_num = 0;\n let operator = &self.operator;\n for record in records {\n let duplicates: Vec = operator\n .query(\n None,\n None,\n article_record::Column::SourceLink.eq(&record.source_link),\n )\n .await?;\n let mut has_existed_unread = false;\n for duplicate in duplicates {\n if duplicate.has_read {\n operator.delete(duplicate.into_active_model()).await?;\n } else {\n has_existed_unread = true;\n }\n }\n if !has_existed_unread {\n let mut active_model = record.into_active_model();\n active_model.id = Default::default();\n operator.insert(active_model).await?;\n inserted_num += 1;\n }\n }\n Ok(inserted_num)\n }\n\n pub async fn exists_by_source(&self, source_link: &String) -> anyhow::Result {\n let operator = &self.operator;\n operator.exists(article_record::Column::SourceLink.eq(source_link)).await\n }\n\n pub async fn query_backward(&self, group_id: Option<&str>, offset: u64, max_count: u64) -> anyhow::Result> {\n let operator = &self.operator;\n match group_id {\n None => operator\n .query_without_filter(Some(offset), Some(max_count))\n .await,\n Some(group_id) => operator\n .query(Some(offset), Some(max_count), article_record::Column::GroupId.eq(group_id))\n .await\n }\n }\n\n pub async fn query_favorite(&self, offset: u64, max_count: u64) -> anyhow::Result> {\n let operator = &self.operator;\n operator\n .query(Some(offset), Some(max_count), article_record::Column::IsFavorite.eq(true))\n .await\n }\n\n pub async fn query_unread(&self, offset: u64, max_count: u64) -> anyhow::Result> {\n let operator = &self.operator;\n let filters = vec![article_record::Column::HasRead.eq(false)];\n operator\n .query_by_filters(Some(offset), Some(max_count), filters)\n .await\n }\n\n pub async fn query_backward_in_duration(&self, offset: u64, max_count: u64, begin: NaiveDate, end: NaiveDate) -> anyhow::Result> {\n let operator = &self.operator;\n operator\n .query(Some(offset), Some(max_count), article_record::Column::PublishedAt.between(begin, end))\n .await\n }\n\n pub async fn count(&self) -> anyhow::Result {\n let operator = &self.operator;\n operator.count().await\n }\n\n pub async fn mark_as_read(&self, id: i32) -> anyhow::Result> {\n let operator = &self.operator;\n let record = operator.query_by_id(id).await?;\n match record {\n None => Ok(None),\n Some(record) => {\n let mut active_model = record.into_active_model();\n active_model.has_read = Set(true);\n let updated_record = operator.update(active_model).await?;\n Ok(Some(updated_record))\n }\n }\n }\n\n pub async fn set_favorite(&self, id: i32, is_favorite: bool) -> anyhow::Result> {\n let operator = &self.operator;\n let record = operator.query_by_id(id).await?;\n match record {\n None => Ok(None),\n Some(record) => {\n let mut active_model = record.into_active_model();\n active_model.is_favorite = Set(is_favorite);\n let updated_record = operator.update(active_model).await?;\n Ok(Some(updated_record))\n }\n }\n }\n\n pub async fn query_by_id(&self, id: i32) -> anyhow::Result> {\n self.operator.query_by_id(id).await\n }\n\n pub async fn dispose(&mut self) -> anyhow::Result<()> {\n self.operator.dispose().await\n }\n\n pub async fn search_contents_by_keyword(&self, keyword: &str, offset: u64, max_count: u64) -> anyhow::Result> {\n let operator = &self.operator;\n let keyword = format!(\"%{}%\", keyword.to_lowercase());\n operator\n .query(Some(offset), Some(max_count),\n Condition::any()\n .add(Expr::cust_with_values(\"LOWER(title) LIKE?\", vec![keyword.clone()]))\n .add(Expr::cust_with_values(\"LOWER(head_read) LIKE?\", vec![keyword.clone()]))\n .add(Expr::cust_with_values(\"LOWER(melted_content) LIKE?\", vec![keyword.clone()])),\n )\n .await\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.4667, + "cyclomatic_complexity": 9.0, + "depth_of_inheritance": 0, + "lines_of_code": 157, + "number_of_classes": 1, + "number_of_functions": 18 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": true, + "line_number": 1, + "name": "chrono::NaiveDate", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 2, + "name": "sea_orm::ColumnTrait", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 2, + "name": "sea_orm::Condition", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 2, + "name": "sea_orm::IntoActiveModel", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 3, + "name": "sea_orm::ActiveValue::Set", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": true, + "line_number": 4, + "name": "sea_orm::prelude::Expr", + "path": null, + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 6, + "name": "crate::entity::article_record", + "path": "./crates/recorder/src/entity/article_record.rs", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 7, + "name": "crate::operator::Operator", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是文章记录的核心服务层实现,封装了对文章记录(Model)的各类数据访问逻辑。它通过依赖 Operator 操作底层数据库,实现了初始化、插入、更新、查询(按分组、收藏、未读、时间范围等)、标记已读、设置收藏、关键词搜索等功能。其主要职责集中在文章记录的生命周期管理与状态变更控制,是连接上层业务逻辑与底层数据存储的关键中介。", + "interfaces": [ + { + "description": "文章记录服务的主要结构体,包含Operator用于执行数据库操作。", + "interface_type": "struct", + "name": "ArticleRecorderService", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "初始化服务及其依赖的Operator。", + "interface_type": "function", + "name": "initialize", + "parameters": [], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "更新指定记录的三种内容字段。", + "interface_type": "function", + "name": "update_content", + "parameters": [ + { + "description": "需要更新的文章记录", + "is_optional": false, + "name": "record", + "param_type": "Model" + }, + { + "description": "清洗后的内容", + "is_optional": false, + "name": "purged_content", + "param_type": "String" + }, + { + "description": "优化后的内容", + "is_optional": false, + "name": "optimized_content", + "param_type": "String" + }, + { + "description": "融合后的内容", + "is_optional": false, + "name": "melted_content", + "param_type": "String" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "批量插入文章记录,自动处理重复链接:删除已读的重复项,跳过未读的重复项。", + "interface_type": "function", + "name": "insert", + "parameters": [ + { + "description": "待插入的文章记录列表", + "is_optional": false, + "name": "records", + "param_type": "Vec" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "管理文章记录的持久化操作(增删改查)", + "维护文章记录的状态(已读/未读、收藏)", + "提供多维度的文章查询接口(按时间、收藏、未读、关键词等)", + "确保数据一致性(如插入时去重逻辑)" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供对应用数据目录和数据库文件路径的管理功能,确保所需目录存在并返回正确的路径。", + "file_path": "crates/recorder/src/path.rs", + "functions": [ + "get_appdata_articles", + "get_appdata_file", + "get_appdata_file_in_dir", + "ensure_app_data_prepared", + "ensure_dir_in_appdata_prepared", + "ensure_dir_prepared" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "path.rs", + "source_summary": "use std::fs;\nuse std::path::{Path, PathBuf};\n\nconst FOLDER_NAME_APP_DATA: &str = \"qino_feed.app_data\";\nconst FILE_NAME_DB_RECORD: &str = \"article_recorder.db\";\n\n/// 获取Recorder数据库文件路径\npub fn get_appdata_articles() -> PathBuf {\n ensure_app_data_prepared().join(FILE_NAME_DB_RECORD)\n}\n\n/// 获取App Data下指定文件的路径\npub fn get_appdata_file>(file_name: P) -> PathBuf {\n ensure_app_data_prepared().join(file_name)\n}\n\n/// 获取App Data下指定文件夹下的指定文件的路径\npub fn get_appdata_file_in_dir>(sub_dir_name: &str, file_name: P) -> PathBuf {\n ensure_dir_in_appdata_prepared(sub_dir_name).join(file_name)\n}\n\n/// 确保appdata下的应用文件夹内的子文件夹存在,如果不存在会自动创建指定路径的文件夹\nfn ensure_dir_in_appdata_prepared(sub_dir_name: &str) -> PathBuf {\n let app_data_dir = dirs::data_local_dir()\n .unwrap()\n .join(FOLDER_NAME_APP_DATA)\n .join(sub_dir_name);\n ensure_dir_prepared(app_data_dir)\n}\n\n/// 确保appdata下的应用文件夹存在,如果不存在会自动创建指定路径的文件夹\nfn ensure_app_data_prepared() -> PathBuf {\n let app_data_dir = dirs::data_local_dir().unwrap().join(FOLDER_NAME_APP_DATA);\n ensure_dir_prepared(app_data_dir)\n}\n\n/// 确保给定的路径文件夹存在,如果不存在会自动创建指定路径的文件夹\nfn ensure_dir_prepared(dir_path: PathBuf) -> PathBuf {\n let dir_path_meta = fs::metadata(&dir_path);\n if dir_path_meta.is_ok() && dir_path_meta.unwrap().is_dir() {\n return dir_path;\n }\n fs::create_dir(&dir_path).unwrap();\n dir_path\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.33, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 45, + "number_of_classes": 0, + "number_of_functions": 6 + }, + "dependencies": [ + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 1, + "name": "std::fs", + "path": "std::fs", + "version": null + }, + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 2, + "name": "std::path", + "path": "std::path", + "version": null + }, + { + "dependency_type": "external_crate", + "is_external": true, + "line_number": null, + "name": "dirs", + "path": "dirs", + "version": null + } + ], + "detailed_description": "该组件主要用于管理和生成应用程序的数据存储路径。它封装了对本地文件系统中特定目录(如用户本地数据目录下的 qino_feed.app_data)的操作,确保目标目录结构在访问前已正确创建。主要功能包括获取主数据库文件路径、构建子文件或子目录的完整路径,并自动创建缺失的目录结构。所有路径操作基于 `std::path::PathBuf` 并结合 `dirs` crate 获取标准系统路径,适用于跨平台场景。", + "interfaces": [ + { + "description": "获取文章记录器数据库文件的完整路径", + "interface_type": "function", + "name": "get_appdata_articles", + "parameters": [], + "return_type": "PathBuf", + "visibility": "pub" + }, + { + "description": "获取App Data下指定文件的完整路径", + "interface_type": "function", + "name": "get_appdata_file", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "file_name", + "param_type": "P: AsRef" + } + ], + "return_type": "PathBuf", + "visibility": "pub" + }, + { + "description": "获取App Data下指定子目录中某个文件的完整路径", + "interface_type": "function", + "name": "get_appdata_file_in_dir", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "sub_dir_name", + "param_type": "&str" + }, + { + "description": null, + "is_optional": false, + "name": "file_name", + "param_type": "P: AsRef" + } + ], + "return_type": "PathBuf", + "visibility": "pub" + }, + { + "description": "确保给定路径的目录存在,若不存在则创建", + "interface_type": "function", + "name": "ensure_dir_prepared", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "dir_path", + "param_type": "PathBuf" + } + ], + "return_type": "PathBuf", + "visibility": "private" + } + ], + "responsibilities": [ + "管理应用专属数据目录的路径生成", + "确保应用所需的数据目录结构存在(不存在则自动创建)", + "提供类型安全且可复用的路径构造接口", + "封装底层文件系统操作细节,降低调用方复杂度" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "提供基于Tauri框架的网页内容抓取功能,通过创建隐藏Webview窗口加载指定URL并提取页面HTML内容。", + "file_path": "crates/tauri-plugin-feed-api/src/scrap_host.rs", + "functions": [ + "scrap_text_by_url" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "scrap_host.rs", + "source_summary": "use std::sync::Arc;\n\nuse spdlog::error;\nuse tauri::{\n async_runtime, AppHandle, Listener, Manager, Runtime, Url, WebviewUrl, WebviewWindow,\n WebviewWindowBuilder,\n};\nuse tokio::sync::oneshot;\n\nconst WINDOW_SCRAP_HOST: &str = \"WINDOW_SCRAP_HOST\";\n\npub(crate) async fn scrap_text_by_url(\n app_handle: AppHandle,\n url: &str,\n) -> Result {\n match app_handle.get_webview_window(WINDOW_SCRAP_HOST) {\n Some(_) => {\n error!(\"The scrap host was busy to use, scrap pages at the same time was not support currently!\");\n Err(())\n }\n None => {\n let window = WebviewWindowBuilder::new(\n &app_handle,\n WINDOW_SCRAP_HOST,\n WebviewUrl::External(Url::parse(url).unwrap()),\n )\n .title(\"WINDOW_SCRAP_HOST\")\n .inner_size(1920.0, 1080.0)\n .visible(false)\n .build()\n .unwrap();\n\n let window_ref = Arc::new(window);\n let window_ref_disposer = Arc::clone(&window_ref);\n let (tx, rx) = oneshot::channel::();\n\n async_runtime::spawn(async move {\n tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;\n window_ref\n .eval(r#\"var ecruos_oniq_value = document.documentElement.innerHTML;window.__TAURI__.event.emit(\"ecruos_oniq_tneve\", ecruos_oniq_value)\"#)\n .unwrap();\n\n window_ref.once(\"ecruos_oniq_tneve\", move |event| {\n let scraped_str = event.payload();\n let _ = tx.send(scraped_str.to_owned());\n });\n });\n let result = rx.await.unwrap();\n window_ref_disposer\n .close()\n .expect(\"close scrap host panic!\");\n Ok(result)\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 4.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 55, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 1, + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "version": null + }, + { + "dependency_type": "logging", + "is_external": true, + "line_number": 3, + "name": "spdlog::error", + "path": "spdlog::error", + "version": null + }, + { + "dependency_type": "framework", + "is_external": true, + "line_number": 5, + "name": "tauri", + "path": "tauri", + "version": null + }, + { + "dependency_type": "async_channel", + "is_external": true, + "line_number": 7, + "name": "tokio::sync::oneshot", + "path": "tokio::sync::oneshot", + "version": null + } + ], + "detailed_description": "该组件实现了异步网页内容抓取功能。其核心逻辑是:接收一个URL地址,在Tauri应用中创建一个不可见的Webview窗口加载该页面;等待3秒确保页面渲染完成;通过执行JavaScript脚本读取document.documentElement.innerHTML;使用Tauri事件系统将结果回传,并通过channel发送出去;最后关闭临时窗口并返回抓取结果。若已有抓取任务正在进行,则拒绝新请求以避免并发冲突。", + "interfaces": [ + { + "description": "异步抓取指定URL页面的完整HTML内容", + "interface_type": "function", + "name": "scrap_text_by_url", + "parameters": [ + { + "description": "Tauri应用句柄,用于管理Webview窗口", + "is_optional": false, + "name": "app_handle", + "param_type": "AppHandle" + }, + { + "description": "待抓取的网页URL字符串引用", + "is_optional": false, + "name": "url", + "param_type": "&str" + } + ], + "return_type": "Result", + "visibility": "pub(crate)" + } + ], + "responsibilities": [ + "管理用于网页抓取的专用Webview窗口生命周期", + "防止并发抓取操作,保证单实例运行", + "执行JavaScript代码从远程页面提取HTML内容", + "通过异步通道返回抓取结果", + "处理Webview窗口的创建、通信与资源释放" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "Tauri插件入口,定义并注册所有与feed功能相关的前端可调用命令。通过依赖注入管理应用状态,并初始化底层业务逻辑组件。", + "file_path": "crates/tauri-plugin-feed-api/src/lib.rs", + "functions": [ + "init" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "lib.rs", + "source_summary": "use std::sync::Arc;\n\nuse tauri::{\n generate_handler,\n plugin::{Builder, TauriPlugin},\n Manager, RunEvent,\n};\n\nuse feed_api_rs::application_context::ContextHost;\nuse feed_api_rs::features::impl_default::FeaturesAPIImpl;\nuse feed_api_rs::startup::Startup;\n\nuse crate::commands::{\n add_feed, add_feeds_package, change_feed_data, chat_with_article_assistant, download_ollama,\n get_app_config, get_feeds_by_package, get_feeds_packages, get_ollama_status, launch_ollama,\n mark_as_read, open_article_external, query_by_id, read_feed_contents, remove_feed,\n remove_feeds_package, rename_feed, rename_feeds_package, scrap_text_by_url,\n search_contents_by_keyword, set_app_config, set_favorite, update_article_by_source,\n update_feed_contents,\n};\nuse crate::state::HybridRuntimeState;\n\nmod commands;\nmod scrap_host;\npub mod state;\n\npub fn init() -> TauriPlugin\nwhere\n R: tauri::Runtime,\n{\n Builder::new(\"feed-api\")\n .invoke_handler(generate_handler![\n add_feeds_package,\n remove_feeds_package,\n rename_feeds_package,\n add_feed,\n remove_feed,\n rename_feed,\n change_feed_data,\n get_feeds_packages,\n get_feeds_by_package,\n update_feed_contents,\n read_feed_contents,\n query_by_id,\n mark_as_read,\n set_favorite,\n get_app_config,\n set_app_config,\n get_ollama_status,\n download_ollama,\n launch_ollama,\n open_article_external,\n scrap_text_by_url,\n update_article_by_source,\n chat_with_article_assistant,\n search_contents_by_keyword\n ])\n .setup(|app_handle, _plugin| {\n let features_api = tauri::async_runtime::block_on(async {\n let context_host = Startup::launch().await.unwrap();\n let context = context_host.copy_context();\n FeaturesAPIImpl::new(context)\n .await\n .expect(\"tauri-plugin-feed-api setup the features instance failure\")\n });\n\n app_handle.manage(Arc::new(HybridRuntimeState { features_api }));\n Ok(())\n })\n .on_event(|app, event| match event {\n #[cfg(target_os = \"macos\")]\n RunEvent::Reopen {\n has_visible_windows,\n ..\n } => {\n if *has_visible_windows {\n return;\n }\n if let Some(window) = app.get_window(\"main\") {\n window.show().unwrap();\n }\n }\n _ => {}\n })\n .build()\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 0.82, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 86, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "std_lib", + "is_external": false, + "line_number": 1, + "name": "std::sync::Arc", + "path": null, + "version": null + }, + { + "dependency_type": "external_crate", + "is_external": true, + "line_number": 3, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "internal_crate", + "is_external": false, + "line_number": 7, + "name": "feed_api_rs::application_context::ContextHost", + "path": "crates/feed-api-rs", + "version": null + }, + { + "dependency_type": "internal_crate", + "is_external": false, + "line_number": 8, + "name": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "path": "crates/feed-api-rs", + "version": null + }, + { + "dependency_type": "internal_crate", + "is_external": false, + "line_number": 9, + "name": "feed_api_rs::startup::Startup", + "path": "crates/feed-api-rs", + "version": null + }, + { + "dependency_type": "internal_module", + "is_external": false, + "line_number": 11, + "name": "crate::commands", + "path": "./crates/tauri-plugin-feed-api/src/commands.rs", + "version": null + }, + { + "dependency_type": "internal_module", + "is_external": false, + "line_number": 15, + "name": "crate::state::HybridRuntimeState", + "path": "./crates/tauri-plugin-feed-api/src/state.rs", + "version": null + } + ], + "detailed_description": "该组件是Tauri框架下的一个原生插件(`tauri-plugin-feed-api`)的核心入口文件。其主要职责是将位于`commands`模块中的异步Rust函数暴露给前端JavaScript环境,使其能够安全地调用本地系统能力。组件通过`tauri::plugin::Builder`构建插件实例,使用`generate_handler!`宏批量注册了24个由`#[tauri::command]`标记的函数。这些函数覆盖了从RSS源管理(增删改查)、文章内容获取、AI模型(Ollama)交互到全文搜索等完整的feed应用核心功能。在初始化阶段(`setup`),它异步启动了一个`Startup`流程来创建全局共享的`FeaturesAPIImpl`业务逻辑实例,并将其包裹在`Arc>`中通过`app_handle.manage()`进行状态管理,确保了跨命令调用的数据一致性和线程安全。此外,还包含了一个针对macOS的`on_event`监听器,用于处理应用重新打开事件时窗口的显示逻辑。", + "interfaces": [ + { + "description": "插件的初始化函数,返回一个构建好的Tauri插件实例。", + "interface_type": "function", + "name": "init", + "parameters": [], + "return_type": "TauriPlugin", + "visibility": "public" + } + ], + "responsibilities": [ + "作为Tauri插件的初始化入口,协调整个插件的生命周期", + "集中注册和暴露所有后端功能命令(Commands)供前端调用", + "管理插件级共享状态(HybridRuntimeState),实现依赖注入", + "处理特定于平台的应用程序事件(如macOS的Reopen事件)" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "Tauri命令处理模块,封装了所有前端可调用的异步API接口,用于管理订阅源包、文章内容读取、AI交互等功能。", + "file_path": "crates/tauri-plugin-feed-api/src/commands.rs", + "functions": [ + "add_feeds_package", + "remove_feeds_package", + "rename_feeds_package", + "add_feed", + "remove_feed", + "rename_feed", + "change_feed_data", + "get_feeds_packages", + "get_feeds_by_package", + "update_feed_contents", + "read_feed_contents", + "query_by_id", + "mark_as_read", + "set_favorite", + "get_app_config", + "set_app_config", + "get_ollama_status", + "download_ollama", + "launch_ollama", + "open_article_external", + "scrap_text_by_url", + "update_article_by_source", + "chat_with_article_assistant", + "search_contents_by_keyword" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "commands.rs", + "source_summary": "use std::sync::Arc;\n\nuse spdlog::error;\nuse tauri::{AppHandle, Manager, Runtime, State};\n\nuse feed_api_rs::features::api::FeaturesAPI;\nuse ollama::ProgramStatus;\nuse recorder::entity::article_record::Model;\nuse types::{AppConfig, ConversationMessage, FeedTargetDescription, FeedsPackage};\n\nuse crate::scrap_host;\nuse crate::state::HybridRuntimeState;\n\n// #[tauri::command(rename_all = \"snake_case\")]\n// async fn template(state: State<'_, Mutex>) -> Result<(), ()> {\n// let features_api = &mut state.lock().await.features_api;\n// todo!()\n// }\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn add_feeds_package(\n state: State<'_, Arc>,\n feeds_package: FeedsPackage,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.add_feeds_package(feeds_package).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn remove_feeds_package(\n state: State<'_, Arc>,\n package_id: &str,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.remove_feeds_package(package_id).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn rename_feeds_package(\n state: State<'_, Arc>,\n package_id: &str,\n new_name: &str,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .rename_feeds_package(package_id, new_name)\n .await,\n )\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn add_feed(\n state: State<'_, Arc>,\n package_id: &str,\n ftd: FeedTargetDescription,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.add_feed(package_id, ftd).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn remove_feed(\n state: State<'_, Arc>,\n package_id: &str,\n feed_id: &str,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.remove_feed(package_id, feed_id).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn rename_feed(\n state: State<'_, Arc>,\n package_id: &str,\n feed_id: &str,\n new_name: &str,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .rename_feed(package_id, feed_id, new_name)\n .await,\n )\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn change_feed_data(\n state: State<'_, Arc>,\n package_id: &str,\n feed_id: &str,\n data: Vec,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .change_feed_data(package_id, feed_id, data)\n .await,\n )\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn get_feeds_packages(\n state: State<'_, Arc>,\n) -> Result, ()> {\n let features_api = &state.features_api;\n Ok(features_api.get_feeds_packages().await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn get_feeds_by_package(\n state: State<'_, Arc>,\n package_id: &str,\n) -> Result, ()> {\n let features_api = &state.features_api;\n Ok(features_api.get_feeds_by_package(package_id).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn update_feed_contents(\n app_handle: AppHandle,\n state: State<'_, Arc>,\n package_id: &str,\n feed_id: &str,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .update_feed_contents(package_id, feed_id, Some(app_handle))\n .await,\n )\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn read_feed_contents(\n state: State<'_, Arc>,\n feed_id: &str,\n offset: u64,\n count: u64,\n) -> Result, ()> {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .read_feed_contents(feed_id, offset, count)\n .await,\n )\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn query_by_id(\n state: State<'_, Arc>,\n id: i32,\n) -> Result, ()> {\n let features_api = &state.features_api;\n convert_result(features_api.query_by_id(id).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn mark_as_read(\n state: State<'_, Arc>,\n id: i32,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.mark_as_read(id).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn set_favorite(\n state: State<'_, Arc>,\n id: i32,\n favorite: bool,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.set_favorite(id, favorite).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn get_app_config(\n state: State<'_, Arc>,\n) -> Result {\n let features_api = &state.features_api;\n convert_result(features_api.get_app_config().await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn set_app_config(\n state: State<'_, Arc>,\n app_config: AppConfig,\n) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.set_app_config(app_config).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn get_ollama_status(\n state: State<'_, Arc>,\n) -> Result {\n let features_api = &state.features_api;\n convert_result(features_api.get_ollama_status().await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn download_ollama(state: State<'_, Arc>) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.download_ollama().await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn launch_ollama(state: State<'_, Arc>) -> Result<(), ()> {\n let features_api = &state.features_api;\n convert_result(features_api.launch_ollama().await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn open_article_external(\n state: State<'_, Arc>,\n url: &str,\n) -> Result<(), ()> {\n if !url.starts_with(\"https://\") {\n error!(\"open_article_external error, the url bypassed from web exists risk\");\n return Err(());\n }\n let features_api = &state.features_api;\n convert_result(features_api.open_article_external(url).await)\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn scrap_text_by_url(\n app_handle: AppHandle,\n url: &str,\n) -> Result {\n // 查询Article,获得url并抓取数据,将content塞进去并走llm workflow\n scrap_host::scrap_text_by_url(app_handle, url).await\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn update_article_by_source(\n app_handle: AppHandle,\n state: State<'_, Arc>,\n article_id: i32,\n url: &str,\n) -> Result {\n // 查询Article,获得url并抓取数据,将content塞进去并走llm workflow\n match scrap_host::scrap_text_by_url(app_handle, url).await {\n Ok(content) => {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .update_article_by_source(article_id, content)\n .await,\n )\n }\n Err(e) => {\n error!(\"command execution error...{:?}\", e);\n Err(())\n }\n }\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn chat_with_article_assistant(\n app_handle: AppHandle,\n state: State<'_, Arc>,\n article_id: i32,\n user_prompt: &str,\n history: Vec,\n) -> Result {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .chat_with_article_assistant(article_id, user_prompt, history)\n .await,\n )\n}\n\nfn convert_result(result: anyhow::Result) -> Result {\n match result {\n Ok(value) => Ok(value),\n Err(e) => {\n error!(\"command execution error...{}\", e);\n Err(())\n }\n }\n}\n\n#[tauri::command(rename_all = \"snake_case\")]\npub(crate) async fn search_contents_by_keyword(\n state: State<'_, Arc>,\n keyword: &str,\n offset: u64,\n count: u64,\n) -> Result, ()> {\n let features_api = &state.features_api;\n convert_result(\n features_api\n .search_contents_by_keyword(keyword, offset, count)\n .await,\n )\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 9.0, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 299, + "number_of_classes": 0, + "number_of_functions": 24 + }, + "dependencies": [ + { + "dependency_type": "std", + "is_external": false, + "line_number": null, + "name": "std::sync::Arc", + "path": null, + "version": null + }, + { + "dependency_type": "logging", + "is_external": true, + "line_number": null, + "name": "spdlog", + "path": "spdlog", + "version": null + }, + { + "dependency_type": "framework", + "is_external": true, + "line_number": null, + "name": "tauri", + "path": "tauri", + "version": null + }, + { + "dependency_type": "business_logic", + "is_external": true, + "line_number": null, + "name": "feed_api_rs", + "path": "feed_api_rs::features::api::FeaturesAPI", + "version": null + }, + { + "dependency_type": "ai_service", + "is_external": true, + "line_number": null, + "name": "ollama", + "path": "ollama::ProgramStatus", + "version": null + }, + { + "dependency_type": "data_access", + "is_external": true, + "line_number": null, + "name": "recorder", + "path": "recorder::entity::article_record::Model", + "version": null + }, + { + "dependency_type": "domain_model", + "is_external": true, + "line_number": null, + "name": "types", + "path": "types::{AppConfig, ConversationMessage, FeedTargetDescription, FeedsPackage}", + "version": null + }, + { + "dependency_type": "local_module", + "is_external": false, + "line_number": null, + "name": "crate::scrap_host", + "path": "crate::scrap_host", + "version": null + }, + { + "dependency_type": "local_state", + "is_external": false, + "line_number": null, + "name": "crate::state::HybridRuntimeState", + "path": "crate::state::HybridRuntimeState", + "version": null + } + ], + "detailed_description": "该组件是Tauri插件的核心命令层,负责暴露Rust后端功能给前端JavaScript调用。每个函数通过`#[tauri::command]`宏导出为IPC接口,统一使用`Arc`状态管理共享资源,并通过`features_api`代理实际业务逻辑。包含对Feeds包的增删改查、文章内容抓取与标记、Ollama模型控制、外部网页打开、AI对话等完整功能集。错误处理采用anyhow Result转换为标准Result<()>模式,日志通过spdlog记录。特别地,`scrap_text_by_url`依赖独立WebView窗口实现页面内容抓取,具有较强的系统集成能力。", + "interfaces": [ + { + "description": "添加新的订阅源包", + "interface_type": "command", + "name": "add_feeds_package", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "state", + "param_type": "State<'_, Arc>" + }, + { + "description": null, + "is_optional": false, + "name": "feeds_package", + "param_type": "FeedsPackage" + } + ], + "return_type": "Result<(), ()>", + "visibility": "private" + }, + { + "description": "移除指定ID的订阅源包", + "interface_type": "command", + "name": "remove_feeds_package", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "state", + "param_type": "State<'_, Arc>" + }, + { + "description": null, + "is_optional": false, + "name": "package_id", + "param_type": "&str" + } + ], + "return_type": "Result<(), ()>", + "visibility": "private" + }, + { + "description": "获取所有订阅源包列表", + "interface_type": "command", + "name": "get_feeds_packages", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "state", + "param_type": "State<'_, Arc>" + } + ], + "return_type": "Result, ()>", + "visibility": "private" + }, + { + "description": "更新指定订阅源的内容", + "interface_type": "command", + "name": "update_feed_contents", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "app_handle", + "param_type": "AppHandle" + }, + { + "description": null, + "is_optional": false, + "name": "state", + "param_type": "State<'_, Arc>" + }, + { + "description": null, + "is_optional": false, + "name": "package_id", + "param_type": "&str" + }, + { + "description": null, + "is_optional": false, + "name": "feed_id", + "param_type": "&str" + } + ], + "return_type": "Result<(), ()>", + "visibility": "private" + }, + { + "description": "与文章助手进行聊天对话", + "interface_type": "command", + "name": "chat_with_article_assistant", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "app_handle", + "param_type": "AppHandle" + }, + { + "description": null, + "is_optional": false, + "name": "state", + "param_type": "State<'_, Arc>" + }, + { + "description": null, + "is_optional": false, + "name": "article_id", + "param_type": "i32" + }, + { + "description": null, + "is_optional": false, + "name": "user_prompt", + "param_type": "&str" + }, + { + "description": null, + "is_optional": false, + "name": "history", + "param_type": "Vec" + } + ], + "return_type": "Result", + "visibility": "private" + } + ], + "responsibilities": [ + "提供Tauri IPC命令接口供前端调用", + "协调应用状态(HybridRuntimeState)与核心业务逻辑(FeaturesAPI)之间的交互", + "处理订阅源(FeedsPackage)和文章(Article)的CRUD操作", + "管理Ollama本地AI服务的生命周期(下载、启动、状态查询)", + "实现网页内容抓取及基于LLM的文章智能交互功能" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "Ollama 程序状态与版本信息查询组件,支持跨平台检测和远程健康检查", + "file_path": "crates/ollama/src/lib.rs", + "functions": [ + "install", + "launch", + "request_running", + "request_version", + "query_platform", + "query_platform_by_remote", + "query_platform_by_process", + "parse_version", + "parse_is_running_from_version", + "create_shell_command" + ], + "importance_score": 0.8, + "interfaces": [ + "ProgramStatus", + "Information", + "APIVersionResponse" + ], + "name": "lib.rs", + "source_summary": "use serde::{Deserialize, Serialize};\nuse tokio::process::Command;\nuse types::llm_endpoint::LLMEndPoint;\n\n#[derive(Serialize, Deserialize, Clone)]\npub enum ProgramStatus {\n Uninstall,\n InstallButNotRunning,\n Running,\n}\n\npub struct Information {\n pub version: String,\n pub status: ProgramStatus,\n pub extra: Option,\n}\n\n#[derive(Deserialize)]\nstruct APIVersionResponse {\n version: String,\n}\n\n#[cfg(target_os = \"windows\")]\nstatic PATH_TO_OLLAMA: &str = \"ollama\";\n#[cfg(target_os = \"macos\")]\nstatic PATH_TO_OLLAMA: &str = \"/usr/local/bin/ollama\";\n#[cfg(target_os = \"linux\")]\nstatic PATH_TO_OLLAMA: &str = \"/usr/local/bin/ollama\";\n\npub async fn install() {}\n\npub async fn launch() -> anyhow::Result<()> {\n create_shell_command()\n .arg(format!(\"{PATH_TO_OLLAMA} list\"))\n .output()\n .await?;\n Ok(())\n}\n\n#[cfg(target_family = \"unix\")]\nfn create_shell_command() -> Command {\n let mut cmd = Command::new(\"sh\");\n cmd.arg(\"-c\");\n cmd\n}\n\n#[cfg(target_family = \"windows\")]\nfn create_shell_command() -> Command {\n // use std::os::windows::process::CommandExt;\n let mut cmd = Command::new(\"cmd\");\n cmd.arg(\"/C\").creation_flags(0x08000000);\n cmd\n}\n\npub async fn request_running(llm_endpoint: &LLMEndPoint) -> anyhow::Result {\n let raw_str = reqwest::get(&llm_endpoint.api_base_url)\n .await?\n .text()\n .await?;\n Ok(raw_str.eq(\"Ollama is running\"))\n}\n\npub async fn request_version(llm_endpoint: &LLMEndPoint) -> anyhow::Result {\n let url = [llm_endpoint.api_base_url.as_str(), \"/api/version\"].join(\"\");\n let body: APIVersionResponse = reqwest::get(url).await?.json().await?;\n Ok(body.version)\n}\n\npub async fn query_platform(llm_endpoint: &LLMEndPoint) -> anyhow::Result {\n match query_platform_by_process().await {\n Ok(information) => match information.status {\n ProgramStatus::Uninstall => query_platform_by_remote(llm_endpoint).await,\n ProgramStatus::InstallButNotRunning => Ok(information),\n ProgramStatus::Running => Ok(information),\n },\n Err(_) => query_platform_by_remote(&LLMEndPoint::default()).await,\n }\n}\n\nasync fn query_platform_by_remote(llm_endpoint: &LLMEndPoint) -> anyhow::Result {\n let has_running = request_running(llm_endpoint).await?;\n if !has_running {\n return Ok(Information {\n version: \"-\".into(),\n status: ProgramStatus::Uninstall,\n extra: None,\n });\n }\n let version = request_version(llm_endpoint).await?;\n Ok(Information {\n version,\n status: ProgramStatus::Running,\n extra: None,\n })\n}\n\nasync fn query_platform_by_process() -> anyhow::Result {\n match create_shell_command()\n .arg(format!(\"{PATH_TO_OLLAMA} -v\"))\n .output()\n .await\n {\n Ok(output) => {\n if output.status.success() {\n let stdout_str = std::str::from_utf8(&output.stdout)?;\n let status = match parse_is_running_from_version(stdout_str) {\n true => ProgramStatus::Running,\n false => ProgramStatus::InstallButNotRunning,\n };\n return Ok(Information {\n version: parse_version(stdout_str).into(),\n status,\n extra: None,\n });\n }\n let stderr_str = std::str::from_utf8(&output.stderr)?;\n Ok(Information {\n version: \"-\".into(),\n status: ProgramStatus::Uninstall,\n extra: Some(stderr_str.to_owned()),\n })\n }\n Err(err) => Ok(Information {\n version: \"-\".into(),\n status: ProgramStatus::Uninstall,\n extra: Some(err.to_string()),\n }),\n }\n}\n\nfn parse_version(version_output: &str) -> &str {\n match version_output.find(\" version is \") {\n Some(index) => version_output.split_at(index + 12).1,\n None => \"unknown\",\n }\n}\n\nfn parse_is_running_from_version(version_output: &str) -> bool {\n !version_output.contains(\"could not connect to a running Ollama instance\")\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 0.3, + "cyclomatic_complexity": 8.0, + "depth_of_inheritance": 0, + "lines_of_code": 140, + "number_of_classes": 3, + "number_of_functions": 10 + }, + "dependencies": [ + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 1, + "name": "serde", + "path": null, + "version": null + }, + { + "dependency_type": "runtime", + "is_external": true, + "line_number": 2, + "name": "tokio", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 3, + "name": "types::llm_endpoint::LLMEndPoint", + "path": "crates/types/src/llm_endpoint.rs", + "version": null + } + ], + "detailed_description": "该组件负责管理 Ollama AI 模型运行时的状态检测、安装启动及版本查询。通过本地进程调用和远程 HTTP 接口两种方式判断 Ollama 是否已安装并运行,并获取其版本信息。支持 Windows、macOS 和 Linux 跨平台路径配置,使用条件编译处理不同操作系统的 shell 命令差异。核心逻辑包括:1) 通过执行 `ollama -v` 检查本地安装状态;2) 向 API 端点发送请求验证服务是否运行;3) 解析响应内容提取版本号;4) 综合判断返回结构化信息。", + "interfaces": [ + { + "description": "表示 Ollama 程序的三种状态:未安装、已安装但未运行、正在运行", + "interface_type": "enum", + "name": "ProgramStatus", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "封装版本号、状态和额外信息的响应数据结构", + "interface_type": "struct", + "name": "Information", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "用于反序列化远程 API 返回的版本信息", + "interface_type": "struct", + "name": "APIVersionResponse", + "parameters": [], + "return_type": null, + "visibility": "private" + } + ], + "responsibilities": [ + "检测 Ollama 在当前系统中的安装与运行状态", + "通过本地命令行和远程 API 双重机制获取程序信息", + "跨平台兼容性处理(Windows/macOS/Linux)", + "解析命令输出和 API 响应数据", + "提供统一的信息查询接口供上层模块调用" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "Tauri 应用的主入口模块,负责初始化应用插件、系统托盘、守护进程调度及窗口管理。", + "file_path": "app/src-tauri/src/lib.rs", + "functions": [ + "run" + ], + "importance_score": 0.8, + "interfaces": [ + "run" + ], + "name": "lib.rs", + "source_summary": "mod constrant;\nmod daemon;\nmod env;\nmod monitor;\n#[cfg(desktop)]\nmod tray;\n\nuse std::sync::Arc;\n\nuse constrant::WINDOW_MAIN_LABEL;\nuse daemon::{args::DAEMON_FEEDS_SCHEDULE_UPDATE, feeds_update::launch_feeds_schedule_update};\nuse tauri::{Manager, State};\nuse tauri_plugin_autostart::MacosLauncher;\nuse tauri_plugin_feed_api::state::HybridRuntimeState;\nuse tray::open_main_window;\n\n#[cfg_attr(mobile, tauri::mobile_entry_point)]\npub fn run() {\n monitor::start();\n\n tauri::Builder::default()\n .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {\n open_main_window(&app);\n }))\n .plugin(tauri_plugin_dialog::init())\n .plugin(tauri_plugin_os::init())\n .plugin(tauri_plugin_shell::init())\n .plugin(tauri_plugin_feed_api::init())\n .plugin(tauri_plugin_clipboard_manager::init())\n .plugin(tauri_plugin_autostart::init(\n MacosLauncher::LaunchAgent,\n Some(vec![DAEMON_FEEDS_SCHEDULE_UPDATE]),\n ))\n .invoke_handler(tauri::generate_handler![])\n .on_window_event(|window, event| match event {\n tauri::WindowEvent::CloseRequested { api, .. } => {\n if window.label() != WINDOW_MAIN_LABEL {\n return;\n }\n #[cfg(target_os = \"macos\")]\n {\n tauri::AppHandle::hide(window.app_handle()).unwrap();\n api.prevent_close();\n }\n }\n _ => {}\n })\n .setup(|app| {\n let handle = app.handle();\n #[cfg(all(desktop))]\n {\n tray::create_tray(handle)?;\n }\n\n let is_daemon = env::is_daemon();\n if !is_daemon {\n if let Some(window) = app.get_window(WINDOW_MAIN_LABEL) {\n window.show().unwrap();\n }\n }\n let state: State<'_, Arc> = app.state();\n let state_clone = Arc::clone(&state);\n launch_feeds_schedule_update(handle, state_clone).unwrap();\n Ok(())\n })\n .run(tauri::generate_context!())\n .expect(\"error while running Saga Reader Desktop Application\");\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 13.0, + "cyclomatic_complexity": 6.0, + "depth_of_inheritance": 0, + "lines_of_code": 68, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "constrant", + "path": "./app/src-tauri/src/constrant.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "daemon", + "path": "./app/src-tauri/src/daemon", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "env", + "path": "./app/src-tauri/src/env.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "monitor", + "path": "./app/src-tauri/src/monitor.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "tray", + "path": "./app/src-tauri/src/tray.rs", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": 7, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 15, + "name": "tauri_plugin_single_instance", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 18, + "name": "tauri_plugin_dialog", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 19, + "name": "tauri_plugin_os", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 20, + "name": "tauri_plugin_shell", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 21, + "name": "tauri_plugin_feed_api", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 22, + "name": "tauri_plugin_clipboard_manager", + "path": null, + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 23, + "name": "tauri_plugin_autostart", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是 Tauri 桌面应用的核心启动器,通过 `run` 函数构建并运行应用实例。它集成多个 Tauri 插件(如自动启动、剪贴板、Shell 等),设置单实例机制防止重复启动,并监听窗口关闭事件以在 macOS 上隐藏而非退出主窗口。支持桌面端系统托盘创建,提供‘显示主窗口’、‘网络信息’、‘关于’和‘退出’菜单项。通过 `env::is_daemon` 判断是否为守护进程模式,在非守护模式下显示主窗口,并启动定时更新订阅源的任务(`launch_feeds_schedule_update`)。整体作为智能 Agent 协调多个子模块完成应用生命周期管理。", + "interfaces": [ + { + "description": "应用的主入口函数,构建 Tauri 应用并启动事件循环。", + "interface_type": "function", + "name": "run", + "parameters": [], + "return_type": "void", + "visibility": "public" + } + ], + "responsibilities": [ + "初始化并运行 Tauri 应用实例", + "管理应用插件注册与配置", + "处理主窗口的显示/隐藏逻辑(尤其 macOS 平台)", + "创建系统托盘并响应用户交互", + "启动后台任务调度(如订阅源更新)" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "系统托盘图标管理组件,用于创建和控制桌面应用的托盘菜单及窗口行为", + "file_path": "app/src-tauri/src/tray.rs", + "functions": [ + "create_tray", + "open_main_window", + "bring_to_front" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "tray.rs", + "source_summary": "use tauri::{\n menu::{Menu, MenuItem},\n tray::TrayIconBuilder,\n Manager, Runtime, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder,\n};\n\nuse crate::constrant::{\n WINDOW_ABOUT_LABEL, WINDOW_ABOUT_TITLE, WINDOW_ABOUT_URL,\n WINDOW_EXTERNAL_ENDPOINT_INFORMATION_LABEL, WINDOW_EXTERNAL_ENDPOINT_INFORMATION_TITLE,\n WINDOW_EXTERNAL_ENDPOINT_INFORMATION_URL, WINDOW_MAIN_LABEL, WINDOW_MAIN_TITLE,\n WINDOW_MAIN_URL,\n};\n\npub fn create_tray(app: &tauri::AppHandle) -> tauri::Result<()> {\n let show_main_i = MenuItem::with_id(app, \"main_show\", \"显示主窗口\", true, None::<&str>)?;\n let show_endpoint_information =\n MenuItem::with_id(app, \"endpoint_information\", \"网络信息\", true, None::<&str>)?;\n let about_i = MenuItem::with_id(app, \"about\", \"关于\", true, None::<&str>)?;\n let quit_i = MenuItem::with_id(app, \"quit\", \"退出程序\", true, None::<&str>)?;\n let menu = Menu::with_items(\n app,\n &[&show_main_i, &show_endpoint_information, &about_i, &quit_i],\n )?;\n\n #[cfg(target_os = \"macos\")]\n let menu_click_by_left = true;\n #[cfg(not(target_os = \"macos\"))]\n let menu_click_by_left = false;\n\n let _ = TrayIconBuilder::with_id(\"tray\")\n .icon(app.default_window_icon().unwrap().clone())\n .menu(&menu)\n .show_menu_on_left_click(menu_click_by_left)\n .on_menu_event(move |app, event| match event.id.as_ref() {\n \"main_show\" => open_main_window(app),\n \"endpoint_information\" => {\n const WINDOW_LABEL: &str = WINDOW_EXTERNAL_ENDPOINT_INFORMATION_LABEL;\n const URL: &str = WINDOW_EXTERNAL_ENDPOINT_INFORMATION_URL;\n if let Some(window) = app.get_webview_window(WINDOW_LABEL) {\n bring_to_front(window);\n } else {\n WebviewWindowBuilder::new(\n app,\n WINDOW_LABEL,\n WebviewUrl::External(Url::parse(URL).expect(\"url parse error...ip77\")),\n )\n .title(WINDOW_EXTERNAL_ENDPOINT_INFORMATION_TITLE)\n .inner_size(1280 as f64, 720 as f64)\n .center()\n .build()\n .expect(\"build window failure for endpoint_information\")\n .show()\n .expect(\"show window failure for endpoint_information\");\n }\n }\n \"about\" => {\n if let Some(window) = app.get_webview_window(WINDOW_ABOUT_LABEL) {\n bring_to_front(window);\n } else {\n let window = WebviewWindowBuilder::new(\n app,\n WINDOW_ABOUT_LABEL,\n WebviewUrl::App(WINDOW_ABOUT_URL.into()),\n )\n .title(WINDOW_ABOUT_TITLE)\n .inner_size(480 as f64, 360 as f64)\n .resizable(false)\n .maximizable(false)\n .minimizable(false)\n .always_on_top(true)\n .center()\n .build()\n .expect(\"build about window failure\");\n window.show().unwrap();\n }\n }\n \"quit\" => {\n app.exit(0);\n }\n _ => {}\n })\n .on_tray_icon_event(|icon, event| match event {\n tauri::tray::TrayIconEvent::DoubleClick {\n id: _,\n position: _,\n rect: _,\n button: _,\n } => open_main_window(icon.app_handle()),\n _ => (),\n })\n .build(app);\n\n Ok(())\n}\n\npub fn open_main_window(app: &tauri::AppHandle) {\n if let Some(window) = app.get_webview_window(WINDOW_MAIN_LABEL) {\n bring_to_front(window);\n } else {\n let window = WebviewWindowBuilder::new(\n app,\n WINDOW_MAIN_LABEL,\n WebviewUrl::App(WINDOW_MAIN_URL.into()),\n )\n .title(WINDOW_MAIN_TITLE)\n .center()\n .min_inner_size(1440.0, 750.0)\n .maximized(true)\n .build()\n .expect(\"rebuild main window failure\");\n window.show().unwrap();\n }\n}\n\nfn bring_to_front(window: WebviewWindow) {\n let _ = window.unminimize();\n let _ = window.show();\n let _ = window.set_focus();\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.65, + "cyclomatic_complexity": 8.0, + "depth_of_inheritance": 0, + "lines_of_code": 119, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": true, + "line_number": 1, + "name": "tauri::menu::Menu", + "path": "tauri::menu::Menu", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 2, + "name": "tauri::menu::MenuItem", + "path": "tauri::menu::MenuItem", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 3, + "name": "tauri::tray::TrayIconBuilder", + "path": "tauri::tray::TrayIconBuilder", + "version": null + }, + { + "dependency_type": "trait", + "is_external": true, + "line_number": 4, + "name": "tauri::Manager", + "path": "tauri::Manager", + "version": null + }, + { + "dependency_type": "trait", + "is_external": true, + "line_number": 4, + "name": "tauri::Runtime", + "path": "tauri::Runtime", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 5, + "name": "tauri::Url", + "path": "tauri::Url", + "version": null + }, + { + "dependency_type": "enum", + "is_external": true, + "line_number": 5, + "name": "tauri::WebviewUrl", + "path": "tauri::WebviewUrl", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 6, + "name": "tauri::WebviewWindow", + "path": "tauri::WebviewWindow", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 6, + "name": "tauri::WebviewWindowBuilder", + "path": "tauri::WebviewWindowBuilder", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 9, + "name": "crate::constrant::WINDOW_ABOUT_LABEL", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 10, + "name": "crate::constrant::WINDOW_ABOUT_TITLE", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 11, + "name": "crate::constrant::WINDOW_ABOUT_URL", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 12, + "name": "crate::constrant::WINDOW_EXTERNAL_ENDPOINT_INFORMATION_LABEL", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 13, + "name": "crate::constrant::WINDOW_EXTERNAL_ENDPOINT_INFORMATION_TITLE", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 14, + "name": "crate::constrant::WINDOW_EXTERNAL_ENDPOINT_INFORMATION_URL", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 15, + "name": "crate::constrant::WINDOW_MAIN_LABEL", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 16, + "name": "crate::constrant::WINDOW_MAIN_TITLE", + "path": "crate::constrant", + "version": null + }, + { + "dependency_type": "const", + "is_external": false, + "line_number": 17, + "name": "crate::constrant::WINDOW_MAIN_URL", + "path": "crate::constrant", + "version": null + } + ], + "detailed_description": "该组件负责在桌面应用程序中创建系统托盘图标,并绑定右键菜单功能。支持通过托盘菜单项显示/隐藏主窗口、打开网络信息窗口、关于窗口以及退出程序。同时支持双击托盘图标打开主窗口。针对macOS和其他操作系统对菜单点击行为做了差异化处理。所有窗口配置(如标题、尺寸、URL)均从常量模块导入,确保配置集中化。", + "interfaces": [], + "responsibilities": [ + "创建并初始化系统托盘图标及其上下文菜单", + "响应托盘菜单事件以控制应用程序窗口的显示状态", + "实现跨平台托盘行为适配(特别是macOS左键点击菜单的支持)", + "管理多个独立窗口的打开与聚焦逻辑", + "提供通用的窗口前置显示辅助函数" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "负责守护进程的启动逻辑,包含带错误忽略的启动接口和标准启动流程。", + "file_path": "app/src-tauri/src/daemon/launcher.rs", + "functions": [ + "launch_ignore_error", + "launch" + ], + "importance_score": 0.8, + "interfaces": [ + "launch_ignore_error", + "launch" + ], + "name": "launcher.rs", + "source_summary": "use std::env;\nuse std::process::Command;\n\nuse fslock::LockFile;\nuse spdlog::{error, info};\n\nuse crate::daemon::locks::get_lock_path;\n\npub fn launch_ignore_error(host_arg: &str, locker_monitor_name: &str) -> () {\n match launch(host_arg, locker_monitor_name) {\n Ok(_) => (),\n Err(e) => error!(\n \"daemon launch error, host_arg = {}, locker_monitor_path = {}, error = {}\",\n host_arg, locker_monitor_name, e\n ),\n }\n}\n\npub fn launch(host_arg: &str, locker_monitor_name: &str) -> anyhow::Result<()> {\n let lock_path = get_lock_path(locker_monitor_name);\n let mut updater_lock = LockFile::open(&lock_path)?;\n if !updater_lock.try_lock()? {\n info!(\n \"it seems the daemon has already launched because of the locker has already owned. host_arg = {}, locker_monitor_path = {}\",\n host_arg, locker_monitor_name\n );\n return Ok(());\n }\n updater_lock.unlock()?;\n info!(\n \"daemon launching, host_arg = {}, locker_monitor_path = {}\",\n host_arg, locker_monitor_name\n );\n let current_exe = env::current_exe()?;\n Command::new(current_exe).arg(host_arg).spawn()?;\n info!(\n \"daemon launched, host_arg = {}, locker_monitor_path = {}\",\n host_arg, locker_monitor_name\n );\n Ok(())\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.55, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 41, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 1, + "name": "std::env", + "path": null, + "version": null + }, + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 2, + "name": "std::process::Command", + "path": null, + "version": null + }, + { + "dependency_type": "third_party", + "is_external": true, + "line_number": 4, + "name": "fslock::LockFile", + "path": null, + "version": null + }, + { + "dependency_type": "third_party", + "is_external": true, + "line_number": 5, + "name": "spdlog", + "path": null, + "version": null + }, + { + "dependency_type": "internal", + "is_external": false, + "line_number": 7, + "name": "crate::daemon::locks::get_lock_path", + "path": "app/src-tauri/src/daemon/locks.rs", + "version": null + } + ], + "detailed_description": "该组件实现了守护进程(daemon)的启动功能。核心逻辑是通过文件锁机制防止重复启动:首先获取指定名称的锁路径,尝试获取文件锁,若已锁定则说明守护进程已在运行,直接返回;否则释放锁并使用当前可执行文件路径结合参数重新启动守护进程。`launch_ignore_error` 提供了对错误静默处理的启动方式,仅在出错时记录日志。", + "interfaces": [ + { + "description": "安全地启动守护进程,若已被锁定则不重复启动", + "interface_type": "function", + "name": "launch", + "parameters": [ + { + "description": "传递给守护进程的主机参数", + "is_optional": false, + "name": "host_arg", + "param_type": "&str" + }, + { + "description": "用于生成锁文件路径的监控名称", + "is_optional": false, + "name": "locker_monitor_name", + "param_type": "&str" + } + ], + "return_type": "anyhow::Result<()>", + "visibility": "public" + }, + { + "description": "启动守护进程并在出错时仅记录日志而不中断调用方", + "interface_type": "function", + "name": "launch_ignore_error", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "host_arg", + "param_type": "&str" + }, + { + "description": null, + "is_optional": false, + "name": "locker_monitor_name", + "param_type": "&str" + } + ], + "return_type": "()", + "visibility": "public" + } + ], + "responsibilities": [ + "管理守护进程的启动流程", + "通过文件锁防止守护进程重复启动", + "提供静默失败的安全启动接口", + "记录关键启动事件日志", + "调用自身二进制启动新进程实例" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "负责定时拉取并更新订阅源内容的后台守护任务,基于配置频率执行周期性更新。", + "file_path": "app/src-tauri/src/daemon/feeds_update.rs", + "functions": [ + "launch_feeds_schedule_update", + "schedule_loop" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "feeds_update.rs", + "source_summary": "use std::sync::Arc;\n\nuse feed_api_rs::features::api::FeaturesAPI;\nuse fslock::LockFile;\nuse spdlog::{error, info, warn};\nuse tauri::{async_runtime, AppHandle, EventLoopMessage, Runtime};\nuse tauri_plugin_feed_api::state::HybridRuntimeState;\nuse tokio::time::{self, Duration, Instant};\n\nuse crate::daemon::locks::{get_lock_path, LOCK_FEEDS_SCHEDULE_UPDATE};\n\npub(crate) fn launch_feeds_schedule_update(\n app_handle: &AppHandle,\n state: Arc,\n) -> anyhow::Result<()> {\n // 防止重复运行更新实例\n let lock_path = get_lock_path(LOCK_FEEDS_SCHEDULE_UPDATE);\n let mut updater_lock = LockFile::open(&lock_path)?;\n if !updater_lock.try_lock()? {\n warn!(\n \"launch_feeds_schedule_update...lock failured, may be there already a updater running.\"\n );\n return Ok(());\n }\n let ah = app_handle.clone();\n async_runtime::spawn(async move {\n schedule_loop(ah, state)\n .await\n .expect(\"schedule_loop occurs error\");\n });\n Ok(())\n}\n\nasync fn schedule_loop(\n app_handle: AppHandle,\n state: Arc,\n) -> anyhow::Result<()> {\n let features = &state.features_api;\n let app_config = { features.context.read().await.app_config.clone() };\n // 在所有权转移前读取需要的配置\n let update_interval = Duration::from_secs(match &app_config.daemon.frequency_feeds_update {\n true => 60 * 60 * 1,\n false => 60 * 60 * 3,\n });\n\n let mut interval = time::interval_at(Instant::now() + update_interval, update_interval);\n\n // 定时任务\n loop {\n interval.tick().await;\n info!(\"scheduled feeds update begin\");\n let feeds_packages = features.get_feeds_packages().await;\n for feed_package in feeds_packages {\n for feed in feed_package.feeds {\n match features\n .update_feed_contents(&feed_package.id, &feed.id, Some(app_handle.clone()))\n .await\n {\n Ok(_) => (),\n Err(e) => error!(\n \"update_feed_contents failure, package_id = {}, feed_id = {}, error = {}\",\n &feed_package.id, &feed.id, e\n ),\n }\n }\n }\n info!(\"scheduled feeds update end\");\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 0.875, + "cyclomatic_complexity": 6.0, + "depth_of_inheritance": 0, + "lines_of_code": 69, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "std", + "is_external": false, + "line_number": null, + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "feed_api_rs::features::api::FeaturesAPI", + "path": "feed_api_rs::features::api::FeaturesAPI", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "fslock::LockFile", + "path": "fslock::LockFile", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "spdlog", + "path": "spdlog", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "tauri", + "path": "tauri", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "tauri_plugin_feed_api::state::HybridRuntimeState", + "path": "tauri_plugin_feed_api::state::HybridRuntimeState", + "version": null + }, + { + "dependency_type": "crate", + "is_external": true, + "line_number": null, + "name": "tokio::time", + "path": "tokio::time", + "version": null + }, + { + "dependency_type": "local", + "is_external": false, + "line_number": null, + "name": "crate::daemon::locks", + "path": "crate::daemon::locks", + "version": null + } + ], + "detailed_description": "该组件实现了一个后台定时任务代理(Agent),用于周期性地更新应用程序中的订阅源内容。通过读取应用配置中的更新频率(高频1小时或低频3小时),启动一个异步循环,每隔设定时间触发一次批量更新操作。每次执行时遍历所有已注册的feed package及其包含的feed项,并调用FeaturesAPI进行内容更新。使用文件锁机制防止多个实例同时运行,确保更新过程的唯一性和安全性。错误信息通过日志记录,成功与失败均有相应日志输出,便于监控和调试。", + "interfaces": [], + "responsibilities": [ + "管理订阅源内容的周期性自动更新任务", + "防止并发执行:通过文件锁确保同一时间仅有一个更新进程运行", + "根据应用配置动态调整更新频率(1小时或3小时)", + "协调调用FeaturesAPI完成各个feed的内容拉取与刷新", + "提供结构化日志输出以支持运行时监控和故障排查" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "Tauri应用的主入口文件,负责初始化并启动核心运行时。", + "file_path": "app/src-tauri/src/main.rs", + "functions": [ + "main" + ], + "importance_score": 0.8, + "interfaces": [ + "run" + ], + "name": "main.rs", + "source_summary": "// Prevents additional console window on Windows in release, DO NOT REMOVE!!\n#![cfg_attr(not(debug_assertions), windows_subsystem = \"windows\")]\n\nmod daemon;\nmod env;\n\nfn main() {\n qino_feed_client_lib::run()\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.33, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 9, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "library", + "is_external": false, + "line_number": 7, + "name": "qino_feed_client_lib", + "path": "crate::qino_feed_client_lib", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "daemon", + "path": "./daemon", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 4, + "name": "env", + "path": "./env", + "version": null + } + ], + "detailed_description": "该组件是Tauri桌面应用的程序入口点。通过cfg_attr属性在Windows发布版本中隐藏控制台窗口,确保用户体验整洁。它导入本地模块daemon和env,并在main函数中调用qino_feed_client_lib库的run函数来启动应用程序。整体逻辑简洁,专注于引导流程。", + "interfaces": [ + { + "description": "来自qino_feed_client_lib的核心启动函数,初始化应用服务、窗口及事件循环", + "interface_type": "function", + "name": "run", + "parameters": [], + "return_type": "Result<(), anyhow::Error>", + "visibility": "public" + } + ], + "responsibilities": [ + "作为应用程序的启动入口点", + "配置平台特定行为(如Windows下的控制台隐藏)", + "协调底层库的初始化与执行" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "实现了 Feeds 功能相关的 API 接口,封装了与后端 Tauri 模块的通信逻辑,提供 RSS/信息流管理、文章操作、AI 助手交互等功能。", + "file_path": "app/src/lib/hybrid-apis/feed/impl.ts", + "functions": [ + "isSpecifyFeed", + "isRecentFamilyFeed" + ], + "importance_score": 0.8, + "interfaces": [ + "FeaturesAPI" + ], + "name": "impl.ts", + "source_summary": "import { call } from \"../tauri-regular\";\nimport type { Option } from \"../tauri-regular\";\nimport type { FeaturesAPI } from \"./api\";\nimport type {\n FeedsPackage,\n FeedTargetDescription,\n ArticleModel,\n AppConfig,\n ConversationMessage,\n} from \"./types\";\n\nclass FeaturesAPIImpl implements FeaturesAPI {\n add_feeds_package(feeds_package: FeedsPackage): Promise {\n return call(\"add_feeds_package\", { feeds_package });\n }\n\n remove_feeds_package(package_id: string): Promise {\n return call(\"remove_feeds_package\", { package_id });\n }\n\n rename_feeds_package(package_id: string, new_name: string): Promise {\n return call(\"rename_feeds_package\", { package_id, new_name });\n }\n\n add_feed(package_id: string, ftd: FeedTargetDescription): Promise {\n return call(\"add_feed\", { package_id, ftd });\n }\n\n remove_feed(package_id: string, feed_id: string): Promise {\n return call(\"remove_feed\", { package_id, feed_id });\n }\n\n rename_feed(\n package_id: string,\n feed_id: string,\n new_name: string,\n ): Promise {\n return call(\"rename_feed\", { package_id, feed_id, new_name });\n }\n\n change_feed_data(\n package_id: string,\n feed_id: string,\n data: string[],\n ): Promise {\n return call(\"change_feed_data\", { package_id, feed_id, data });\n }\n\n get_feeds_packages(): Promise {\n return call(\"get_feeds_packages\", {});\n }\n\n get_feeds_by_package(package_id: string): Promise> {\n return call(\"get_feeds_by_package\", { package_id });\n }\n\n update_feed_contents(package_id: string, feed_id: string): Promise {\n return call(\"update_feed_contents\", { package_id, feed_id });\n }\n\n read_feed_contents(\n feed_id: string,\n offset: number,\n count: number,\n ): Promise {\n return call(\"read_feed_contents\", { feed_id, offset, count });\n }\n\n query_by_id(id: number): Promise {\n return call(\"query_by_id\", { id });\n }\n\n mark_as_read(id: number): Promise {\n return call(\"mark_as_read\", { id });\n }\n\n get_app_config(): Promise {\n return call(\"get_app_config\", {});\n }\n\n set_app_config(app_config: AppConfig): Promise {\n return call(\"set_app_config\", { app_config });\n }\n\n get_ollama_status(): Promise {\n return call(\"get_ollama_status\", {});\n }\n\n download_ollama(): Promise {\n return call(\"download_ollama\", {});\n }\n\n launch_ollama(): Promise {\n return call(\"launch_ollama\", {});\n }\n\n open_article_external(url: string): Promise {\n return call(\"open_article_external\", { url });\n }\n\n set_favorite(id: number, favorite: boolean): Promise {\n return call(\"set_favorite\", { id, favorite });\n }\n\n scrap_text_by_url(url: string): Promise {\n return call(\"scrap_text_by_url\", { url });\n }\n\n update_article_by_source(article_id: number, url: string): Promise {\n return call(\"update_article_by_source\", { article_id, url });\n }\n\n chat_with_article_assistant(\n article_id: number | undefined,\n user_prompt: string,\n history: ConversationMessage[],\n ): Promise {\n return call(\"chat_with_article_assistant\", {\n article_id,\n user_prompt,\n history,\n });\n }\n\n search_contents_by_keyword(\n keyword: string,\n offset: number,\n count: number,\n ): Promise {\n return call(\"search_contents_by_keyword\", { keyword, offset, count });\n }\n}\n\nconst SPECIFY_FEED_IDSET = {\n TODAY_FILTER: \"TODAY_FILTER\",\n WEEKEND_FILTER: \"WEEKEND_FILTER\",\n FAVORITE_FILTER: \"FAVORITE_FILTER\",\n UNREAD_FILTER: \"UNREAD_FILTER\",\n};\n\nfunction isSpecifyFeed(feedId: string | undefined) {\n if (!feedId) return false;\n return (\n Object.values(SPECIFY_FEED_IDSET).findIndex((id) => id === feedId) >= 0\n );\n}\n\nfunction isRecentFamilyFeed(feedId: string | undefined) {\n if (!feedId) return false;\n return (\n feedId === SPECIFY_FEED_IDSET.TODAY_FILTER ||\n feedId === SPECIFY_FEED_IDSET.WEEKEND_FILTER\n );\n}\n\nconst featuresApi = new FeaturesAPIImpl();\n\nexport {\n FeaturesAPIImpl,\n featuresApi,\n SPECIFY_FEED_IDSET,\n isSpecifyFeed,\n isRecentFamilyFeed,\n};\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.15, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 164, + "number_of_classes": 1, + "number_of_functions": 20 + }, + "dependencies": [ + { + "dependency_type": "module_import", + "is_external": false, + "line_number": 1, + "name": "../tauri-regular", + "path": "app/src/lib/hybrid-apis/feed/../tauri-regular", + "version": null + }, + { + "dependency_type": "module_import", + "is_external": false, + "line_number": 3, + "name": "./api", + "path": "app/src/lib/hybrid-apis/feed/api", + "version": null + }, + { + "dependency_type": "module_import", + "is_external": false, + "line_number": 4, + "name": "./types", + "path": "app/src/lib/hybrid-apis/feed/types", + "version": null + } + ], + "detailed_description": "该组件是 FeaturesAPI 的具体实现类 FeaturesAPIImpl,通过调用 Tauri 的通用 call 方法与原生后端进行异步通信。它提供了对信息流(Feeds)的完整 CRUD 操作支持,包括包管理、订阅增删改查、内容更新与读取;同时集成了应用配置管理、Ollama AI 引擎控制、外部链接打开、文本抓取、 favorites 标记、全文搜索及基于文章的智能对话功能。此外,还定义了特殊虚拟 feed ID 常量集合,并提供了判断 feed 类型的辅助函数。整体作为前端与本地后端之间的桥梁,承担混合 API 调用的核心职责。", + "interfaces": [ + { + "description": "定义了所有 Feeds 功能所需的方法契约,由 FeaturesAPIImpl 实现", + "interface_type": "class", + "name": "FeaturesAPI", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "封装 Tauri RPC 调用以实现 Feeds 相关业务逻辑", + "提供统一接口用于管理信息流订阅与内容同步", + "支持文章的阅读状态、收藏状态和内容检索操作", + "集成 AI 功能如 Ollama 控制与文章智能问答", + "导出工具函数以识别特定类型的 Feed" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "定义了用于管理订阅源、文章内容、应用配置及AI辅助交互的一系列异步接口。", + "file_path": "app/src/lib/hybrid-apis/feed/api.ts", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "FeaturesAPI" + ], + "name": "api.ts", + "source_summary": "import type { Option } from \"../tauri-regular\";\nimport type {\n AppConfig,\n ArticleModel,\n ConversationMessage,\n FeedsPackage,\n FeedTargetDescription,\n} from \"./types\";\n\ninterface FeaturesAPI {\n add_feeds_package: (feeds_package: FeedsPackage) => Promise;\n\n remove_feeds_package: (package_id: string) => Promise;\n\n rename_feeds_package: (package_id: string, new_name: string) => Promise;\n\n add_feed: (package_id: string, ftd: FeedTargetDescription) => Promise;\n\n remove_feed: (package_id: string, feed_id: string) => Promise;\n\n rename_feed: (\n package_id: string,\n feed_id: string,\n new_name: string,\n ) => Promise;\n\n get_feeds_packages: () => Promise;\n\n get_feeds_by_package: (package_id: string) => Promise>;\n\n update_feed_contents: (package_id: string, feed_id: string) => Promise;\n\n read_feed_contents: (\n feed_id: string,\n offset: number,\n count: number,\n ) => Promise;\n\n query_by_id: (id: number) => Promise;\n\n get_app_config: () => Promise;\n\n set_app_config: (appConfig: AppConfig) => Promise;\n\n get_ollama_status: () => Promise;\n\n download_ollama: () => Promise;\n\n launch_ollama: () => Promise;\n\n open_article_external: (url: string) => Promise;\n\n scrap_text_by_url: (url: string) => Promise;\n\n update_article_by_source: (\n article_id: number,\n url: string,\n ) => Promise;\n\n chat_with_article_assistant: (\n article_id: number,\n user_prompt: string,\n history: ConversationMessage[],\n ) => Promise;\n\n search_contents_by_keyword: (\n keyword: string,\n offset: number,\n count: number,\n ) => Promise;\n}\n\nexport type { FeaturesAPI };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 6.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 73, + "number_of_classes": 0, + "number_of_functions": 17 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": false, + "line_number": 1, + "name": "../tauri-regular", + "path": "app/src/lib/hybrid-apis/feed/../tauri-regular", + "version": null + } + ], + "detailed_description": "该组件定义了一个名为 FeaturesAPI 的 TypeScript 接口,封装了客户端与后端或原生层(如通过 Tauri)通信所需的所有方法。主要功能包括:对 FeedsPackage(订阅包)和 Feed(订阅源)的增删改查操作;获取和更新文章内容;基于关键词搜索文章;读取和设置应用配置;与 Ollama 模型服务进行交互(状态查询、下载、启动);支持外部打开文章链接和网页内容抓取;以及提供基于文章内容的智能对话能力。所有方法均以 Promise 形式返回,表明其异步特性,适用于跨进程或网络调用场景。", + "interfaces": [ + { + "description": "核心 API 接口契约,声明了所有可用的异步功能方法。", + "interface_type": "interface", + "name": "FeaturesAPI", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "提供统一的异步接口契约以管理信息流订阅体系", + "支持本地应用配置的持久化读写操作", + "集成 AI 功能(Ollama)以实现智能内容处理与交互", + "定义文章内容检索、更新与外部交互的标准方法", + "为前端或业务逻辑层屏蔽底层通信细节" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义了应用核心数据结构,包括LLM配置、信息流抓取、文章模型和对话消息等类型。", + "file_path": "app/src/lib/hybrid-apis/feed/types.ts", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "AppConfig", + "LLMProviderType", + "FeedsPackage", + "FeedTargetDescription", + "ArticleModel", + "FeedFetcherID", + "ConversationMessage", + "ConversationInput" + ], + "name": "types.ts", + "source_summary": "type LLMProviderType = \"ollama\" | \"platform\" | \"glm\" | \"openai\";\n\ntype LLMSection = {\n provider_ollama: {\n endpoint: {\n api_base_url: string;\n model: string;\n };\n };\n provider_glm: {\n api_key: string;\n };\n provider_openai: {\n model_name: string;\n api_base_url: string;\n api_key: string;\n };\n provider_platform: {\n template_path: string;\n model_path: string;\n };\n active_provider_type: LLMProviderType;\n instruct: {\n lang: string;\n emphasis: string | undefined | null;\n };\n};\n\ntype AppConfig = {\n llm: LLMSection;\n scrap: \"baidu\" | \"bing\";\n daemon: {\n frequency_feeds_update: boolean;\n };\n};\n\ntype FeedFetcherID = \"scrap\" | \"rss\";\n\ntype FeedTargetDescription = {\n id: string;\n name: string;\n fetcher_id: FeedFetcherID;\n data: string[];\n};\n\ntype FeedsPackage = {\n id: string;\n name: string;\n feeds: FeedTargetDescription[];\n is_flat_on_root: boolean;\n};\n\ntype ArticleModel = {\n id: number;\n title: string;\n source_link: string;\n head_read: string;\n purged_content: string;\n optimized_content: string;\n melted_content: string;\n published_at: string;\n created_at: string;\n has_read: boolean;\n group_id: string;\n is_favorite: boolean;\n};\n\ntype ConversationMessage = {\n role: \"system\" | \"user\" | \"assistant\";\n mtype: \"text\" | \"image\" | \"video\" | \"audio\" | \"file\";\n payload: string;\n created_at: string;\n};\n\ntype ConversationInput = {\n mtype: \"text\" | \"image\" | \"video\" | \"audio\" | \"file\";\n payload: string;\n};\n\nexport type {\n AppConfig,\n LLMProviderType,\n FeedsPackage,\n FeedTargetDescription,\n ArticleModel,\n FeedFetcherID,\n ConversationMessage,\n ConversationInput,\n};\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 89, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是系统中的核心类型定义文件,主要用于声明应用程序中多个模块共享的数据结构。主要包括:1) LLMProviderType 和 LLMSection 定义了支持的大型语言模型提供者及其对应的配置参数;2) AppConfig 封装了整个应用的顶层配置结构;3) Feed 相关类型(FeedFetcherID, FeedTargetDescription, FeedsPackage)用于描述信息源抓取的目标与组织方式;4) ArticleModel 表示一篇文章的完整元数据和内容状态;5) ConversationMessage 和 ConversationInput 支持多模态对话交互的消息格式。所有类型均通过 export type 导出,供其他模块按需引用。", + "interfaces": [ + { + "description": "应用的顶层配置对象,包含LLM设置、爬虫选项和守护进程策略", + "interface_type": "object", + "name": "AppConfig", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "支持的语言模型提供者枚举类型", + "interface_type": "union", + "name": "LLMProviderType", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "LLM相关配置的完整结构,包含各provider的具体字段和激活类型", + "interface_type": "object", + "name": "LLMSection", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "信息源抓取器标识符,决定使用哪种抓取机制", + "interface_type": "union", + "name": "FeedFetcherID", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "单个信息源目标的描述,包括ID、名称、抓取器和原始数据", + "interface_type": "object", + "name": "FeedTargetDescription", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "信息源包的容器结构,包含多个feed及其组织逻辑", + "interface_type": "object", + "name": "FeedsPackage", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "文章实体的完整模型,涵盖展示、存储和处理所需的所有字段", + "interface_type": "object", + "name": "ArticleModel", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "对话系统中的消息单元,支持多种角色和媒体类型", + "interface_type": "object", + "name": "ConversationMessage", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "用户输入消息的简化结构,仅包含媒体类型和负载", + "interface_type": "object", + "name": "ConversationInput", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "定义并导出应用程序的通用数据模型", + "统一LLM服务提供商的配置结构", + "规范信息流抓取任务的数据格式", + "提供文章内容处理的标准化表示", + "支持多模态对话系统的消息类型定义" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "Tauri插件调用的统一接口封装,用于与原生功能交互。", + "file_path": "app/src/lib/hybrid-apis/tauri-regular/index.ts", + "functions": [ + "call" + ], + "importance_score": 0.8, + "interfaces": [ + "InvokeArgs", + "Option" + ], + "name": "index.ts", + "source_summary": "import { invoke } from '@tauri-apps/api/core';\n\ntype InvokeArgs = Record | number[] | ArrayBuffer | Uint8Array;\n\ntype Option = T | null | undefined;\n\nasync function call(methodName: string, args: InvokeArgs): Promise {\n\treturn invoke(`plugin:feed-api|${methodName}`, args);\n}\n\nexport type { InvokeArgs, Option };\n\nexport { call };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.08, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 13, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "@tauri-apps/api/core", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是Tauri框架下与原生插件通信的核心桥梁,通过`invoke`机制调用名为'feed-api'的Rust插件方法。它定义了类型安全的泛型函数`call`,接收方法名和参数,并返回Promise类型的响应结果。所有对外暴露的方法均通过'plugin:feed-api|{methodName}'格式进行路由,实现了前端JavaScript/TypeScript与后端Rust逻辑的安全异步通信。", + "interfaces": [ + { + "description": "允许传递对象、数字数组或二进制数据作为调用参数的联合类型", + "interface_type": "type", + "name": "InvokeArgs", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "表示可选值的标准类型定义,兼容null和undefined", + "interface_type": "type", + "name": "Option", + "parameters": [ + { + "description": "泛型占位符", + "is_optional": false, + "name": "T", + "param_type": "generic" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "执行异步插件调用并返回泛型结果", + "interface_type": "function", + "name": "call", + "parameters": [ + { + "description": "要调用的Rust插件方法名称", + "is_optional": false, + "name": "methodName", + "param_type": "string" + }, + { + "description": "传递给方法的序列化参数", + "is_optional": false, + "name": "args", + "param_type": "InvokeArgs" + } + ], + "return_type": "Promise", + "visibility": "public" + } + ], + "responsibilities": [ + "提供统一的Tauri插件调用接口", + "封装底层invoke通信细节", + "实现类型安全的跨语言方法调用", + "管理与原生模块的异步通信协议" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": null, + "file_path": "app/src/lib/index.ts", + "functions": [], + "importance_score": 0.8, + "interfaces": [], + "name": "index.ts", + "source_summary": "// place files you want to import through the `$lib` alias in this folder.\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 1, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是一个空的入口文件,当前仅包含一条注释,说明其用途是存放通过 `$lib` 别名导入的文件。它本身不导出任何功能或模块,也没有实现具体逻辑。", + "interfaces": [], + "responsibilities": [ + "作为项目中 `@lib` 别名指向的入口目录索引", + "组织和集中管理共享库代码的导出(未来潜在职责)", + "提供可扩展的模块导入机制供其他部分引用" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供Tauri应用中窗口管理的工具函数,支持单例窗口展示和带回调的窗口打开功能。", + "file_path": "app/src/lib/windows/utils.ts", + "functions": [ + "openWithCallback", + "showWindowSingleton" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "utils.ts", + "source_summary": "import { Window, getAllWindows, type WindowOptions } from '@tauri-apps/api/window';\nimport { Webview } from '@tauri-apps/api/webview';\nimport type { UnlistenFn } from '@tauri-apps/api/event';\n\nasync function openWithCallback(\n\tlabel: string,\n\turl: string,\n\tonClose: (data: string) => void,\n\twindowOpt?: WindowOptions\n): Promise {\n\tconst eventId = `event-openWithCallback-${Date.now()}`;\n\tconst urlWithEventId =\n\t\turl.indexOf('?') < 0\n\t\t\t? `${url}?callbackEventId=${eventId}`\n\t\t\t: `${url}&callbackEventId=${eventId}`;\n\tconst window = await showWindowSingleton(label, urlWithEventId, windowOpt);\n\treturn window.listen(eventId, (e) => onClose(e.payload));\n}\n\nasync function showWindowSingleton(\n\tlabel: string,\n\turl: string,\n\twindowOpt?: WindowOptions\n): Promise {\n\tconst windows = await getAllWindows();\n\tconst existed_window = windows.find((w) => w.label === label);\n\tif (existed_window) {\n\t\texisted_window.setFocus();\n\t\treturn existed_window;\n\t}\n\n\tconst new_window = new Window(label, windowOpt);\n\tnew Webview(new_window, label, {\n\t\turl: url,\n\t\tx: 0,\n\t\ty: 0,\n\t\twidth: windowOpt?.width || 100,\n\t\theight: windowOpt?.height || 100\n\t});\n\treturn new_window;\n}\n\nexport { showWindowSingleton, openWithCallback };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.6, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 43, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "@tauri-apps/api/window", + "path": null, + "version": null + }, + { + "dependency_type": "import", + "is_external": true, + "line_number": 2, + "name": "@tauri-apps/api/webview", + "path": null, + "version": null + }, + { + "dependency_type": "import", + "is_external": true, + "line_number": 3, + "name": "@tauri-apps/api/event", + "path": null, + "version": null + } + ], + "detailed_description": "该组件封装了Tauri框架下窗口(Window)与Webview的创建与管理逻辑。主要包含两个核心函数:`showWindowSingleton`用于确保指定label的窗口在应用中仅存在一个实例,若已存在则聚焦该窗口,否则创建新窗口;`openWithCallback`在此基础上扩展,允许在新窗口关闭时通过事件机制触发回调函数,实现跨窗口通信。URL中注入唯一事件ID以保证通信的安全性和隔离性。", + "interfaces": [], + "responsibilities": [ + "管理Tauri应用中的窗口生命周期,确保单例模式", + "实现跨窗口异步回调通信机制", + "封装Webview的初始化与配置逻辑", + "处理URL参数拼接以支持事件回调绑定" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "该文件是窗口模块的入口,负责导出窗口相关的功能,当前仅导出打开设置窗口的功能。", + "file_path": "app/src/lib/windows/index.ts", + "functions": [ + "openSettings" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "index.ts", + "source_summary": "import { open as openSettings } from './settings';\n\nexport { openSettings };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 1.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 3, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": false, + "line_number": 1, + "name": "./settings", + "path": "app/src/lib/windows/settings", + "version": null + } + ], + "detailed_description": "该组件作为窗口模块的公共入口文件,通过重新导出从 './settings' 模块导入的 open 函数,提供统一的访问接口。它简化了外部模块对窗口操作函数的引用路径,符合模块化设计中的聚合模式。", + "interfaces": [], + "responsibilities": [ + "作为窗口模块的公共API入口", + "聚合并重新导出窗口相关功能", + "简化外部模块的导入路径", + "维护模块间依赖关系的清晰性" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "该组件负责管理与订阅组和订阅相关的窗口打开逻辑,封装了 Tauri 窗口操作的异步交互流程。", + "file_path": "app/src/lib/windows/lite-edit.ts", + "functions": [ + "openFeedPackageCreateWindow", + "openFeedPackageEditWindow", + "openFeedCreateWindow", + "openFeedEditWindow", + "open" + ], + "importance_score": 0.8, + "interfaces": [ + "UnlistenFn", + "FeedsPackage", + "FeedTargetDescription", + "WindowOptions" + ], + "name": "lite-edit.ts", + "source_summary": "import type { UnlistenFn } from '@tauri-apps/api/event';\nimport { openWithCallback } from './utils';\nimport type { FeedsPackage, FeedTargetDescription } from '$lib/hybrid-apis/feed/types';\nimport type { WindowOptions } from '@tauri-apps/api/window';\n\nfunction openFeedPackageCreateWindow(): Promise {\n\treturn new Promise((resolve) => {\n\t\topen(\n\t\t\t'window_feed_create',\n\t\t\t'新增订阅组',\n\t\t\t`/feedsPackage/create_or_edit?mode=create`,\n\t\t\t(submited: boolean, data: string) => {\n\t\t\t\tconst result = JSON.parse(data) as FeedsPackage;\n\t\t\t\tresolve(result);\n\t\t\t},\n\t\t\t{ height: 220 }\n\t\t);\n\t});\n}\n\nfunction openFeedPackageEditWindow(\n\tid: string,\n\tname: string\n): Promise<{ submited: boolean; newName: string }> {\n\treturn new Promise((resolve) => {\n\t\topen(\n\t\t\t'window_feeds_package_edit',\n\t\t\t'编辑订阅组',\n\t\t\t`/feedsPackage/create_or_edit?mode=edit&id=${id}&name=${name}`,\n\t\t\t(submited: boolean, newName: string) => {\n\t\t\t\tresolve({ submited, newName });\n\t\t\t},\n\t\t\t{ height: 220 }\n\t\t);\n\t});\n}\n\nfunction openFeedCreateWindow(feedsPackageId: string): Promise {\n\treturn new Promise((resolve) => {\n\t\topen(\n\t\t\t'window_feeds_package_create',\n\t\t\t'新增订阅',\n\t\t\t`/feeds/create_or_edit?mode=create&feedsPackageId=${feedsPackageId}`,\n\t\t\t(submited: boolean, data: string) => {\n\t\t\t\tconst result = JSON.parse(data) as FeedTargetDescription;\n\t\t\t\tresolve(result);\n\t\t\t},\n\t\t\t{ height: 400 }\n\t\t);\n\t});\n}\n\nfunction openFeedEditWindow(\n\tid: string,\n\tname: string,\n\tfetcher_id: string,\n\tdata: string[],\n\tfeedsPackageId: string\n): Promise<{ submited: boolean; newName: string }> {\n\treturn new Promise((resolve) => {\n\t\topen(\n\t\t\t'window_feed_edit',\n\t\t\t'编辑订阅',\n\t\t\t`/feeds/create_or_edit?mode=edit&id=${id}&name=${name}&fetcher_id=${fetcher_id}&data=${JSON.stringify(data)}&feedsPackageId=${feedsPackageId}`,\n\t\t\t(submited: boolean, newName: string) => {\n\t\t\t\tresolve({ submited, newName });\n\t\t\t},\n\t\t\t{ height: 400 }\n\t\t);\n\t});\n}\n\nasync function open(\n\tlabel: string,\n\ttitle: string,\n\turl: string,\n\tonFinish: (submited: boolean, data: string) => void,\n\twindowOpt: WindowOptions = {}\n) {\n\tlet disposer: UnlistenFn | null = null;\n\tconst onCloseWithAutoDispose = (data: string) => {\n\t\tconsole.log('onCloseWithAutoDispose...callback', data);\n\t\tonFinish(!!data, data);\n\t\tif (disposer) disposer();\n\t};\n\tdisposer = await openWithCallback(label, url, onCloseWithAutoDispose, {\n\t\ttitle,\n\t\twidth: 600,\n\t\tcenter: true,\n\t\tresizable: false,\n\t\tmaximizable: false,\n\t\talwaysOnTop: true,\n\t\t...windowOpt\n\t});\n}\n\nexport {\n\topen,\n\topenFeedPackageCreateWindow,\n\topenFeedPackageEditWindow,\n\topenFeedCreateWindow,\n\topenFeedEditWindow\n};\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.6, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 103, + "number_of_classes": 0, + "number_of_functions": 5 + }, + "dependencies": [ + { + "dependency_type": "type", + "is_external": true, + "line_number": 1, + "name": "@tauri-apps/api/event", + "path": null, + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 2, + "name": "./utils", + "path": "app/src/lib/windows/utils", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "$lib/hybrid-apis/feed/types", + "path": "app/src/lib/hybrid-apis/feed/types", + "version": null + }, + { + "dependency_type": "type", + "is_external": true, + "line_number": 4, + "name": "@tauri-apps/api/window", + "path": null, + "version": null + } + ], + "detailed_description": "该文件实现了一组用于打开模态窗口的函数,主要用于创建或编辑‘订阅组’(FeedsPackage) 和 ‘订阅’(Feed)。每个公开函数都返回一个 Promise,封装了通过回调接收用户输入结果的异步过程。核心逻辑集中在 `open` 函数中,它利用 Tauri 的 `openWithCallback` 方法打开指定 URL 的新窗口,并在窗口关闭时执行回调,自动清理事件监听器。所有上层函数(如 openFeedPackageCreateWindow)基于此通用机制构造特定参数的 URL 并解析返回数据。整个模块作为 UI 控制层,桥接前端页面与底层窗口系统。", + "interfaces": [ + { + "description": "通用函数:打开指定标签、标题、URL的窗口,并注册关闭回调。支持传入选项覆盖默认窗口配置。", + "interface_type": "function", + "name": "open", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "label", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "title", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "url", + "param_type": "string" + }, + { + "description": null, + "is_optional": false, + "name": "onFinish", + "param_type": "(submited: boolean, data: string) => void" + }, + { + "description": null, + "is_optional": true, + "name": "windowOpt", + "param_type": "WindowOptions" + } + ], + "return_type": "Promise", + "visibility": "exported" + }, + { + "description": "打开‘新增订阅组’窗口,用户提交后返回 FeedsPackage 数据对象。", + "interface_type": "function", + "name": "openFeedPackageCreateWindow", + "parameters": [], + "return_type": "Promise", + "visibility": "exported" + } + ], + "responsibilities": [ + "提供统一的窗口打开与回调处理机制", + "封装订阅组和订阅的创建/编辑窗口打开逻辑", + "管理窗口生命周期中的事件监听器自动释放", + "构造带参数的导航URL以传递模式和上下文数据", + "将底层回调接口转换为Promise风格的异步API" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "国际化模块的初始化入口,负责加载多语言资源并配置默认语言环境。", + "file_path": "app/src/lib/i18n/index.ts", + "functions": [], + "importance_score": 0.8, + "interfaces": [], + "name": "index.ts", + "source_summary": "import { init } from \"svelte-i18n\";\nimport { addMessages } from \"svelte-i18n\";\nimport { fallbackLocale, getLocale } from \"./settings\";\nimport en from \"./locales/en.json\";\nimport zh from \"./locales/zh.json\";\n\naddMessages(\"en\", en);\naddMessages(\"zh\", zh);\n\ninit({\n fallbackLocale,\n initialLocale: getLocale(),\n});\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 5.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 13, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "library", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": null, + "version": null + }, + { + "dependency_type": "library", + "is_external": true, + "line_number": 2, + "name": "svelte-i18n", + "path": null, + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "./settings", + "path": "app/src/lib/i18n/settings", + "version": null + }, + { + "dependency_type": "resource", + "is_external": false, + "line_number": 4, + "name": "./locales/en.json", + "path": "app/src/lib/i18n/locales/en.json", + "version": null + }, + { + "dependency_type": "resource", + "is_external": false, + "line_number": 5, + "name": "./locales/zh.json", + "path": "app/src/lib/i18n/locales/zh.json", + "version": null + } + ], + "detailed_description": "该组件是Svelte应用中i18n(国际化)系统的初始化入口。它通过导入svelte-i18n库的核心函数init和addMessages,注册英文(en)和中文(zh)的语言包,并基于getLocale()获取当前用户的首选语言,fallbackLocale作为备用语言进行初始化配置。整个逻辑在模块加载时自动执行,无需显式调用,确保应用启动时语言环境已正确设置。", + "interfaces": [], + "responsibilities": [ + "加载并注册多语言消息(en, zh)", + "初始化i18n系统的核心配置", + "设置回退语言和初始语言", + "作为i18n功能的统一接入点" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "主题管理模块,用于获取、设置和应用UI主题(亮色/暗色),支持持久化存储与DOM同步。", + "file_path": "app/src/lib/themes/index.ts", + "functions": [ + "getTheme", + "setTheme", + "applyTheme", + "setWebInnerOnly" + ], + "importance_score": 0.8, + "interfaces": [ + "ThemePresets" + ], + "name": "index.ts", + "source_summary": "import { setTheme as setAppTheme } from '@tauri-apps/api/app';\n\ntype ThemePresets = 'light' | 'dark';\nconst LITE_STORAGE_KEY_THEME = 'ls_user_theme';\n\nfunction getTheme(): ThemePresets {\n\treturn (window.localStorage.getItem(LITE_STORAGE_KEY_THEME) || 'light') as ThemePresets;\n}\n\nfunction setTheme(theme: ThemePresets) {\n\tsetAppTheme(theme);\n\twindow.localStorage.setItem(LITE_STORAGE_KEY_THEME, theme);\n}\n\nfunction applyTheme(): ThemePresets {\n\tconst theme = getTheme();\n\tsetAppTheme(theme);\n\tsetWebInnerOnly(theme);\n\treturn theme;\n}\n\nfunction setWebInnerOnly(theme: ThemePresets) {\n\tdocument.documentElement.classList.toggle('dark', theme === 'dark');\n}\n\nexport { applyTheme, getTheme, setTheme, setWebInnerOnly };\nexport type { ThemePresets };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.25, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 27, + "number_of_classes": 0, + "number_of_functions": 5 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "@tauri-apps/api/app", + "path": null, + "version": null + } + ], + "detailed_description": "该组件实现了前端应用的主题管理系统,支持亮色和暗色两种预设模式。通过localStorage持久化用户选择的主题,并利用Tauri API在桌面端同步主题设置。组件提供四个核心函数:getTheme读取当前主题,setTheme更新主题并持久化,applyTheme应用当前存储的主题到应用环境,setWebInnerOnly则负责更新DOM以反映主题变化。类型ThemePresets定义了合法的主题值。所有功能通过统一接口导出,便于外部调用。", + "interfaces": [ + { + "description": "定义支持的主题类型枚举,限制主题值仅为'light'或'dark'", + "interface_type": "type", + "name": "ThemePresets", + "parameters": [], + "return_type": "'light' | 'dark'", + "visibility": "exported" + }, + { + "description": "从localStorage读取用户主题偏好,若无则返回默认'light'主题", + "interface_type": "function", + "name": "getTheme", + "parameters": [], + "return_type": "ThemePresets", + "visibility": "exported" + }, + { + "description": "设置主题并同步到localStorage和Tauri原生环境", + "interface_type": "function", + "name": "setTheme", + "parameters": [ + { + "description": "要设置的主题模式", + "is_optional": false, + "name": "theme", + "param_type": "ThemePresets" + } + ], + "return_type": "void", + "visibility": "exported" + } + ], + "responsibilities": [ + "管理应用的主题状态(亮色/暗色)", + "通过localStorage实现主题偏好持久化", + "调用Tauri API同步原生应用主题", + "更新DOM类名以应用CSS主题样式", + "提供统一的主题操作接口供系统其他部分使用" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "嵌入式Web视图组件,用于加载外部网页内容并提供加载状态反馈", + "file_path": "app/src/lib/widgets/EmbedWebView.svelte", + "functions": [ + "onLoadEventHandler", + "onVisiblityChanged" + ], + "importance_score": 0.8, + "interfaces": [ + "EmbedWebViewProps" + ], + "name": "EmbedWebView.svelte", + "source_summary": "\n\n\n\t{#if hasRequestToUse}\n\t\t{#if loadingStatus === LoadingStatus.Loading}\n\t\t\t\n\t\t{/if}\n\t\t\n\t{/if}\n\n\n\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.5, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 79, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "function", + "is_external": false, + "line_number": 1, + "name": "observeVisiblity", + "path": "$lib/utils/dom", + "version": null + }, + { + "dependency_type": "enum", + "is_external": false, + "line_number": 2, + "name": "LoadingStatus", + "path": "$lib/types/loading", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 3, + "name": "EmbedWebViewProps", + "path": "./types", + "version": null + }, + { + "dependency_type": "component", + "is_external": true, + "line_number": 4, + "name": "Progress", + "path": "@skeletonlabs/skeleton-svelte", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于在应用中嵌入外部网页。通过iframe实现内容加载,并结合自定义的可见性观察器和加载状态管理,优化用户体验。组件支持传入src属性指定目标URL,并暴露onLoadStart和onLoadEnd回调函数以通知页面加载生命周期。使用Skeleton框架的Progress组件显示加载进度动画,在内容完全加载前隐藏iframe以避免闪烁。组件采用$state和$effect.pre进行响应式状态管理,确保在属性变化时正确重置加载状态。", + "interfaces": [ + { + "description": "嵌入式WebView组件的输入属性类型定义", + "interface_type": "type", + "name": "EmbedWebViewProps", + "parameters": [ + { + "description": "要嵌入的网页URL", + "is_optional": false, + "name": "src", + "param_type": "string" + }, + { + "description": "加载开始时的回调函数", + "is_optional": true, + "name": "onLoadStart", + "param_type": "(src: string) => void" + }, + { + "description": "加载完成时的回调函数", + "is_optional": true, + "name": "onLoadEnd", + "param_type": "(src: string) => void" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "处理iframe加载完成事件的内部处理器", + "interface_type": "function", + "name": "onLoadEventHandler", + "parameters": [], + "return_type": "void", + "visibility": "private" + } + ], + "responsibilities": [ + "管理嵌入式网页的加载生命周期", + "提供可视化的加载状态指示", + "优化资源加载策略(仅当组件可见时才请求内容)", + "封装iframe的安全沙箱配置", + "向父组件传递加载状态事件" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "提供可复用的右键上下文菜单功能,支持动态菜单项渲染和位置自适应。", + "file_path": "app/src/lib/widgets/ContextMenuProvider.svelte", + "functions": [ + "showContextMenu", + "onHideMenu", + "getContextMenuDimension", + "wrapMenuPressHandler" + ], + "importance_score": 0.8, + "interfaces": [ + "MenuType" + ], + "name": "ContextMenuProvider.svelte", + "source_summary": "\n\n\n\n\n\n{#if menus && menus.length !== 0}\n\t
\n\t\t{@render children()}\n\t
\n\n\t{#if showMenu}\n\t\t\n\t{/if}\n\n\t\n\n\t\n{/if}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.88, + "coupling_factor": 0.25, + "cyclomatic_complexity": 7.0, + "depth_of_inheritance": 0, + "lines_of_code": 160, + "number_of_classes": 0, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 2, + "name": "svelte", + "path": "svelte", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于在用户右键点击时显示一个上下文菜单。它通过接收`menus`属性来动态渲染菜单项,并根据浏览器窗口尺寸自动调整菜单位置以避免溢出。组件使用了Svelte的响应式状态管理($state)和片段(Snippet)机制,确保良好的封装性和可复用性。菜单项支持图标、文本和点击回调函数,并可通过`wrapMenuPressHandler`统一处理事件冒泡与关闭逻辑。", + "interfaces": [ + { + "description": "定义上下文菜单中单个菜单项的数据结构", + "interface_type": "type", + "name": "MenuType", + "parameters": [ + { + "description": "菜单项唯一标识,用于key映射或分隔线标记", + "is_optional": false, + "name": "name", + "param_type": "string" + }, + { + "description": "菜单项点击时触发的回调函数", + "is_optional": false, + "name": "onClick", + "param_type": "() => void" + }, + { + "description": "菜单项显示的文字内容", + "is_optional": false, + "name": "displayText", + "param_type": "string" + }, + { + "description": "图标CSS类名,如FontAwesome类", + "is_optional": false, + "name": "class", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "private" + }, + { + "description": "显示上下文菜单,阻止默认行为,设置坐标并防止重叠", + "interface_type": "function", + "name": "showContextMenu", + "parameters": [ + { + "description": "鼠标右键点击事件对象", + "is_optional": false, + "name": "e", + "param_type": "MouseEvent" + } + ], + "return_type": "boolean", + "visibility": "private" + }, + { + "description": "当点击页面其他区域时隐藏上下文菜单", + "interface_type": "function", + "name": "onHideMenu", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "获取并更新上下文菜单的实际宽高用于定位计算", + "interface_type": "function", + "name": "getContextMenuDimension", + "parameters": [ + { + "description": "上下文菜单DOM节点", + "is_optional": false, + "name": "node", + "param_type": "HTMLElement" + } + ], + "return_type": null, + "visibility": "private" + }, + { + "description": "包装菜单点击事件处理器,阻止冒泡并在执行后关闭菜单", + "interface_type": "function", + "name": "wrapMenuPressHandler", + "parameters": [ + { + "description": "原始菜单项点击处理器", + "is_optional": false, + "name": "handler", + "param_type": "() => void" + } + ], + "return_type": "(e: MouseEvent) => boolean", + "visibility": "private" + } + ], + "responsibilities": [ + "管理上下文菜单的显示与隐藏状态", + "计算并适配上下文菜单在视口中的安全位置", + "拦截右键事件并阻止默认行为", + "提供菜单项点击后的自动关闭机制", + "测量并存储上下文菜单的尺寸用于定位" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "一个用于渲染 Markdown 内容的 Svelte 组件,支持自定义样式和图像渲染器。", + "file_path": "app/src/lib/widgets/Markdown.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "MarkdownProps" + ], + "name": "Markdown.svelte", + "source_summary": "\n\n
\n\t\n
\n\n\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.029411764705882353, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 136, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "component", + "is_external": true, + "line_number": 1, + "name": "@humanspeak/svelte-markdown", + "path": null, + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "./types", + "path": "app/src/lib/widgets/types", + "version": null + }, + { + "dependency_type": "framework", + "is_external": true, + "line_number": 3, + "name": "svelte", + "path": null, + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": 4, + "name": "./MarkdownImg.svelte", + "path": "app/src/lib/widgets/MarkdownImg.svelte", + "version": null + } + ], + "detailed_description": "该组件封装了 '@humanspeak/svelte-markdown' 库,接收一个包含 Markdown 源文本的 `value` 属性,并通过自定义 `renderers` 配置(如使用 `MarkdownImg` 处理图片)来增强渲染能力。它还通过全局 CSS 样式统一了标题、段落、列表、表格和代码块等元素的视觉呈现,确保与应用整体设计语言一致。", + "interfaces": [ + { + "description": "定义传递给 Markdown 组件的属性结构", + "interface_type": "type", + "name": "MarkdownProps", + "parameters": [ + { + "description": "要渲染的 Markdown 源文本", + "is_optional": false, + "name": "value", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "private" + } + ], + "responsibilities": [ + "解析并渲染传入的 Markdown 字符串", + "提供可扩展的 HTML 元素渲染机制(通过 renderers)", + "统一 Markdown 内容的视觉样式以匹配产品设计规范", + "处理图片等内联元素的自定义渲染逻辑" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "渲染文章内容的UI组件,支持HTML和Markdown两种格式。", + "file_path": "app/src/lib/widgets/ArticleRenderWidget.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "ArticleRenderProps", + "ArticleRenderType" + ], + "name": "ArticleRenderWidget.svelte", + "source_summary": "\n\n{#if renderType === 'html'}\n\t
{@html purgedHtml}
\n{:else}\n\t\n{/if}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 0.83, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 39, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "ArticleRenderProps", + "path": "./types", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "ArticleRenderType", + "path": "./types", + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": 3, + "name": "Markdown", + "path": "./Markdown.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 4, + "name": "removeCodeBlockWrapper", + "path": "$lib/utils/text", + "version": null + }, + { + "dependency_type": "api", + "is_external": false, + "line_number": 5, + "name": "featuresApi", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + } + ], + "detailed_description": "该组件用于渲染文章内容,根据输入内容自动判断是HTML还是Markdown格式。若为HTML,则直接插入并绑定容器以监听链接点击;若为Markdown,则通过Markdown子组件进行渲染。在挂载时注册事件监听器,拦截所有a标签的默认跳转行为,并通过featuresApi.open_article_external打开外部链接,确保应用内安全导航。", + "interfaces": [ + { + "description": "定义传递给组件的属性结构", + "interface_type": "type", + "name": "ArticleRenderProps", + "parameters": [ + { + "description": "文章原始内容,支持HTML或Markdown格式", + "is_optional": false, + "name": "value", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "解析并判断文章内容类型(HTML或Markdown)", + "安全渲染HTML内容并防止XSS风险(通过预处理移除代码块包装)", + "拦截内部渲染的链接点击事件并交由API处理外部跳转", + "管理DOM事件生命周期(挂载时添加、卸载时移除监听器)", + "提供一致的文章展示样式与布局" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "应用设置页面,管理主题、LLM配置、启动行为等全局配置项。", + "file_path": "app/src/routes/settings/+page.svelte", + "functions": [ + "switchTheme", + "selectLang", + "onAutoStartUpSwitched", + "onFrequencyUpdateSwitched", + "openGLMGuide", + "updateAppConfig", + "afterAppConfigUpdated", + "createSaveLLMFormAction", + "createLLMSwitcherAction", + "restoreLLMFormOllama", + "restoreLLMFormGLM", + "restoreLLMFormOpenAILike", + "restoreLLMFormPlatform" + ], + "importance_score": 0.8, + "interfaces": [ + "PressuredHandler", + "CheckSwitchedHandler", + "SelectionSelectedHandler" + ], + "name": "+page.svelte", + "source_summary": "\n\n
\n\t
\n\t\t
\n\t\t\t

{$_('settings.label')}

\n\t\t
\n\t\t
\n\t\t{#if !appConfig}\n\t\t\t

{$_('settings.loading')}

\n\t\t{:else}\n\t\t\t
\n\t\t\t\t\n\t\t\t\t{@render SectionHeader($_('settings.section_llm_appearance.label'))}\n\t\t\t\t{@render CheckOption(\n\t\t\t\t\t$_('settings.section_llm_appearance.theme.label'),\n\t\t\t\t\t$_('settings.section_llm_appearance.theme.description'),\n\t\t\t\t\tisDarkModeEnabled,\n\t\t\t\t\tswitchTheme\n\t\t\t\t)}\n\n\t\t\t\t{@render SectionEnd()}\n\t\t\t\t\n\n\t\t\t\t\n\n\t\t\t\t{@render SectionHeader($_('settings.section_llm_provider.label'))}\n\t\t\t\t
\n\t\t\t\t\t

\n\t\t\t\t\t\t{$_('settings.section_llm_provider.tip')}\n\t\t\t\t\t

\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_ollama')}\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\n\t\t\t\t\t\t

\n\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_ollama_tip')}\n\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_ollama_sentence_1')}。\n\t\t\t\t\t\t

\n\t\t\t\t\t\t{#if activedProviderType === 'ollama'}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\n\t\t\t\t\t\t\t{#if llmFormChangedOllama}\n\t\t\t\t\t\t\t\t{@render LLMGroupSavePanel(saveLLMFormOllama, restoreLLMFormOllama)}\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t{/if}\n\t\t\t\t\t
\n\t\t\t\t\t\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_glm')}\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t

\n\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_glm_sentence_1')}\n\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_glm_sentence_2')}。\n\t\t\t\t\t\t

\n\t\t\t\t\t\t{#if activedProviderType === 'glm'}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{#if llmFormChangedGLM}\n\t\t\t\t\t\t\t\t{@render LLMGroupSavePanel(saveLLMFormGLM, restoreLLMFormGLM)}\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t{/if}\n\t\t\t\t\t
\n\t\t\t\t\t\n\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_openai')}\n\t\t\t\t\t\t\t

\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t

\n\t\t\t\t\t\t\t{$_('settings.section_llm_provider.provider_openai_sentence_1')}\n\t\t\t\t\t\t

\n\t\t\t\t\t\t{#if activedProviderType === 'openai'}\n\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t{#if llmFormChangedOpenAILike}\n\t\t\t\t\t\t\t\t{@render LLMGroupSavePanel(saveLLMFormOpenAILike, restoreLLMFormOpenAILike)}\n\t\t\t\t\t\t\t{/if}\n\t\t\t\t\t\t{/if}\n\t\t\t\t\t\n\t\t\t\t\t\n\n\t\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t{@render SectionEnd()}\n\n\t\t\t\t{@render SectionHeader($_('settings.section_llm_instruct.label'))}\n\t\t\t\t{@render SelectOption(\n\t\t\t\t\t$_('settings.section_llm_instruct.lang.label'),\n\t\t\t\t\t$_('settings.section_llm_instruct.lang.description'),\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: $_('settings.section_llm_instruct.lang.as_system'),\n\t\t\t\t\t\t\tvalue: 'system'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: $_('settings.section_llm_instruct.lang.english'),\n\t\t\t\t\t\t\tvalue: 'English'\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tlabel: $_('settings.section_llm_instruct.lang.chinese'),\n\t\t\t\t\t\t\tvalue: 'Chinese'\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tappConfig.llm.instruct.lang,\n\t\t\t\t\tselectLang\n\t\t\t\t)}\n\t\t\t\t{@render SectionEnd()}\n\n\t\t\t\t{@render SectionHeader($_('settings.section_app_behavior.label'))}\n\t\t\t\t{@render CheckOption(\n\t\t\t\t\t$_('settings.section_app_behavior.option_autostart.label'),\n\t\t\t\t\t$_('settings.section_app_behavior.option_autostart.description'),\n\t\t\t\t\tenableAutoStartUp,\n\t\t\t\t\tonAutoStartUpSwitched\n\t\t\t\t)}\n\n\t\t\t\t{@render CheckOption(\n\t\t\t\t\t$_('settings.section_app_behavior.option_scheduled_fetch.label'),\n\t\t\t\t\t$_('settings.section_app_behavior.option_scheduled_fetch.description'),\n\t\t\t\t\tenableFrequencyUpdate,\n\t\t\t\t\tonFrequencyUpdateSwitched\n\t\t\t\t)}\n\n\t\t\t\t{@render SectionEnd()}\n\t\t\t\t{@render SectionHeader($_('settings.section_users_support.label'))}\n\t\t\t\t
\n\t\t\t\t\t{@render LinkButton(\n\t\t\t\t\t\t$_('settings.section_users_support.visit_home'),\n\t\t\t\t\t\t'https://aiqino.netlify.app?s=desktop'\n\t\t\t\t\t)}\n\t\t\t\t\t{@render LinkButton(\n\t\t\t\t\t\t$_('settings.section_users_support.feedback'),\n\t\t\t\t\t\t'https://github.com/sopaco/saga-reader/issues'\n\t\t\t\t\t)}\n\t\t\t\t\t{@render LinkButton(\n\t\t\t\t\t\t$_('settings.section_users_support.blogs'),\n\t\t\t\t\t\t'https://skyron.netlify.app/downloads/'\n\t\t\t\t\t)}\n\t\t\t\t\t{@render LinkButton(\n\t\t\t\t\t\t$_('settings.section_users_support.changelogs'),\n\t\t\t\t\t\t'https://github.com/sopaco/saga-reader/releases'\n\t\t\t\t\t)}\n\t\t\t\t
\n\n\t\t\t\t{@render SectionEnd()}\n\t\t\t\t{@render SectionHeader($_('settings.section_version.label'))}\n\t\t\t\t
\n\t\t\t\t\t\"logo\"\n\t\t\t\t\t
\n\t\t\t\t\t\t

{appName}

\n\t\t\t\t\t\t

\n\t\t\t\t\t\t\t{`${$_('settings.section_version.ver_app')}:${appVersion}`}\n\t\t\t\t\t\t

\n\t\t\t\t\t\t

\n\t\t\t\t\t\t\t{`${$_('settings.section_version.ver_engine')}:${engineVersion}`}\n\t\t\t\t\t\t

\n\t\t\t\t\t\t

\n\t\t\t\t\t\t\t{`${$_('settings.section_version.ver_system')}:${sysPlatform} ${sysVersion}, ${sysArch}, ${sysLocale}`}\n\t\t\t\t\t\t

\n\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\n\t\t{/if}\n\t\n\n\n{#snippet SectionHeader(text: string)}\n\t
\n\t\t
{text}
\n\t
\n{/snippet}\n\n{#snippet CheckOption(\n\tlabel: string,\n\tdescription: string,\n\tchecked: boolean,\n\tonCheckSwitched: CheckSwitchedHandler\n)}\n\t\n\t\t

{label}

\n\t\t\n\t\n\t

{description}

\n{/snippet}\n\n{#snippet SelectOption(\n\tlabel: string,\n\t_description: string,\n\tselections: { value: string; label: string }[],\n\tselectedValue: string,\n\tonSelected: SelectionSelectedHandler\n)}\n\t
\n\t\t

{label}

\n\t\t onSelected((e.target as HTMLSelectElement).value)}\n\t\t>\n\t\t\t{#each selections as s (s.value)}\n\t\t\t\t\n\t\t\t{/each}\n\t\t\n\t
\n{/snippet}\n\n{#snippet SectionEnd()}\n\t
\n{/snippet}\n\n{#snippet LinkButton(label: string, link: string)}\n\t featuresApi.open_article_external(link)}>{label}\n{/snippet}\n\n{#snippet LLMGroupSavePanel(onSave: PressedHandler, onCancel: PressedHandler)}\n\t
\n\t\t
\n{/snippet}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.65, + "coupling_factor": 0.85, + "cyclomatic_complexity": 33.0, + "depth_of_inheritance": 0, + "lines_of_code": 653, + "number_of_classes": 0, + "number_of_functions": 14 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": "@tauri-apps/api/app", + "version": null + }, + { + "dependency_type": "framework", + "is_external": true, + "line_number": 2, + "name": "$app/environment", + "path": "$app/environment", + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 3, + "name": "@tauri-apps/api/app", + "path": "@tauri-apps/api/app", + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 4, + "name": "@tauri-apps/plugin-os", + "path": "@tauri-apps/plugin-os", + "version": null + }, + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 5, + "name": "@tauri-apps/plugin-autostart", + "path": "@tauri-apps/plugin-autostart", + "version": null + }, + { + "dependency_type": "service", + "is_external": false, + "line_number": 6, + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 7, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + }, + { + "dependency_type": "ui", + "is_external": true, + "line_number": 8, + "name": "@skeletonlabs/skeleton-svelte", + "path": "@skeletonlabs/skeleton-svelte", + "version": null + }, + { + "dependency_type": "model", + "is_external": false, + "line_number": 9, + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 10, + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "version": null + }, + { + "dependency_type": "theme", + "is_external": false, + "line_number": 11, + "name": "$lib/themes", + "path": "$lib/themes", + "version": null + } + ], + "detailed_description": "该组件是应用程序的设置中心页面,主要负责展示和管理用户的全局配置。功能包括:1) 主题切换(亮色/暗色模式);2) 多种LLM提供商(Ollama、GLM、OpenAI兼容接口)的配置与激活;3) 应用行为设置如开机自启和后台更新频率;4) 显示应用及系统版本信息。组件通过Tauri插件获取系统环境信息,并利用Svelte的状态管理实现响应式UI更新。所有配置变更均通过`featuresApi`持久化到后端存储。", + "interfaces": [ + { + "description": "表示一个无参数的事件处理函数类型", + "interface_type": "type", + "name": "PressuredHandler", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "复选框状态切换时的回调函数类型", + "interface_type": "type", + "name": "CheckSwitchedHandler", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "下拉选项被选择时的回调函数类型", + "interface_type": "type", + "name": "SelectionSelectedHandler", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "value", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "private" + } + ], + "responsibilities": [ + "管理用户界面主题偏好设置", + "处理多种LLM服务提供商的配置输入与验证", + "协调应用级行为配置(如自动启动、更新策略)", + "展示应用元信息与系统环境详情", + "提供配置变更的保存与还原机制" + ] + }, + { + "code_dossier": { + "code_purpose": "page", + "description": "Svelte页面组件,用于创建或编辑信息源包。通过URL参数判断操作模式(创建/编辑),提供表单输入和保存/取消操作面板。", + "file_path": "app/src/routes/feedsPackage/create_or_edit/+page.svelte", + "functions": [ + "onSave", + "onCancel" + ], + "importance_score": 0.8, + "interfaces": [ + "Mode" + ], + "name": "+page.svelte", + "source_summary": "\n\n{#if loaded}\n\t
\n\t\t\n\t\t{#if submitErrorMessage}\n\t\t\t

\n\t\t\t\t{submitErrorMessage}\n\t\t\t

\n\t\t{:else}\n\t\t\t

\n\t\t\t\t{$_('main.feeds.create_or_edit.tip_footer')}\n\t\t\t

\n\t\t{/if}\n\n\t\t\n\t
\n{/if}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 8.0, + "cyclomatic_complexity": 6.0, + "depth_of_inheritance": 0, + "lines_of_code": 90, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": null, + "version": null + }, + { + "dependency_type": "framework", + "is_external": false, + "line_number": 2, + "name": "$app/environment", + "path": null, + "version": null + }, + { + "dependency_type": "desktop", + "is_external": true, + "line_number": 3, + "name": "@tauri-apps/api/window", + "path": null, + "version": null + }, + { + "dependency_type": "ui_component", + "is_external": false, + "line_number": 4, + "name": "$lib/widgets/SaveOperatePanel.svelte", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 5, + "name": "$lib/utils/text", + "path": null, + "version": null + }, + { + "dependency_type": "api_client", + "is_external": false, + "line_number": 6, + "name": "$lib/hybrid-apis/feed/impl", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 7, + "name": "$lib/utils/id", + "path": null, + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 8, + "name": "$lib/utils/dom", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是SvelteKit路由驱动的前端页面,负责渲染创建或编辑信息源包的UI界面。组件根据URL中的查询参数动态设置模式(create/edit)、ID、名称及回调事件ID。在浏览器环境中解析参数并初始化状态。用户输入包名后,通过`onSave`调用底层API执行添加或重命名操作,并通过Tauri的窗口系统触发回调事件后关闭窗口。`onCancel`则直接关闭窗口而不保存。界面包含输入验证、错误提示和操作面板,支持国际化文本显示。", + "interfaces": [ + { + "description": "定义页面操作模式的联合类型,支持'create'和'edit'两种状态", + "interface_type": "type", + "name": "Mode", + "parameters": [], + "return_type": null, + "visibility": "private" + }, + { + "description": "处理保存操作:创建时调用add_feeds_package添加新包;编辑时调用rename_feeds_package修改名称", + "interface_type": "function", + "name": "onSave", + "parameters": [], + "return_type": "Promise", + "visibility": "public" + } + ], + "responsibilities": [ + "解析URL参数初始化页面状态", + "提供信息源包名称的输入与验证功能", + "调用API实现创建或编辑信息源包的业务逻辑", + "通过Tauri窗口系统处理跨进程通信与窗口关闭", + "展示操作结果反馈与错误提示信息" + ] + }, + { + "code_dossier": { + "code_purpose": "page", + "description": "关于页面的Svelte组件,展示应用名称、版本信息及引擎版本,并提供访问官网按钮。", + "file_path": "app/src/routes/about/+page.svelte", + "functions": [ + "onVisitHome" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "+page.svelte", + "source_summary": "\n\n\n\t
\n\t\t\"logo\"\n\t\t

{appName}

\n\t\t

{`${$_('about.ver_app')}:${appVersion}`}

\n\t\t

{`${$_('about.ver_engine')}:${engineVersion}`}

\n\t\t{$_('about.visit_home')}\n\t\t
\n\t
\n\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 5.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 37, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 2, + "name": "svelte-i18n", + "path": null, + "version": null + }, + { + "dependency_type": "api", + "is_external": true, + "line_number": 3, + "name": "@tauri-apps/api/app", + "path": null, + "version": null + }, + { + "dependency_type": "service", + "is_external": false, + "line_number": 4, + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "framework", + "is_external": false, + "line_number": 5, + "name": "$app/environment", + "path": "$app/environment", + "version": null + }, + { + "dependency_type": "util", + "is_external": false, + "line_number": 6, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + } + ], + "detailed_description": "该组件是SvelteKit路由系统中的一个页面组件(+page.svelte),用于渲染应用的'关于'页面。在浏览器环境中,它异步获取应用名称、应用版本和Tauri运行时版本,并通过$state响应式变量更新UI。界面包含应用logo、名称、版本信息以及一个跳转到主页的按钮。右键菜单被禁用以提升用户体验一致性。", + "interfaces": [], + "responsibilities": [ + "展示应用元信息(名称、版本)", + "加载并显示Tauri引擎版本", + "提供外部链接入口(官网访问)", + "管理页面级UI交互逻辑", + "防止右键上下文菜单弹出" + ] + }, + { + "code_dossier": { + "code_purpose": "page", + "description": "Svelte页面组件,用于创建或编辑订阅源的表单界面。支持两种模式:创建和编辑。根据选择的数据获取方式(scrap/rss)动态调整输入字段标签和占位符,并通过Tauri API与主窗口通信完成保存操作。", + "file_path": "app/src/routes/feeds/create_or_edit/+page.svelte", + "functions": [ + "onSave", + "onCancel" + ], + "importance_score": 0.8, + "interfaces": [ + "formErrorName", + "formErrorFetcherId", + "formErrorData", + "canSave", + "formLabelData", + "formInputPlaceHolderData" + ], + "name": "+page.svelte", + "source_summary": "\n\n{#if loaded}\n\t
\n\t\t\n\n\t\t\n\n\t\t\n\n\t\t{#if submitErrorMessage}\n\t\t\t

\n\t\t\t\t{submitErrorMessage}\n\t\t\t

\n\t\t{:else}\n\t\t\t

\n\t\t\t {$_('main.feed.create_or_edit.tip_footer')}\n\t\t\t

\n\t\t{/if}\n\n\t\t\n\t
\n{/if}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.75, + "coupling_factor": 9.0, + "cyclomatic_complexity": 10.0, + "depth_of_inheritance": 0, + "lines_of_code": 136, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + }, + { + "dependency_type": "framework", + "is_external": false, + "line_number": 2, + "name": "$app/environment", + "path": "$app/environment", + "version": null + }, + { + "dependency_type": "native_api", + "is_external": true, + "line_number": 3, + "name": "@tauri-apps/api/window", + "path": "@tauri-apps/api/window", + "version": null + }, + { + "dependency_type": "component", + "is_external": false, + "line_number": 4, + "name": "$lib/widgets/SaveOperatePanel.svelte", + "path": "$lib/widgets/SaveOperatePanel.svelte", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 5, + "name": "$lib/utils/text", + "path": "$lib/utils/text", + "version": null + }, + { + "dependency_type": "api_client", + "is_external": false, + "line_number": 6, + "name": "$lib/hybrid-apis/feed/impl", + "path": "$lib/hybrid-apis/feed/impl", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 7, + "name": "$lib/utils/id", + "path": "$lib/utils/id", + "version": null + }, + { + "dependency_type": "type_definition", + "is_external": false, + "line_number": 8, + "name": "$lib/hybrid-apis/feed/types", + "path": "$lib/hybrid-apis/feed/types", + "version": null + }, + { + "dependency_type": "utility", + "is_external": false, + "line_number": 9, + "name": "$lib/utils/dom", + "path": "$lib/utils/dom", + "version": null + } + ], + "detailed_description": "该组件是SvelteKit路由系统中的一个页面级组件,负责渲染‘创建/编辑’订阅源的UI表单。组件初始化时从URL参数中读取当前操作模式(mode)、ID、名称、数据等信息并填充到表单中。提供两个主要交互函数:onSave用于提交更改并关闭窗口,onCancel取消操作。表单包含名称输入、抓取类型选择及对应数据输入框,其标签和提示文本根据所选fetcher类型动态变化。错误提示机制确保必填项非空,且仅在所有验证通过后才允许保存。最终通过Tauri的window.emit向父窗口发送回调事件以通知结果。", + "interfaces": [ + { + "description": "计算属性:判断feed名称是否为空", + "interface_type": "derived_state", + "name": "formErrorName", + "parameters": [], + "return_type": "boolean", + "visibility": "private" + }, + { + "description": "计算属性:判断抓取器ID是否为空", + "interface_type": "derived_state", + "name": "formErrorFetcherId", + "parameters": [], + "return_type": "boolean", + "visibility": "private" + }, + { + "description": "计算属性:判断数据内容是否为空", + "interface_type": "derived_state", + "name": "formErrorData", + "parameters": [], + "return_type": "boolean", + "visibility": "private" + }, + { + "description": "计算属性:综合判断是否可执行保存操作", + "interface_type": "derived_state", + "name": "canSave", + "parameters": [], + "return_type": "boolean", + "visibility": "private" + }, + { + "description": "根据当前fetcher_id动态生成数据输入框的标签文本", + "interface_type": "derived_state", + "name": "formLabelData", + "parameters": [], + "return_type": "string", + "visibility": "private" + }, + { + "description": "根据当前fetcher_id动态生成数据输入框的占位符文本", + "interface_type": "derived_state", + "name": "formInputPlaceHolderData", + "parameters": [], + "return_type": "string", + "visibility": "private" + } + ], + "responsibilities": [ + "解析URL参数初始化表单数据", + "管理创建/编辑两种模式下的状态逻辑", + "实现表单输入验证与动态UI更新", + "处理保存和取消操作并与宿主窗口通信", + "提供国际化文本支持与用户反馈" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "定义了两个全局通知toaster实例,用于在应用不同位置显示提示信息", + "file_path": "app/src/routes/main/stores/toast.ts", + "functions": [], + "importance_score": 0.8, + "interfaces": [], + "name": "toast.ts", + "source_summary": "import { createToaster } from '@skeletonlabs/skeleton-svelte';\n\nexport const globalToaster = createToaster({\n\tplacement: 'bottom-end',\n\toffsets: '30px'\n});\nexport const spriteToaster = createToaster({\n\tplacement: 'bottom-start',\n\toffsets: '128px'\n});\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 10, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "@skeletonlabs/skeleton-svelte", + "path": null, + "version": null + } + ], + "detailed_description": "该组件使用Skeleton框架的createToaster函数创建了两个预配置的toaster实例:globalToaster位于屏幕右下角,偏移30px;spriteToaster位于屏幕左下角,偏移128px。这两个实例可在应用任何地方导入使用,实现一致性的通知展示体验。", + "interfaces": [], + "responsibilities": [ + "提供全局通知服务实例", + "预配置toaster显示位置和偏移量", + "封装第三方通知库的初始化逻辑", + "确保通知样式和行为的一致性" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "实现文章搜索状态管理的Svelte store,用于维护过滤文本和激活状态。", + "file_path": "app/src/routes/main/stores/articles/search/index.svelte.ts", + "functions": [ + "create" + ], + "importance_score": 0.8, + "interfaces": [ + "StoreType" + ], + "name": "index.svelte.ts", + "source_summary": "type StoreType = {\n\tfilterText: string;\n\tisFilterActived: boolean;\n};\n\nfunction create(): StoreType {\n\tlet filterText = $state('');\n\tconst isFilterActived = $derived(filterText != '');\n\n\treturn {\n\t\tget filterText() {\n\t\t\treturn filterText;\n\t\t},\n\t\tset filterText(value) {\n\t\t\tfilterText = value;\n\t\t},\n\t\tget isFilterActived() {\n\t\t\treturn isFilterActived;\n\t\t}\n\t};\n}\n\nexport type { StoreType };\nexport { create };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 24, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [], + "detailed_description": "该组件定义了一个基于Svelte的响应式store,用于管理文章列表的搜索与过滤状态。其核心是`StoreType`类型和`create`工厂函数。`filterText`是一个可读写的响应式状态,表示当前输入的搜索关键词;`isFilterActived`是一个派生状态,当`filterText`非空时自动为true,表示过滤功能已激活。通过getter/setter封装了对`filterText`的访问,保证了状态的响应式更新,同时对外暴露只读的`isFilterActived`。此store设计简洁,符合Svelte的状态管理范式,专为UI层的搜索交互提供支持。", + "interfaces": [ + { + "description": "定义了文章搜索store的结构,包含filterText和isFilterActived两个属性。", + "interface_type": "type", + "name": "StoreType", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "工厂函数,用于创建并返回一个新的StoreType实例。", + "interface_type": "function", + "name": "create", + "parameters": [], + "return_type": "StoreType", + "visibility": "public" + } + ], + "responsibilities": [ + "创建并初始化文章搜索相关的响应式状态", + "管理用户输入的搜索过滤文本", + "提供计算属性以判断当前过滤器是否处于激活状态", + "封装状态逻辑,为Svelte组件提供类型安全的store接口" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "文章管理模块的状态容器工厂,协调搜索与列表子模块的创建和依赖注入。", + "file_path": "app/src/routes/main/stores/articles/index.svelte.ts", + "functions": [ + "create" + ], + "importance_score": 0.8, + "interfaces": [], + "name": "index.svelte.ts", + "source_summary": "import { create as createSearch } from './search/index.svelte';\nimport { create as createList } from './list/index.svelte';\nimport type { StoreType as TasksStoreType } from '../tasks.svelte';\n\nexport function create(tasks: TasksStoreType) {\n\tconst search = createSearch();\n\tconst list = createList({\n\t\ttasks,\n\t\tsearch\n\t});\n\n\treturn {\n\t\tsearch,\n\t\tlist\n\t};\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.92, + "coupling_factor": 0.375, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 16, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "function", + "is_external": false, + "line_number": 1, + "name": "createSearch", + "path": "./search/index.svelte", + "version": null + }, + { + "dependency_type": "function", + "is_external": false, + "line_number": 2, + "name": "createList", + "path": "./list/index.svelte", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 3, + "name": "TasksStoreType", + "path": "../tasks.svelte", + "version": null + } + ], + "detailed_description": "该组件作为文章管理功能的核心状态管理协调器,负责初始化并组合两个关键子模块:搜索(search)和列表(list)。通过依赖注入的方式接收来自任务模块(tasks)的状态存储,并将其与本地创建的搜索状态一起传递给列表模块,实现跨模块状态联动。采用工厂函数模式返回结构化的状态对象,便于上层组件解构使用。", + "interfaces": [], + "responsibilities": [ + "初始化文章搜索状态管理模块", + "初始化文章列表状态管理模块并注入依赖", + "协调tasks、search与list三者之间的状态依赖关系", + "提供统一的工厂接口创建复合状态结构" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义了应用上下文的状态结构,用于在Svelte组件之间共享当前选中的Feed和文章信息。", + "file_path": "app/src/routes/main/stores/context.ts", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "IContext" + ], + "name": "context.ts", + "source_summary": "import type { Article } from '$lib/types/article';\n\ninterface IContext {\n\tcurrentFeedId: string | undefined;\n\tcurrentArticle: Article | null;\n}\n\nexport type { IContext };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 1.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 8, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "type import", + "is_external": false, + "line_number": 1, + "name": "$lib/types/article", + "path": "app/src/lib/types/article", + "version": null + } + ], + "detailed_description": "该组件定义了一个名为 IContext 的接口,用于描述应用程序的全局状态上下文。它包含两个字段:currentFeedId(表示当前激活的订阅源ID,可选)和 currentArticle(表示当前查看的文章内容,可为 null)。此类型主要用于 Svelte 的 context API 中,以便在嵌套组件树中安全地传递状态,避免通过 props 层层透传。该文件仅提供类型定义,不包含运行时逻辑,属于纯类型声明模块。", + "interfaces": [ + { + "description": "描述主界面中组件共享的状态上下文结构", + "interface_type": "interface", + "name": "IContext", + "parameters": [ + { + "description": "当前选中的 Feed 的唯一标识符,可能未设置", + "is_optional": false, + "name": "currentFeedId", + "param_type": "string | undefined" + }, + { + "description": "当前显示的文章对象,若无则为 null", + "is_optional": false, + "name": "currentArticle", + "param_type": "Article | null" + } + ], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "定义应用级上下文的数据结构", + "提供跨组件通信的类型安全支持", + "管理当前 Feed 和文章的引用状态", + "支持 Svelte Context API 的类型推导" + ] + }, + { + "code_dossier": { + "code_purpose": "controller", + "description": "实现一个响应式加载状态管理器,用于跟踪操作的加载、完成、错误等状态,并提供可读的状态文本。", + "file_path": "app/src/routes/main/stores/loading.svelte.ts", + "functions": [ + "create" + ], + "importance_score": 0.8, + "interfaces": [ + "StoreType", + "Status" + ], + "name": "loading.svelte.ts", + "source_summary": "type StoreType = {\n\tunset: () => void;\n\tload: () => void;\n\tcomplete: () => void;\n\terror: (e: Error) => void;\n\tstatus: Status;\n\tstatusText: string;\n};\n\nenum Status {\n\tUnset,\n\tLoading,\n\tCompleted,\n\tError\n}\n\nfunction create(initStatus = Status.Unset): StoreType {\n\tlet status: Status = $state(initStatus);\n\n\tfunction unset() {\n\t\tstatus = Status.Unset;\n\t}\n\n\tfunction load() {\n\t\tstatus = Status.Loading;\n\t}\n\n\tfunction error(e: Error) {\n\t\tconsole.error('LoadingStore state error', e);\n\t\tstatus = Status.Error;\n\t}\n\n\tfunction complete() {\n\t\tstatus = Status.Completed;\n\t}\n\n\treturn {\n\t\tunset,\n\t\tload,\n\t\terror,\n\t\tcomplete,\n\t\tget status() {\n\t\t\treturn status;\n\t\t},\n\t\tget statusText() {\n\t\t\tswitch (status) {\n\t\t\t\tcase Status.Unset:\n\t\t\t\t\treturn '未设定状态';\n\t\t\t\tcase Status.Loading:\n\t\t\t\t\treturn '执行中';\n\t\t\t\tcase Status.Completed:\n\t\t\t\t\treturn '完成';\n\t\t\t\tcase Status.Error:\n\t\t\t\t\treturn '错误';\n\t\t\t}\n\t\t}\n\t};\n}\n\nexport type { StoreType };\nexport { Status, create };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.0, + "cyclomatic_complexity": 5.0, + "depth_of_inheritance": 0, + "lines_of_code": 61, + "number_of_classes": 0, + "number_of_functions": 5 + }, + "dependencies": [], + "detailed_description": "该组件定义了一个基于Svelte状态管理机制的加载状态存储(Loading Store),通过`create`函数返回一个包含加载控制方法和只读状态属性的对象。支持四种状态:未设定(Unset)、加载中(Loading)、已完成(Completed)和错误(Error)。每个状态变更都会触发UI更新,且提供了`statusText`计算属性以返回对应状态的人性化中文描述,适用于前端界面中的加载提示展示。", + "interfaces": [ + { + "description": "定义加载状态store的公开接口,包括控制方法和状态访问器", + "interface_type": "type", + "name": "StoreType", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "表示加载过程中的不同状态枚举值", + "interface_type": "enum", + "name": "Status", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "创建并返回一个新的加载状态store实例", + "interface_type": "function", + "name": "create", + "parameters": [ + { + "description": "初始状态,默认为Status.Unset", + "is_optional": true, + "name": "initStatus", + "param_type": "Status" + } + ], + "return_type": "StoreType", + "visibility": "public" + } + ], + "responsibilities": [ + "管理异步操作的加载状态生命周期", + "提供统一的加载状态变更接口(load/unset/complete/error)", + "暴露可读的状态码与人类可读的状态文本映射", + "实现响应式状态更新以支持Svelte组件绑定" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "一个Svelte前端UI组件,用于在阅读器为空时显示提示信息。", + "file_path": "app/src/routes/main/widgets/ReaderBlankIndicator.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "i18n $_" + ], + "name": "ReaderBlankIndicator.svelte", + "source_summary": "\n\n
\n\t
\n\t\t
{$_('reader.blank_tip_0')}
\n\t\t{$_('reader.blank_tip_1')}\n\t\t{$_('reader.blank_tip_2')}\n\t\t{$_('reader.blank_tip_3')}\n\t
\n
\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 12, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 2, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + } + ], + "detailed_description": "该组件是一个轻量级的Svelte UI组件,用于在阅读器内容为空时向用户提供视觉提示。它通过使用svelte-i18n库实现国际化文本渲染,展示四条依次排列的提示语句,引导用户理解当前状态。布局采用Flexbox垂直居中,并设置默认光标样式以表明其不可交互性。", + "interfaces": [ + { + "description": "来自svelte-i18n的翻译函数,用于动态获取本地化字符串", + "interface_type": "function", + "name": "$_", + "parameters": [ + { + "description": "国际化键值", + "is_optional": false, + "name": "key", + "param_type": "string" + } + ], + "return_type": "string", + "visibility": "external" + } + ], + "responsibilities": [ + "在阅读器无内容时展示空白状态提示", + "支持多语言环境下的提示文本渲染", + "提供清晰的用户体验引导", + "保持简洁美观的UI布局结构" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": null, + "file_path": "app/src/routes/main/widgets/FeedsPanel.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [], + "name": "FeedsPanel.svelte", + "source_summary": "" + }, + "complexity_metrics": { + "cohesion_score": 0.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 0, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件源代码为空,未实现任何功能。理论上应作为信息流展示面板的UI容器,但当前无实际逻辑或结构。", + "interfaces": [], + "responsibilities": [ + "占位组件:暂时作为FeedsPanel的UI占位符", + "待实现职责:信息流数据展示", + "待实现职责:用户交互响应(如刷新、筛选)" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": null, + "file_path": "app/src/routes/main/widgets/FeedEditPanel.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [], + "name": "FeedEditPanel.svelte", + "source_summary": "" + }, + "complexity_metrics": { + "cohesion_score": 0.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 0, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件的源代码为空,未实现任何功能。理论上作为Feed编辑面板,应提供内容输入、格式化、提交等交互能力,但当前版本为空白组件。", + "interfaces": [], + "responsibilities": [ + "占位符:待实现Feed内容编辑功能", + "占位符:待实现用户输入处理逻辑", + "占位符:待集成表单验证机制" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "搜索栏组件,支持绑定过滤文本并条件显示刷新按钮。", + "file_path": "app/src/routes/main/widgets/SearchBar.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [ + "SearchBarProps" + ], + "name": "SearchBar.svelte", + "source_summary": "\n\n
\n\t\n\t{#if !articles_store.isFeedSpecified}\n\t\t\n\t\t\t\n\t\t\n\t{/if}\n
\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.5, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 26, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "SearchBarProps", + "path": "./types", + "version": null + }, + { + "dependency_type": "component", + "is_external": true, + "line_number": 3, + "name": "IconRefresh", + "path": "lucide-svelte/icons/refresh-cw", + "version": null + } + ], + "detailed_description": "该组件是一个Svelte编写的前端UI组件,用于实现主界面中的搜索功能。它接收一个包含store和articles_store的SearchBarProps类型属性,其中store用于双向绑定输入框的filterText字段,实现搜索关键词的实时同步;articles_store.isFeedSpecified用于判断是否指定了数据源,若未指定则显示刷新按钮,允许用户手动触发feeds更新操作。国际化通过svelte-i18n的$_函数实现占位符翻译。", + "interfaces": [ + { + "description": "定义SearchBar组件所需传入的属性结构", + "interface_type": "type", + "name": "SearchBarProps", + "parameters": [ + { + "description": "包含filterText的状态对象,用于双向绑定搜索输入", + "is_optional": false, + "name": "store", + "param_type": "any" + }, + { + "description": "文章数据管理对象,提供isFeedSpecified状态及updateFeeds方法", + "is_optional": false, + "name": "articles_store", + "param_type": "ArticlesStore" + } + ], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "提供用户可输入的搜索框界面元素", + "将用户的输入实时同步到外部store中进行过滤处理", + "根据数据源状态决定是否显示刷新按钮", + "支持多语言占位符文本展示", + "封装样式与交互逻辑以复用在主页面中" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": null, + "file_path": "app/src/routes/main/widgets/FeedPackageEditPanel.svelte", + "functions": [], + "importance_score": 0.8, + "interfaces": [], + "name": "FeedPackageEditPanel.svelte", + "source_summary": "" + }, + "complexity_metrics": { + "cohesion_score": 0.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 0, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件为空文件,无任何代码实现。预期应为一个用于编辑信息流包(Feed Package)的前端UI面板,但当前未定义任何逻辑、结构或交互。", + "interfaces": [], + "responsibilities": [ + "占位组件:目前仅作为路径存在,无实际职责", + "待实现功能:预计承担信息流包的配置与编辑界面展示", + "用户交互处理:未来可能包含表单输入、数据绑定和提交操作" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "Vite构建工具的配置文件,用于SvelteKit应用的开发和构建设置", + "file_path": "app/vite.config.ts", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "vite.config.ts", + "source_summary": "import { defineConfig } from 'vite';\nimport tailwindcss from '@tailwindcss/vite';\nimport { sentrySvelteKit } from '@sentry/sveltekit';\nimport { sveltekit } from '@sveltejs/kit/vite';\n\nconst host = process.env.TAURI_DEV_HOST;\n\n// https://vitejs.dev/config/\nexport default defineConfig(async () => ({\n\tplugins: [\n\t\ttailwindcss(),\n\t\tsentrySvelteKit({\n\t\t\tsourceMapsUploadOptions: {\n\t\t\t\torg: 'sopaco',\n\t\t\t\tproject: 'qino-feed-client-interactive',\n\t\t\t\tauthToken:\n\t\t\t\t\t'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',\n\t\t\t\ttelemetry: false\n\t\t\t}\n\t\t}),\n\t\tsveltekit()\n\t],\n\n\t// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`\n\t//\n\t// 1. prevent vite from obscuring rust errors\n\tclearScreen: false,\n\t// 2. tauri expects a fixed port, fail if that port is not available\n\tserver: {\n\t\tport: 1420,\n\t\tstrictPort: true,\n\t\thost: host || false,\n\t\thmr: host\n\t\t\t? {\n\t\t\t\t\tprotocol: 'ws',\n\t\t\t\t\thost,\n\t\t\t\t\tport: 1421\n\t\t\t\t}\n\t\t\t: undefined,\n\t\twatch: {\n\t\t\t// 3. tell vite to ignore watching `src-tauri`\n\t\t\tignored: ['**/src-tauri/**']\n\t\t}\n\t},\n\n\toptimizeDeps: { exclude: ['fsevents'] }\n}));\n" + }, + "complexity_metrics": { + "cohesion_score": 0.72, + "coupling_factor": 0.85, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 47, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "vite", + "path": "vite", + "version": null + }, + { + "dependency_type": "import", + "is_external": true, + "line_number": 2, + "name": "@tailwindcss/vite", + "path": "@tailwindcss/vite", + "version": null + }, + { + "dependency_type": "@sentry/sveltekit", + "is_external": true, + "line_number": 3, + "name": "@sentry/sveltekit", + "path": "@sentry/sveltekit", + "version": null + }, + { + "dependency_type": "import", + "is_external": true, + "line_number": 4, + "name": "@sveltejs/kit/vite", + "path": "@sveltejs/kit/vite", + "version": null + } + ], + "detailed_description": "该组件是Vite构建系统的配置文件,专为SvelteKit框架设计。它定义了开发服务器行为、插件集成(Tailwind CSS、Sentry错误监控、SvelteKit支持)、热更新机制以及针对Tauri桌面应用环境的特殊配置。通过异步方式导出配置对象,支持条件性地根据TAURI_DEV_HOST环境变量调整HMR连接协议和主机地址。同时排除了fsevents依赖的预优化,避免在非macOS系统上出现问题。", + "interfaces": [], + "responsibilities": [ + "配置Vite开发服务器端口及HMR热重载行为", + "集成Tailwind CSS、Sentry和SvelteKit等核心构建插件", + "适配Tauri桌面应用的开发环境需求", + "优化依赖处理以提升构建性能", + "管理环境变量驱动的条件性配置逻辑" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义LLM服务所需的核心数据模型与接口契约,包含AI生成参数配置和Completion服务抽象。", + "file_path": "crates/llm/src/providers/types.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "CompletionService" + ], + "name": "types.rs", + "source_summary": "use serde::{Deserialize, Serialize};\n\n#[derive(Serialize, Deserialize, Clone)]\npub struct AITargetOption {\n pub temperature: Option,\n pub seed: Option,\n pub top_k: Option,\n pub top_p: Option,\n pub num_ctx: Option,\n}\n\nimpl Default for AITargetOption {\n fn default() -> Self {\n AITargetOption {\n temperature: Some(0.0),\n seed: Some(0),\n top_k: Some(40),\n top_p: Some(0.9),\n num_ctx: Some(4096),\n }\n }\n}\n\n/// LLM Generate服务代理\npub trait CompletionService {\n /// 调用LLM Completion能力,参数`message`会被作为user prompt传递给LLM。\n fn completion(&self, message: String) -> impl std::future::Future>;\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.5, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 28, + "number_of_classes": 1, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": true, + "line_number": 1, + "name": "serde", + "path": null, + "version": null + } + ], + "detailed_description": "该组件定义了两个核心结构:AITargetOption 和 CompletionService。AITargetOption 是一个可序列化的配置结构体,用于封装 LLM 生成过程中的关键参数(如 temperature、top_p、top_k 等),并实现了 Default trait 提供默认值,便于在不同场景下统一行为。CompletionService 是一个异步 trait,抽象了 LLM 的文本生成能力,要求实现者提供一个返回 Future 的 completion 方法,支持异步调用模式,符合现代 Rust 异步编程范式。整体设计简洁,聚焦于类型安全与接口抽象,服务于上层 LLM 调用逻辑。", + "interfaces": [ + { + "description": "LLM Generate服务代理,用于调用语言模型的completion能力。", + "interface_type": "trait", + "name": "CompletionService", + "parameters": [ + { + "description": "用户输入的提示信息,将作为prompt传递给LLM", + "is_optional": false, + "name": "message", + "param_type": "String" + } + ], + "return_type": "impl std::future::Future>", + "visibility": "pub" + } + ], + "responsibilities": [ + "定义AI生成任务的参数配置模型", + "为LLM Completion能力提供统一的异步接口契约", + "确保配置项的可序列化与反序列化支持", + "提供合理的默认参数设置以降低使用复杂度", + "支持跨平台或服务间的数据交换格式兼容性" + ] + }, + { + "code_dossier": { + "code_purpose": "router", + "description": "该模块作为LLM提供者功能的内部路由与组织单元,集中声明了多个子模块,用于管理不同LLM服务(如Mistral、Ollama、GLM、OpenAI兼容等)的实现。", + "file_path": "crates/llm/src/providers/mod.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "mod.rs", + "source_summary": "pub(crate) mod llm_mistral;\npub(crate) mod llm_ollama;\npub(crate) mod llm_platform;\npub mod types;\npub(crate) mod llm_glm;\npub(crate) mod llm_openaibase_like;" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 6.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 6, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": 1, + "name": "llm_mistral", + "path": "crates/llm/src/providers/llm_mistral/mod.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 2, + "name": "llm_ollama", + "path": "crates/llm/src/providers/llm_ollama/mod.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "llm_platform", + "path": "crates/llm/src/providers/llm_platform/mod.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 4, + "name": "types", + "path": "crates/llm/src/providers/types/mod.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 5, + "name": "llm_glm", + "path": "crates/llm/src/providers/llm_glm/mod.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 6, + "name": "llm_openaibase_like", + "path": "crates/llm/src/providers/llm_openaibase_like/mod.rs", + "version": null + } + ], + "detailed_description": "该文件是Rust项目中`llm` crate下`providers`目录的模块定义文件(mod.rs),其主要作用是将多个具体的LLM提供商实现模块进行聚合和可见性控制。通过`pub(crate) mod`语法,它将`llm_mistral`、`llm_ollama`、`llm_platform`、`llm_glm`、`llm_openaibase_like`等私有于crate内的子模块引入当前命名空间,同时将`types`模块设为公共以供外部使用。此文件本身不包含具体业务逻辑或函数实现,而是承担模块组织和封装职责,形成清晰的代码结构层次。", + "interfaces": [], + "responsibilities": [ + "聚合所有LLM提供商的子模块,形成统一的模块入口", + "控制各子模块在crate内的可见性(通过pub(crate))", + "暴露公共类型接口(types模块)以便其他模块复用", + "维护LLM providers层级的命名空间结构" + ] + }, + { + "code_dossier": { + "code_purpose": "agent", + "description": "LLM功能的核心模块聚合器,提供统一的接口访问入口。", + "file_path": "crates/llm/src/lib.rs", + "functions": [ + "pub mod llm_agent", + "mod connector", + "pub mod providers" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "lib.rs", + "source_summary": "pub mod llm_agent;\nmod connector;\npub mod providers;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.8, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 3, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "connector", + "path": "./crates/llm/src/connector.rs", + "version": null + } + ], + "detailed_description": "该组件作为LLM(大语言模型)功能的顶层模块聚合器,主要职责是组织和导出子模块。它公开了`llm_agent`和`providers`模块供外部使用,同时私有引入`connector`模块用于内部HTTP客户端管理。整体结构遵循Rust的模块化设计原则,通过合理的可见性控制实现关注点分离。", + "interfaces": [], + "responsibilities": [ + "聚合LLM相关功能模块", + "定义公共API边界", + "管理内部模块依赖关系", + "提供统一的功能导出入口" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "创建并配置用于HTTP请求的reqwest客户端,支持超时和压缩。", + "file_path": "crates/llm/src/connector.rs", + "functions": [ + "new" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "connector.rs", + "source_summary": "use std::time::Duration;\n\nuse reqwest::Client;\n\npub(crate) fn new() -> anyhow::Result {\n Ok(\n Client::builder()\n .timeout(Duration::from_secs(60))\n .gzip(true)\n .deflate(true)\n .build()?\n )\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 2.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 13, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 1, + "name": "std::time::Duration", + "path": null, + "version": null + }, + { + "dependency_type": "third_party", + "is_external": true, + "line_number": 3, + "name": "reqwest::Client", + "path": null, + "version": null + } + ], + "detailed_description": "该组件负责构建一个预配置的reqwest HTTP客户端实例,用于后续的网络请求操作。当前配置包括60秒的全局超时、启用Gzip和Deflate压缩算法以优化传输效率。此客户端通常被LLM相关模块用于调用远程API服务。", + "interfaces": [], + "responsibilities": [ + "初始化HTTP客户端实例", + "设置合理的请求超时策略", + "启用响应内容压缩支持", + "提供可复用的客户端构造方法" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": "定义了feed_api_rs库的模块结构,导出核心功能模块供外部使用。", + "file_path": "crates/feed_api_rs/src/lib.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "lib.rs", + "source_summary": "pub mod application_context;\npub mod features;\npub mod startup;\nmod utils;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.25, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 4, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "internal", + "is_external": false, + "line_number": null, + "name": "utils", + "path": "./crates/feed_api_rs/src/utils.rs", + "version": null + } + ], + "detailed_description": "该组件是feed_api_rs库的根模块,通过pub mod声明导出了application_context、features和startup三个公共模块,同时包含一个私有的utils模块。它主要起到组织和封装内部模块的作用,为外部用户提供统一的模块访问入口。其职责在于构建清晰的模块化结构,便于代码维护和功能扩展。", + "interfaces": [], + "responsibilities": [ + "组织和管理feed_api_rs库的模块结构", + "提供公共模块的导出接口", + "封装内部工具模块(utils)", + "作为库的入口点协调各子模块关系", + "维护模块间的可见性控制" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "定义应用程序上下文结构及其宿主访问机制,用于在系统各组件间共享配置信息。", + "file_path": "crates/feed_api_rs/src/application_context.rs", + "functions": [ + "new", + "get_context", + "copy_context" + ], + "importance_score": 0.6, + "interfaces": [ + "ContextHost" + ], + "name": "application_context.rs", + "source_summary": "use types::{AppConfig, UserConfig};\n\n// const version: &str = env!(\"CARGO_PKG_VERSION\");\n\n#[derive(Clone)]\npub struct ApplicationContext {\n pub app_config: AppConfig,\n pub user_config: UserConfig,\n}\n\npub struct ContextHostWrapper {\n context: ApplicationContext,\n}\n\npub trait ContextHost {\n fn new(context: ApplicationContext) -> Self;\n\n fn get_context(&self) -> &ApplicationContext;\n\n fn copy_context(&self) -> ApplicationContext;\n}\n\nimpl ContextHost for ContextHostWrapper {\n fn new(context: ApplicationContext) -> Self {\n ContextHostWrapper { context }\n }\n\n fn get_context(&self) -> &ApplicationContext {\n &self.context\n }\n\n fn copy_context(&self) -> ApplicationContext {\n self.context.clone()\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.1, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 35, + "number_of_classes": 2, + "number_of_functions": 3 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": 1, + "name": "types", + "path": "types", + "version": null + } + ], + "detailed_description": "该组件定义了 `ApplicationContext` 结构体,用于封装应用运行所需的核心配置(AppConfig 和 UserConfig)。通过 `ContextHost` trait 提供统一的上下文访问契约,允许系统中的其他组件以一致的方式获取和复制上下文实例。`ContextHostWrapper` 是该 trait 的具体实现,包装了一个 `ApplicationContext` 实例并提供安全的访问方法。整体设计支持上下文的不可变共享与克隆,适用于多模块协作场景。", + "interfaces": [ + { + "description": "定义上下文宿主的行为契约,确保所有宿主实现都能提供对 ApplicationContext 的访问能力。", + "interface_type": "trait", + "name": "ContextHost", + "parameters": [ + { + "description": "初始化宿主时传入的应用上下文实例", + "is_optional": false, + "name": "context", + "param_type": "ApplicationContext" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "构造一个新的 ContextHostWrapper 实例", + "interface_type": "function", + "name": "new", + "parameters": [ + { + "description": "要包装的应用上下文", + "is_optional": false, + "name": "context", + "param_type": "ApplicationContext" + } + ], + "return_type": "Self", + "visibility": "public" + }, + { + "description": "获取对内部 ApplicationContext 的不可变引用", + "interface_type": "function", + "name": "get_context", + "parameters": [], + "return_type": "&ApplicationContext", + "visibility": "public" + }, + { + "description": "克隆并返回一份 ApplicationContext 的副本", + "interface_type": "function", + "name": "copy_context", + "parameters": [], + "return_type": "ApplicationContext", + "visibility": "public" + } + ], + "responsibilities": [ + "封装应用程序的全局配置数据", + "提供对配置上下文的安全只读访问", + "支持上下文对象的复制与共享", + "定义上下文宿主的标准接口规范", + "促进依赖解耦和测试可替代性" + ] + }, + { + "code_dossier": { + "code_purpose": "api", + "description": null, + "file_path": "crates/feed_api_rs/src/features/mod.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "mod.rs", + "source_summary": "pub mod api;\npub mod impl_default;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 2, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": 1, + "name": "api", + "path": "crates/feed_api_rs/src/features/api", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 2, + "name": "impl_default", + "path": "crates/feed_api_rs/src/features/impl_default", + "version": null + } + ], + "detailed_description": "该组件是一个Rust模块的组织文件,用于将`features`目录下的子模块(api和impl_default)进行公共导出。其主要作用是模块封装与命名空间管理,不包含具体业务逻辑实现,而是通过`pub mod`声明对外暴露内部功能模块。", + "interfaces": [], + "responsibilities": [ + "组织和管理features目录下的子模块结构", + "提供统一的模块访问入口,支持外部代码引用api和impl_default模块", + "实现模块级别的封装与可见性控制,确保内部实现细节的隔离", + "作为系统功能扩展点的聚合层,便于未来新增功能模块" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义任务状态枚举和任务转储数据结构,用于表示任务的生命周期状态和执行时长信息。", + "file_path": "crates/feed_api_rs/src/startup/types.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "Status", + "TaskDump" + ], + "name": "types.rs", + "source_summary": "#[derive(Clone, Copy)]\npub enum Status {\n UnLaunch,\n Running,\n Completed,\n Aborted,\n Error,\n}\n\n#[derive(Clone, Copy)]\npub struct TaskDump {\n pub status: Status,\n pub duration: u128,\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 14, + "number_of_classes": 2, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件定义了两个核心类型:`Status` 枚举用于表示任务的生命周期状态(未启动、运行中、已完成、已中止、错误),`TaskDump` 结构体用于封装任务的状态和持续时间(以纳秒为单位)。这些类型主要用于任务监控、状态跟踪和性能分析场景。通过 `Clone` 和 `Copy` trait 的派生,确保了类型的高效复制语义,适用于高频传递的上下文。", + "interfaces": [ + { + "description": "表示任务的五种可能状态:未启动、运行中、已完成、已中止、错误。", + "interface_type": "enum", + "name": "Status", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "包含任务当前状态和执行持续时间的只读快照结构体。", + "interface_type": "struct", + "name": "TaskDump", + "parameters": [], + "return_type": null, + "visibility": "pub" + } + ], + "responsibilities": [ + "定义任务的生命周期状态模型", + "封装任务执行状态与耗时信息", + "提供轻量级、可复制的数据传输对象", + "支持系统内任务状态的序列化与日志记录" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供异步任务并行执行的限流控制工具函数,确保在指定并发数限制下安全地执行多个Future。", + "file_path": "crates/feed_api_rs/src/utils.rs", + "functions": [ + "do_parallel_with_limit" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "utils.rs", + "source_summary": "use std::future::Future;\nuse std::sync::Arc;\nuse futures::future::join_all;\nuse tokio::sync::Semaphore;\n\npub async fn do_parallel_with_limit(futures: Vec, mut max_concurrent: usize) -> Vec\n where\n F: Future + Send + 'static,\n{\n if max_concurrent == 0 {\n max_concurrent = 1;\n }\n let semaphore = Arc::new(Semaphore::new(max_concurrent));\n\n let controlled_futures: Vec<_> = futures\n .into_iter()\n .map(|fut| {\n let permit = Arc::clone(&semaphore);\n async move {\n let _permit = permit.acquire().await.unwrap();\n #[cfg(debug_assertions)]\n println!(\"semaphore unlocked to execute task, max_concurrent = {}\", max_concurrent);\n fut.await\n }\n })\n .collect();\n\n join_all(controlled_futures).await\n}" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 4.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 29, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "trait", + "is_external": false, + "line_number": 1, + "name": "std::future::Future", + "path": "std::future::Future", + "version": null + }, + { + "dependency_type": "struct", + "is_external": false, + "line_number": 2, + "name": "std::sync::Arc", + "path": "std::sync::Arc", + "version": null + }, + { + "dependency_type": "function", + "is_external": true, + "line_number": 3, + "name": "futures::future::join_all", + "path": "futures::future::join_all", + "version": null + }, + { + "dependency_type": "struct", + "is_external": true, + "line_number": 4, + "name": "tokio::sync::Semaphore", + "path": "tokio::sync::Semaphore", + "version": null + } + ], + "detailed_description": "该组件实现了`do_parallel_with_limit`异步函数,用于在最大并发数限制下并行执行一组Future任务。通过使用Tokio的Semaphore(信号量)机制,每个任务在执行前需获取一个许可,从而实现对并发数量的精确控制。当max_concurrent为0时,默认设为1以防止无效配置。此功能适用于需要避免资源过载的高并发场景,如批量网络请求处理。", + "interfaces": [ + { + "description": "返回所有任务完成后的结果向量", + "interface_type": "function", + "name": "do_parallel_with_limit", + "parameters": [ + { + "description": "待执行的异步任务列表", + "is_optional": false, + "name": "futures", + "param_type": "Vec" + }, + { + "description": "最大允许的并发任务数,0将被自动修正为1", + "is_optional": false, + "name": "max_concurrent", + "param_type": "usize" + } + ], + "return_type": "Vec", + "visibility": "public" + } + ], + "responsibilities": [ + "管理异步任务的并发执行数量", + "防止系统资源因过多并发任务而耗尽", + "封装复杂的并发控制逻辑,提供简洁易用的API", + "支持调试模式下的执行状态输出" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": null, + "file_path": "crates/intelligent/src/lib.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "lib.rs", + "source_summary": "pub mod article_processor;\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 1, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件作为智能模块的根库文件,主要职责是组织和导出内部模块。当前仅公开导出了`article_processor`模块,表明其功能聚焦于文章处理相关的业务逻辑。该文件本身不包含具体实现,而是作为模块系统的基础入口,用于封装和暴露子模块。", + "interfaces": [], + "responsibilities": [ + "作为智能处理模块的顶层组织单元", + "声明并导出内部功能模块(如文章处理器)", + "提供模块边界和命名空间管理", + "支持外部组件对内部子模块的访问控制" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现文章内容清理的LLM处理器,通过预设系统提示和用户指令模板调用大模型完成文本净化任务。", + "file_path": "crates/intelligent/src/article_processor/purge.rs", + "functions": [ + "new_processor" + ], + "importance_score": 0.6, + "interfaces": [ + "IPresetArticleLLMProcessor" + ], + "name": "purge.rs", + "source_summary": "use llm::providers::types::AITargetOption;\nuse types::LLMSection;\n\nuse crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor};\n\nconst SYSTEM_PROMPT: &str = include_str!(\"prompts/purge_sys.prompt\");\nconst USER_PROMPT_COMMAND_PURGE: &str = include_str!(\"prompts/purge_suffix.prompt\");\n\npub struct Purge {}\n\nimpl IPresetArticleLLMProcessor for Purge {\n fn new_processor(llm_section: LLMSection) -> anyhow::Result {\n let options = AITargetOption {\n num_ctx: Some(8192),\n ..Default::default()\n };\n ArticleLLMProcessor::new(llm_section, SYSTEM_PROMPT.into(), USER_PROMPT_COMMAND_PURGE.into(), options)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 3.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 19, + "number_of_classes": 1, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": false, + "line_number": 1, + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "version": null + }, + { + "dependency_type": "type", + "is_external": false, + "line_number": 2, + "name": "types::LLMSection", + "path": "types", + "version": null + }, + { + "dependency_type": "trait", + "is_external": false, + "line_number": 4, + "name": "crate::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crate::article_processor::llm_processor", + "version": null + } + ], + "detailed_description": "该组件实现了IPresetArticleLLMProcessor接口,专门用于构建一个基于大语言模型的文章净化处理器。它通过加载两个外部提示文件(purge_sys.prompt和purge_suffix.prompt)作为系统提示和用户指令后缀,并配置适当的AI目标选项(如上下文长度为8192),来初始化ArticleLLMProcessor实例。其主要业务逻辑是在文章处理流程中执行内容清理操作,去除无关或冗余信息,提升后续处理的质量。", + "interfaces": [ + { + "description": "预设文章LLM处理器接口,定义了如何根据LLMSection创建处理器的标准方法。", + "interface_type": "trait", + "name": "IPresetArticleLLMProcessor", + "parameters": [ + { + "description": "指定大模型服务的区域配置", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "创建一个新的文章净化处理器实例", + "interface_type": "function", + "name": "new_processor", + "parameters": [ + { + "description": "LLM服务区域配置", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "实现文章净化功能的LLM处理器创建逻辑", + "管理并加载用于内容清理的系统级和用户级提示模板", + "配置适合内容清理任务的大模型参数选项", + "遵循预设处理器接口规范完成实例化流程" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "定义文章处理器的统一接口,支持异步处理和责任链模式。", + "file_path": "crates/intelligent/src/article_processor/types.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "IArticleProcessor" + ], + "name": "types.rs", + "source_summary": "use types::{Article, LLMInstructOption};\n\n/// 文章处理器trait,所有文章处理器都应该impl这个trait以形成责任链调度。\npub trait IArticleProcessor {\n /// 处理文章,输入为[Article][types::Article],输出为`Article`的[future][std::future::Future]。\n /// 函数本身不会修改输入的`Article`,且参数本身为不可变引用,在流水线中作为先前的副本。\n fn process(\n &self,\n input: &Article,\n opt: LLMInstructOption,\n ) -> impl std::future::Future>;\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 12, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": false, + "line_number": 1, + "name": "types", + "path": "types", + "version": null + } + ], + "detailed_description": "该组件定义了 `IArticleProcessor` trait,作为文章处理流水线中各处理器的统一接口规范。所有实现该 trait 的结构体均可参与文章处理的责任链调度。`process` 方法接收不可变引用的 `Article` 和 `LLMInstructOption` 配置,返回一个异步 Future,输出为 `anyhow::Result
`,确保非阻塞 I/O 与错误传播能力。此设计支持构建可扩展、松耦合的文章处理管道。", + "interfaces": [ + { + "description": "文章处理器的核心 trait,用于实现责任链模式中的处理器节点。", + "interface_type": "trait", + "name": "IArticleProcessor", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "处理文章的方法,接受不可变引用的 Article 和 LLMInstructOption,返回异步 Result。", + "interface_type": "method", + "name": "process", + "parameters": [ + { + "description": "待处理的文章内容,为不可变引用", + "is_optional": false, + "name": "input", + "param_type": "&Article" + }, + { + "description": "LLM 指令配置选项", + "is_optional": false, + "name": "opt", + "param_type": "LLMInstructOption" + } + ], + "return_type": "impl std::future::Future>", + "visibility": "public" + } + ], + "responsibilities": [ + "定义文章处理器的标准接口", + "支持异步非阻塞处理流程", + "保证输入数据不可变性以维护状态一致性", + "支持通过 LLM 指令选项进行参数化处理", + "为责任链模式提供基础抽象" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": null, + "file_path": "crates/intelligent/src/article_processor/mod.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "mod.rs", + "source_summary": "pub mod llm_processor;\npub mod types;\npub mod purge;\npub mod optimizer;\npub mod melt;\npub mod assistant;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.8, + "coupling_factor": 6.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 6, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": 1, + "name": "llm_processor", + "path": "crates/intelligent/src/article_processor/llm_processor.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 2, + "name": "types", + "path": "crates/intelligent/src/article_processor/types.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "purge", + "path": "crates/intelligent/src/article_processor/purge.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 4, + "name": "optimizer", + "path": "crates/intelligent/src/article_processor/optimizer.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 5, + "name": "melt", + "path": "crates/intelligent/src/article_processor/melt.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 6, + "name": "assistant", + "path": "crates/intelligent/src/article_processor/assistant.rs", + "version": null + } + ], + "detailed_description": "该组件是一个Rust模块的根定义文件,用于组织和导出文章处理功能的相关子模块。它本身不包含具体实现逻辑,而是通过`pub mod`声明将多个功能模块(如LLM处理、类型定义、净化、优化、融合和助手功能)聚合为一个统一的命名空间,便于外部调用者以树状结构引用这些组件。", + "interfaces": [], + "responsibilities": [ + "作为文章处理器的功能模块聚合点", + "提供统一的模块访问入口", + "维护子模块之间的组织结构关系" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现文章处理中的熔合逻辑,通过预设提示词调用LLM进行内容提炼。", + "file_path": "crates/intelligent/src/article_processor/melt.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "IPresetArticleLLMProcessor" + ], + "name": "melt.rs", + "source_summary": "use llm::providers::types::AITargetOption;\nuse types::LLMSection;\n\nuse crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor};\n\nconst SYSTEM_PROMPT: &str = include_str!(\"prompts/melt_sys.prompt\");\nconst USER_PROMPT_COMMAND_PURGE: &str = include_str!(\"prompts/melt_suffix.prompt\");\n\npub struct Melt {}\n\nimpl IPresetArticleLLMProcessor for Melt {\n fn new_processor(llm_section: LLMSection) -> anyhow::Result {\n let options = AITargetOption {\n temperature: Some(0.7),\n ..Default::default()\n };\n ArticleLLMProcessor::new(llm_section, SYSTEM_PROMPT.into(), USER_PROMPT_COMMAND_PURGE.into(), options)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 3.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 19, + "number_of_classes": 1, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": false, + "line_number": 1, + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "version": null + }, + { + "dependency_type": "struct", + "is_external": false, + "line_number": 2, + "name": "types::LLMSection", + "path": "types", + "version": null + }, + { + "dependency_type": "trait", + "is_external": false, + "line_number": 4, + "name": "crate::article_processor::llm_processor::IPresetArticleLLMProcessor", + "path": "crate::article_processor::llm_processor", + "version": null + } + ], + "detailed_description": "该组件实现了IPresetArticleLLMProcessor接口,用于构建一个基于大语言模型的文章处理器。它使用固定的系统提示(SYSTEM_PROMPT)和用户指令(USER_PROMPT_COMMAND_PURGE),并配置了AI生成参数(如temperature=0.7),以执行文章内容的'熔合'或提炼操作。其主要作用是将原始文本通过LLM转化为更紧凑、高质量的输出。", + "interfaces": [ + { + "description": "定义预设文章处理器的创建规范", + "interface_type": "trait", + "name": "IPresetArticleLLMProcessor", + "parameters": [ + { + "description": "指定LLM服务的目标区域", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "实现预设型文章LLM处理器的创建逻辑", + "封装Melt功能所需的系统与用户提示语", + "配置合适的AI生成参数以优化输出质量", + "作为文章处理流程中的一环,提供内容提炼能力" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "实现文章内容优化的LLM处理器,通过预设系统提示和用户指令模板对文本进行AI驱动的优化处理。", + "file_path": "crates/intelligent/src/article_processor/optimizer.rs", + "functions": [ + "new_processor" + ], + "importance_score": 0.6, + "interfaces": [ + "IPresetArticleLLMProcessor" + ], + "name": "optimizer.rs", + "source_summary": "use llm::providers::types::AITargetOption;\nuse types::LLMSection;\n\nuse crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor};\n\nconst SYSTEM_PROMPT: &str = include_str!(\"prompts/optimizer_sys.prompt\");\nconst USER_PROMPT_COMMAND_OPTIMIZE: &str = include_str!(\"prompts/optimizer_suffix.prompt\");\n\npub struct Optimizer {}\n\nimpl IPresetArticleLLMProcessor for Optimizer {\n fn new_processor(llm_section: LLMSection) -> anyhow::Result {\n let options = AITargetOption {\n temperature: Some(0.1),\n ..Default::default()\n };\n ArticleLLMProcessor::new(llm_section, SYSTEM_PROMPT.into(), USER_PROMPT_COMMAND_OPTIMIZE.into(), options)\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 3.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 19, + "number_of_classes": 1, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": false, + "line_number": 1, + "name": "llm::providers::types::AITargetOption", + "path": "llm::providers::types", + "version": null + }, + { + "dependency_type": "struct", + "is_external": false, + "line_number": 2, + "name": "types::LLMSection", + "path": "types", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 4, + "name": "crate::article_processor::llm_processor::{ArticleLLMProcessor, IPresetArticleLLMProcessor}", + "path": "crate::article_processor::llm_processor", + "version": null + } + ], + "detailed_description": "该组件实现了IPresetArticleLLMProcessor接口,专门用于创建一个针对文章优化任务的LLM处理器。它使用固定的系统提示(SYSTEM_PROMPT)和用户后缀提示(USER_PROMPT_COMMAND_OPTIMIZE),配置低温度参数(0.1)以确保输出稳定性,从而实现对文章特定部分的精细化优化。其主要作用是封装优化任务所需的AI模型参数和提示工程策略。", + "interfaces": [ + { + "description": "定义预设型文章LLM处理器的创建规范", + "interface_type": "trait", + "name": "IPresetArticleLLMProcessor", + "parameters": [], + "return_type": "anyhow::Result", + "visibility": "public" + }, + { + "description": "根据给定的LLM段落信息创建优化处理器实例", + "interface_type": "method", + "name": "new_processor", + "parameters": [ + { + "description": "待处理的文章段落信息", + "is_optional": false, + "name": "llm_section", + "param_type": "LLMSection" + } + ], + "return_type": "anyhow::Result", + "visibility": "public" + } + ], + "responsibilities": [ + "实现文章优化专用的LLM处理器工厂方法", + "配置适用于内容优化的AI模型参数(如低温度值)", + "管理并注入优化任务所需的系统与用户提示模板", + "遵循预设处理器规范,保证接口一致性" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义抓取器接口 IFetcher,用于异步获取文章列表。依赖于 Tauri 框架和外部类型系统。", + "file_path": "crates/scrap/src/types.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "IFetcher" + ], + "name": "types.rs", + "source_summary": "use tauri::{AppHandle, Runtime};\nuse types::{Article, FeedTargetDescription, LLMSection};\n\npub trait IFetcher {\n fn fetch(\n &self,\n app_handle: Option>,\n llm_section: &LLMSection,\n ftd: FeedTargetDescription,\n ) -> impl std::future::Future>> + Send;\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.67, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 11, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": true, + "line_number": 1, + "name": "tauri", + "path": "tauri::{AppHandle, Runtime}", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 2, + "name": "types", + "path": "types::{Article, FeedTargetDescription, LLMSection}", + "version": null + } + ], + "detailed_description": "该组件定义了一个名为 IFetcher 的 trait,用于抽象不同数据源的抓取逻辑。其核心方法 fetch 接收应用句柄、LLM 分析段落和 Feed 目标描述,返回一个异步 Future,输出为 Article 对象的 Result 列表。此设计支持在 Tauri 桌面应用上下文中进行灵活扩展,允许不同的实现根据配置从多种来源抓取内容。", + "interfaces": [ + { + "description": "抓取器行为的抽象接口,支持运行时动态分发。", + "interface_type": "trait", + "name": "IFetcher", + "parameters": [ + { + "description": "Tauri 应用句柄,用于访问应用状态或资源", + "is_optional": true, + "name": "app_handle", + "param_type": "Option>" + }, + { + "description": "指定 LLM 处理的内容区域配置", + "is_optional": false, + "name": "llm_section", + "param_type": "&LLMSection" + }, + { + "description": "目标 feed 来源的描述信息", + "is_optional": false, + "name": "ftd", + "param_type": "FeedTargetDescription" + } + ], + "return_type": "impl std::future::Future>> + Send", + "visibility": "public" + } + ], + "responsibilities": [ + "定义抓取操作的统一接口契约", + "支持异步非阻塞的数据获取模式", + "集成 Tauri 应用上下文以访问资源", + "解耦具体抓取逻辑与调用方", + "传递 LLM 处理指令与目标源描述" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "本模块为爬虫功能的核心聚合模块,通过公共子模块暴露RSS、搜索、模拟器、类型定义等功能,并私有化文章读取器等内部实现细节。", + "file_path": "crates/scrap/src/lib.rs", + "functions": [ + "read", + "read_inner", + "acquire_html", + "read_inner_from_response" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "lib.rs", + "source_summary": "mod article_reader;\nmod connector;\npub mod rss;\npub mod search;\npub mod simulator;\npub mod types;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.82, + "coupling_factor": 0.35, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 6, + "number_of_classes": 0, + "number_of_functions": 4 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "article_reader", + "path": "./crates/scrap/src/article_reader.rs", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "connector", + "path": "./crates/scrap/src/connector.rs", + "version": null + } + ], + "detailed_description": "该组件作为`scrap` crate的根模块,主要职责是组织和导出多个与网页抓取相关的功能模块。它将`rss`、`search`、`simulator`、`types`等模块公开,供外部调用者使用;同时将`article_reader`和`connector`设为私有,作为内部实现依赖。其核心逻辑集中在`article_reader`中:实现智能网页内容提取,支持自动重定向处理、HTML清洗(去除script/style)、基于LLM的内容重定向检测与递归抓取。系统结合了HTTP客户端策略控制、DOM解析(scraper)与AI代理决策能力,形成一个具备自适应能力的网页正文抽取管道。", + "interfaces": [], + "responsibilities": [ + "聚合并导出网页抓取相关功能模块", + "协调内部模块(如article_reader、connector)完成网页内容获取", + "提供高层级API以支持RSS抓取、搜索及页面模拟操作", + "管理子模块之间的依赖关系与数据流", + "封装底层实现细节以提供清晰的外部接口" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义搜索功能所需的数据类型和核心行为契约,特别是文章搜索的异步处理接口。", + "file_path": "crates/scrap/src/search/types.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "IProvider" + ], + "name": "types.rs", + "source_summary": "use tauri::{AppHandle, Runtime};\nuse types::Article;\n\npub trait IProvider {\n fn search_by_words(\n &self,\n words: Vec<&str>,\n app_handle: Option>,\n ) -> impl std::future::Future>>;\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 2.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 10, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "use", + "is_external": true, + "line_number": 1, + "name": "tauri", + "path": "tauri::{AppHandle, Runtime}", + "version": null + }, + { + "dependency_type": "use", + "is_external": false, + "line_number": 2, + "name": "types::Article", + "path": "types::Article", + "version": null + } + ], + "detailed_description": "该组件定义了一个名为 IProvider 的 trait,用于规范搜索服务的行为。它要求实现者提供一个基于关键词搜索文章的异步方法 search_by_words,该方法接受字符串切片向量和可选的 Tauri AppHandle,返回一个异步 Future,解析为包含 Article 对象向量的结果。此 trait 是搜索功能的核心抽象,允许不同搜索引擎(如本地、网络等)以统一方式集成。", + "interfaces": [ + { + "description": "搜索服务提供者的抽象接口,规定了必须实现的异步搜索方法。", + "interface_type": "trait", + "name": "IProvider", + "parameters": [], + "return_type": null, + "visibility": "public" + }, + { + "description": "根据提供的关键词执行搜索并返回文章结果的异步操作", + "interface_type": "method", + "name": "search_by_words", + "parameters": [ + { + "description": "用于搜索的关键词列表", + "is_optional": false, + "name": "words", + "param_type": "Vec<&str>" + }, + { + "description": "Tauri 应用句柄,用于访问应用状态或资源", + "is_optional": true, + "name": "app_handle", + "param_type": "Option>" + } + ], + "return_type": "impl std::future::Future>>", + "visibility": "public" + } + ], + "responsibilities": [ + "定义搜索服务的行为契约", + "声明异步搜索方法的统一接口", + "支持可选应用上下文传递以便内部操作", + "作为多种搜索实现的公共抽象基类", + "促进依赖注入和模块化设计" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义文章记录的数据模型,用于存储源链接、标题、内容版本、阅读状态等信息。", + "file_path": "crates/recorder/src/entity/article_record.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "Model", + "Relation", + "ActiveModelBehavior" + ], + "name": "article_record.rs", + "source_summary": "use sea_orm::entity::prelude::*;\nuse serde::{Deserialize, Serialize};\n\n// 源数据、提取的原正文、优化的正文、导读内容、新闻日期、创建日期、是否已阅读\n#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, DeriveEntityModel)]\n#[sea_orm(table_name = \"t_article_record\")]\npub struct Model {\n #[sea_orm(primary_key)]\n pub id: i32,\n pub source_link: String,\n pub title: String,\n pub purged_content: String,\n pub head_read: String,\n pub optimized_content: String,\n pub melted_content: String,\n #[sea_orm(column_type = \"Date\")]\n pub published_at: chrono::NaiveDate,\n #[sea_orm(column_type = \"Date\")]\n pub created_at: chrono::NaiveDate,\n pub has_read: bool,\n pub is_favorite: bool,\n pub group_id: String,\n}\n\n#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]\npub enum Relation {}\n\nimpl ActiveModelBehavior for ActiveModel {}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 2.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 28, + "number_of_classes": 1, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "database_orm", + "is_external": true, + "line_number": 1, + "name": "sea_orm", + "path": null, + "version": null + }, + { + "dependency_type": "serialization", + "is_external": true, + "line_number": 2, + "name": "serde", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是SeaORM实体模型,代表数据库中`t_article_record`表的结构。它包含文章的元数据(如标题、源链接)、多个版本的内容(原始提取、优化后、熔合后)、发布与创建日期、阅读状态和收藏状态。主要用于持久化文章抓取与处理结果,支持后续的内容展示与用户交互功能。", + "interfaces": [ + { + "description": "文章记录的核心数据结构", + "interface_type": "struct", + "name": "Model", + "parameters": [ + { + "description": null, + "is_optional": false, + "name": "id", + "param_type": "i32" + }, + { + "description": null, + "is_optional": false, + "name": "source_link", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "title", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "purged_content", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "head_read", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "optimized_content", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "melted_content", + "param_type": "String" + }, + { + "description": null, + "is_optional": false, + "name": "published_at", + "param_type": "chrono::NaiveDate" + }, + { + "description": null, + "is_optional": false, + "name": "created_at", + "param_type": "chrono::NaiveDate" + }, + { + "description": null, + "is_optional": false, + "name": "has_read", + "param_type": "bool" + }, + { + "description": null, + "is_optional": false, + "name": "is_favorite", + "param_type": "bool" + }, + { + "description": null, + "is_optional": false, + "name": "group_id", + "param_type": "String" + } + ], + "return_type": null, + "visibility": "pub" + }, + { + "description": "定义与其他实体的关系(当前为空)", + "interface_type": "enum", + "name": "Relation", + "parameters": [], + "return_type": null, + "visibility": "pub" + }, + { + "description": "ActiveModel的行为实现(默认)", + "interface_type": "trait_impl", + "name": "ActiveModelBehavior", + "parameters": [], + "return_type": null, + "visibility": "impl" + } + ], + "responsibilities": [ + "定义文章记录的数据库表结构", + "提供序列化与反序列化能力以支持数据传输", + "维护文章内容的多种形态(原始、优化、导读等)", + "管理文章的阅读状态与分组归属" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "该模块作为实体模块的根,用于组织和导出文章记录相关的数据结构。", + "file_path": "crates/recorder/src/entity/mod.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "mod.rs", + "source_summary": "pub mod article_record;\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 1.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 1, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": 1, + "name": "article_record", + "path": "crates/recorder/src/entity/article_record.rs", + "version": null + } + ], + "detailed_description": "该组件是一个Rust模块定义文件(mod.rs),其主要作用是将`article_record`模块声明为当前`entity`模块的公共子模块。此文件本身不包含具体逻辑,而是作为模块系统的一部分,用于组织代码结构,使得`article_record`中定义的数据模型可以在上级模块中通过`entity::article_record`路径访问。它体现了Rust中典型的模块化设计模式,用于封装与文章记录相关的实体类型。", + "interfaces": [], + "responsibilities": [ + "声明并导出 article_record 子模块", + "作为 entity 模块的入口点,提供模块结构组织", + "支持其他模块对文章记录实体的引用和复用" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": "定义了文章记录器的核心模块结构,包括服务、实体、操作器和路径管理。", + "file_path": "crates/recorder/src/lib.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "lib.rs", + "source_summary": "pub mod article_recorder_service;\npub mod entity;\nmod operator;\npub mod path;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.25, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 4, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": null, + "name": "operator", + "path": "./crates/recorder/src/operator.rs", + "version": null + } + ], + "detailed_description": "该组件是文章记录功能的模块入口,通过pub声明暴露article_recorder_service、entity、path等公共模块,并内部封装operator模块。其主要作用是组织和导出与文章记录相关的数据访问逻辑和服务接口。实际的数据操作由operator模块中的Operator结构体实现,包括数据库初始化、增删改查等操作。整体设计遵循Rust的模块化原则,将不同职责分离到独立模块中。", + "interfaces": [], + "responsibilities": [ + "组织和导出文章记录相关功能模块", + "提供模块边界控制(公有/私有)", + "协调子模块之间的依赖关系", + "作为外部访问文章记录功能的统一入口" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义混合运行时状态结构,封装功能API实现。", + "file_path": "crates/tauri-plugin-feed-api/src/state.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "HybridRuntimeState" + ], + "name": "state.rs", + "source_summary": "use feed_api_rs::features::impl_default::FeaturesAPIImpl;\n\npub struct HybridRuntimeState {\n pub features_api: FeaturesAPIImpl,\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 1.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 5, + "number_of_classes": 1, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "struct", + "is_external": true, + "line_number": 1, + "name": "feed_api_rs::features::impl_default::FeaturesAPIImpl", + "path": "feed_api_rs::features::impl_default", + "version": null + } + ], + "detailed_description": "该组件定义了一个名为 HybridRuntimeState 的结构体,用于在 Tauri 插件中持有 feed_api_rs 功能模块的实现实例。其主要作用是作为共享状态在不同组件间传递,使得前端或后端逻辑可以安全地访问底层功能 API。目前仅包含一个字段 features_api,类型为 FeaturesAPIImpl,来自 feed_api_rs crate 的默认实现模块。", + "interfaces": [ + { + "description": "混合运行时状态结构,用于在Tauri插件中共享FeaturesAPIImpl实例。", + "interface_type": "struct", + "name": "HybridRuntimeState", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "封装底层功能API的实现实例", + "作为Tauri应用中的共享状态载体", + "提供类型安全的状态结构定义", + "解耦业务逻辑与具体API实现" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "Tauri 应用的构建与依赖管理配置文件,定义了项目元信息、库类型、构建依赖、运行时依赖及编译优化选项。", + "file_path": "app/src-tauri/Cargo.toml", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "Cargo.toml", + "source_summary": "[package]\nname = \"qino-feed-client\"\nversion = \"0.9.11\"\ndescription = \"Saga Reader\"\nauthors = [\"Sopaco\"]\nedition = \"2024\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[lib]\nname = \"qino_feed_client_lib\"\ncrate-type = [\"lib\", \"cdylib\", \"staticlib\"]\n\n[build-dependencies]\ntauri-build = { version = \"2.3.0\", features = [] }\n\n[dependencies]\n# 本crate的特定的依赖\nsentry = \"0.41.0\"\nfslock = \"0.2.1\"\ntauri-plugin-shell = \"2.3.0\"\ntauri-plugin-clipboard-manager = \"2.3.0\"\ntauri-plugin-os = \"2.3.0\"\ntauri-plugin-dialog = \"2.3.1\"\n\n[target.'cfg(not(any(target_os = \"android\", target_os = \"ios\")))'.dependencies]\ntauri-plugin-autostart = \"2.5.0\"\ntauri-plugin-single-instance = \"2.3.1\"\n\n# 对workspace中其他crate的依赖\nfeed_api_rs = { path = \"../../crates/feed_api_rs\" }\ntypes = { path = \"../../crates/types\" }\nrecorder = { path = \"../../crates/recorder\" }\nollama = { path = \"../../crates/ollama\" }\ntauri-plugin-feed-api = { path = \"../../crates/tauri-plugin-feed-api\" }\n\n# 与workspace共享配置的依赖\ntauri = { workspace = true, features = [\"tray-icon\", \"unstable\"] }\nserde = { workspace = true, features = [\"derive\"] }\nserde_json = { workspace = true }\nanyhow = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\nspdlog-rs = { workspace = true }\n\n[profile.dev]\nincremental = true\n\n[profile.release]\ncodegen-units = 1\nlto = 'thin'\nopt-level = 3\npanic = \"abort\"\nstrip = \"none\"\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.85, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 53, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "build-dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-build", + "path": null, + "version": "2.3.0" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "sentry", + "path": null, + "version": "0.41.0" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "fslock", + "path": null, + "version": "0.2.1" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-plugin-shell", + "path": null, + "version": "2.3.0" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-plugin-clipboard-manager", + "path": null, + "version": "2.3.0" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-plugin-os", + "path": null, + "version": "2.3.0" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-plugin-dialog", + "path": null, + "version": "2.3.1" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-plugin-autostart", + "path": null, + "version": "2.5.0" + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri-plugin-single-instance", + "path": null, + "version": "2.3.1" + }, + { + "dependency_type": "dependencies", + "is_external": false, + "line_number": null, + "name": "feed_api_rs", + "path": "../../crates/feed_api_rs", + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": false, + "line_number": null, + "name": "types", + "path": "../../crates/types", + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": false, + "line_number": null, + "name": "recorder", + "path": "../../crates/recorder", + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": false, + "line_number": null, + "name": "ollama", + "path": "../../crates/ollama", + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": false, + "line_number": null, + "name": "tauri-plugin-feed-api", + "path": "../../crates/tauri-plugin-feed-api", + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tauri", + "path": null, + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "serde", + "path": null, + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "serde_json", + "path": null, + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "anyhow", + "path": null, + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "tokio", + "path": null, + "version": null + }, + { + "dependency_type": "dependencies", + "is_external": true, + "line_number": null, + "name": "spdlog-rs", + "path": null, + "version": null + } + ], + "detailed_description": "该 Cargo.toml 文件是 Tauri 框架驱动的桌面应用程序的核心配置文件。它不仅声明了项目的名称、版本、作者和 Rust 版本(edition 2024),还通过 [lib] 配置指定了生成多种库格式(静态库、动态库等),以支持跨平台原生集成。文件中明确划分了构建期依赖(tauri-build)和运行时依赖,包括 Sentry 错误追踪、文件锁机制(fslock)、多个 Tauri 官方插件(shell、clipboard、os、dialog、autostart、single-instance)以及对本地 workspace 内部 crate 的路径依赖(如 feed_api_rs、types、recorder 等)。此外,依赖项大量使用 workspace 共享配置,确保版本一致性并简化维护。编译配置(profile.release)启用了高级优化(LTO、opt-level=3)、panic 处理策略(abort)和符号剥离控制,针对发布版本进行了性能调优。", + "interfaces": [], + "responsibilities": [ + "定义项目元数据和构建属性", + "管理外部第三方依赖与内部 workspace crate 依赖", + "配置 Tauri 构建系统所需的构建依赖", + "设定不同构建环境(dev/release)的编译优化策略", + "声明库的输出类型以支持多目标链接" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "Tauri 框架的主配置文件,定义了应用元信息、构建流程、窗口设置、安全策略和打包选项。", + "file_path": "app/src-tauri/tauri.conf.json", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "tauri.conf.json", + "source_summary": "{\n \"productName\": \"麒睿智库\",\n \"version\": \"0.9.11\",\n \"identifier\": \"com.sopaco.labs.qinofeed\",\n \"build\": {\n \"beforeDevCommand\": \"bun run dev\",\n \"devUrl\": \"http://localhost:1420\",\n \"beforeBuildCommand\": \"bun run build\",\n \"frontendDist\": \"../build\"\n },\n \"app\": {\n \"windows\": [\n {\n \"label\": \"main\",\n \"title\": \"麒睿智库\",\n \"url\": \"/main\",\n \"center\": true,\n \"minWidth\": 1440,\n \"minHeight\": 750,\n \"visible\": false\n },\n {\n \"label\": \"reserved\",\n \"title\": \"reserved\",\n \"minWidth\": 1440,\n \"minHeight\": 750,\n \"visible\": false\n }\n ],\n \"withGlobalTauri\": true,\n \"security\": {\n \"csp\": null\n }\n },\n \"bundle\": {\n \"active\": true,\n \"targets\": \"all\",\n \"publisher\": \"Sopaco Global Networks ORG.\",\n \"copyright\": \"Sopaco Global Networks ORG.\",\n \"category\": \"Productivity\",\n \"shortDescription\": \"Qino Feed\",\n \"longDescription\": \"A Powerful reader driven by AI Assist-Read, supports multi sources include RSS, Web Search and more.\",\n \"icon\": [\n \"icons/32x32.png\",\n \"icons/128x128.png\",\n \"icons/128x128@2x.png\",\n \"icons/icon.icns\",\n \"icons/icon.ico\"\n ],\n \"windows\": {\n \"wix\": {\n \"language\": \"zh-CN\"\n }\n }\n },\n \"mainBinaryName\": \"SagaReader\",\n \"plugins\": {\n \"tauri-plugin-feed-api\": {\n \"timeout\": 30\n }\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.1, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 62, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "plugin", + "is_external": true, + "line_number": 58, + "name": "tauri-plugin-feed-api", + "path": null, + "version": null + } + ], + "detailed_description": "该配置文件用于定制基于 Tauri 构建的桌面应用程序行为。它定义了应用的基本信息(如名称、版本、标识符),构建指令(开发与生产环境命令及前端资源路径),应用运行时的窗口配置(包括主窗口和预留窗口的尺寸与可见性),以及打包发布时的元数据(如版权、分类、图标等)。同时启用了 `tauri-plugin-feed-api` 插件并设置了请求超时时间,确保 RSS 等内容获取服务稳定运行。CSP 安全策略被禁用(设为 null),可能出于开发灵活性考虑,但在生产环境中存在安全风险。", + "interfaces": [], + "responsibilities": [ + "管理应用元数据(名称、版本、标识符)", + "配置开发与构建生命周期命令", + "定义应用窗口布局与初始状态", + "控制应用打包行为与分发信息", + "集成并配置 Tauri 插件" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "Capability configuration for the In-App window in a Tauri desktop application, defining allowed windows and permissions.", + "file_path": "app/src-tauri/capabilities/default.json", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "default.json", + "source_summary": "{\n\t\"$schema\": \"../gen/schemas/desktop-schema.json\",\n\t\"identifier\": \"default\",\n\t\"description\": \"Capability for the In-App window\",\n\t\"windows\": [\n\t\t\"main\",\n\t\t\"settings\",\n\t\t\"about\",\n\t\t\"window_feed_create\",\n\t\t\"window_feed_edit\",\n\t\t\"window_feeds_package_create\",\n\t\t\"window_feeds_package_edit\",\n\t\t\"reserved\"\n\t],\n\t\"permissions\": [\n\t\t\"core:app:default\",\n\t\t\"core:app:allow-set-app-theme\",\n\t\t\"core:window:default\",\n\t\t\"core:window:allow-close\",\n\t\t\"core:window:allow-is-visible\",\n\t\t\"core:window:allow-get-all-windows\",\n\t\t\"core:window:allow-create\",\n\t\t\"core:window:allow-show\",\n\t\t\"core:window:allow-set-focus\",\n\t\t\"core:window:allow-center\",\n\t\t\"core:webview:allow-create-webview\",\n\t\t\"core:webview:allow-set-webview-focus\",\n\t\t\"core:event:default\",\n\t\t\"core:event:allow-listen\",\n\t\t\"shell:default\",\n\t\t\"shell:allow-open\",\n\t\t\"shell:allow-spawn\",\n\t\t\"clipboard-manager:default\",\n\t\t\"clipboard-manager:allow-write-text\",\n\t\t\"feed-api:default\",\n\t\t\"autostart:allow-enable\",\n\t\t\"autostart:allow-disable\",\n\t\t\"autostart:allow-is-enabled\",\n\t\t\"os:default\",\n\t\t\"dialog:default\",\n\t\t\"dialog:allow-ask\"\n\t]\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.02, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 43, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "$schema", + "is_external": false, + "line_number": 1, + "name": "../gen/schemas/desktop-schema.json", + "path": "app/src-tauri/gen/schemas/desktop-schema.json", + "version": null + } + ], + "detailed_description": "This configuration file defines a capability set named 'default' for a Tauri-based desktop application. It specifies which windows are available in the app (such as main, settings, about, and various feed-related windows) and grants a comprehensive set of permissions required for core functionality including window management, webview creation, event handling, shell operations, clipboard access, feed API interaction, autostart control, OS integration, and user dialogs. The schema reference ensures structural validity against the desktop-schema.json specification.", + "interfaces": [], + "responsibilities": [ + "Defines the set of available windows within the application", + "Grants essential permissions for core desktop functionalities", + "Serves as a security boundary by explicitly listing allowed capabilities", + "Provides configuration for role-based access control in the Tauri framework" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "Tauri应用的构建脚本,用于在编译时生成必要的绑定和配置。", + "file_path": "app/src-tauri/build.rs", + "functions": [ + "main" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "build.rs", + "source_summary": "fn main() {\n tauri_build::build()\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 3, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "build-dependency", + "is_external": true, + "line_number": null, + "name": "tauri_build", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是Rust项目中Tauri框架的构建脚本(build.rs),其主要作用是在编译期间执行tauri_build::build()函数,以生成前端与后端交互所需的绑定代码。它确保了Tauri命令、事件系统以及类型安全接口能够正确集成到最终的二进制文件中。尽管代码简洁,但它是连接Rust后端与前端的关键环节之一。", + "interfaces": [], + "responsibilities": [ + "在编译期触发Tauri绑定代码生成", + "确保前后端类型安全通信的基础设施准备", + "参与构建流程以支持Tauri特定功能(如命令注册、权限检查等)" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "定义应用程序不同运行环境下的能力集,包括权限、窗口访问和平台限制。", + "file_path": "app/src-tauri/gen/schemas/capabilities.json", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "capabilities.json", + "source_summary": "{\"default\":{\"identifier\":\"default\",\"description\":\"Capability for the In-App window\",\"local\":true,\"windows\":[\"main\",\"settings\",\"about\",\"window_feed_create\",\"window_feed_edit\",\"window_feeds_package_create\",\"window_feeds_package_edit\",\"reserved\"],\"permissions\":[\"core:app:default\",\"core:app:allow-set-app-theme\",\"core:window:default\",\"core:window:allow-close\",\"core:window:allow-is-visible\",\"core:window:allow-get-all-windows\",\"core:window:allow-create\",\"core:window:allow-show\",\"core:window:allow-set-focus\",\"core:window:allow-center\",\"core:webview:allow-create-webview\",\"core:webview:allow-set-webview-focus\",\"core:event:default\",\"core:event:allow-listen\",\"shell:default\",\"shell:allow-open\",\"shell:allow-spawn\",\"clipboard-manager:default\",\"clipboard-manager:allow-write-text\",\"feed-api:default\",\"autostart:allow-enable\",\"autostart:allow-disable\",\"autostart:allow-is-enabled\",\"os:default\",\"dialog:default\",\"dialog:allow-ask\"]},\"desktop-capability\":{\"identifier\":\"desktop-capability\",\"description\":\"\",\"local\":true,\"permissions\":[\"autostart:allow-enable\",\"autostart:allow-disable\",\"autostart:allow-is-enabled\"],\"platforms\":[\"macOS\",\"windows\",\"linux\"]},\"scrap-host-capability\":{\"identifier\":\"scrap-host-capability\",\"description\":\"Capability for the Scrap WebHost\",\"remote\":{\"urls\":[\"https://*\"]},\"local\":true,\"windows\":[\"WINDOW_SCRAP_HOST\"],\"permissions\":[\"core:app:default\",\"core:window:default\",\"core:event:default\"]}}" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.0, + "cyclomatic_complexity": 3.0, + "depth_of_inheritance": 0, + "lines_of_code": 1, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是一个JSON配置文件,用于声明Tauri应用中的各种capability(能力),每个capability包含标识符、描述、本地/远程策略、允许的窗口列表、权限列表以及可选的平台限制。主要用于安全模型控制,决定特定上下文(如主窗口或Web视图)可以执行哪些系统级操作。", + "interfaces": [], + "responsibilities": [ + "定义应用的安全能力边界", + "管理不同功能模块的权限分配", + "控制capability对特定窗口的可见性与可用性", + "支持多平台的能力差异化配置" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "定义了应用程序中多个窗口的标签、URL和标题常量,用于Tauri应用的窗口管理和前端路由配置。", + "file_path": "app/src-tauri/src/constrant.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "constrant.rs", + "source_summary": "pub const WINDOW_MAIN_LABEL: &str = \"main\";\npub const WINDOW_MAIN_URL: &str = \"/main\";\npub const WINDOW_MAIN_TITLE: &str = \"麒睿智库\";\n\npub const WINDOW_EXTERNAL_ENDPOINT_INFORMATION_LABEL: &str = \"external_endpoint_information\";\npub const WINDOW_EXTERNAL_ENDPOINT_INFORMATION_URL: &str = \"https://ip77.net/\";\npub const WINDOW_EXTERNAL_ENDPOINT_INFORMATION_TITLE: &str = \"网络信息\";\n\npub const WINDOW_ABOUT_LABEL: &str = \"about\";\npub const WINDOW_ABOUT_URL: &str = \"/about\";\npub const WINDOW_ABOUT_TITLE: &str = \"关于\";\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 11, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件通过定义一系列公共常量,为Tauri桌面应用中的多个窗口(如主窗口、外部端点信息窗口、关于窗口)提供统一的标识符(label)、访问路径(URL)和显示标题(title)。这些常量被用于窗口创建、路由匹配和UI展示等场景,确保跨模块引用的一致性和可维护性。代码采用清晰的命名约定,按功能分组组织常量,提升了可读性。", + "interfaces": [], + "responsibilities": [ + "定义并导出主窗口的标识、路径与标题常量", + "管理外部端点信息窗口的导航与显示配置", + "维护‘关于’窗口的相关元信息", + "为前端路由与窗口控制系统提供统一配置源" + ] + }, + { + "code_dossier": { + "code_purpose": "specificfeature", + "description": null, + "file_path": "app/src-tauri/src/monitor.rs", + "functions": [ + "start" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "monitor.rs", + "source_summary": "pub fn start() {\n let _guard = sentry::init((\n \"https://fcb721997d24a33b1bb3a13bdce4bd05@o83602.ingest.us.sentry.io/4507806662131712\",\n sentry::ClientOptions {\n release: sentry::release_name!(),\n ..Default::default()\n },\n ));\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 1.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 9, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "crate", + "is_external": true, + "line_number": 1, + "name": "sentry", + "path": null, + "version": null + } + ], + "detailed_description": "该组件负责初始化Sentry错误监控服务。在应用启动时调用`start`函数,通过提供的DSN配置连接到Sentry服务器,并自动绑定当前代码的发布版本(使用宏`release_name!()`)。该功能用于捕获运行时异常、错误和性能问题,支持远程监控和调试。", + "interfaces": [ + { + "description": "启动Sentry监控服务,返回一个RAII守卫以维持会话生命周期", + "interface_type": "function", + "name": "start", + "parameters": [], + "return_type": "nil", + "visibility": "public" + } + ], + "responsibilities": [ + "初始化Sentry监控客户端", + "绑定应用发布版本信息以便追踪", + "为全局错误捕获提供运行时上下文" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "用于判断当前程序是否以守护进程模式启动的工具函数。", + "file_path": "app/src-tauri/src/env.rs", + "functions": [ + "is_daemon" + ], + "importance_score": 0.6, + "interfaces": [ + "is_daemon" + ], + "name": "env.rs", + "source_summary": "use crate::daemon::args::DAEMON_FEEDS_SCHEDULE_UPDATE;\n\npub fn is_daemon() -> bool {\n let launch_mode = std::env::args().nth(1).unwrap_or_default();\n launch_mode.eq(DAEMON_FEEDS_SCHEDULE_UPDATE)\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 6, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "constant", + "is_external": false, + "line_number": 1, + "name": "crate::daemon::args::DAEMON_FEEDS_SCHEDULE_UPDATE", + "path": "src/daemon/args.rs", + "version": null + } + ], + "detailed_description": "该组件提供了一个名为 `is_daemon` 的布尔函数,用于检测应用程序是否以特定命令行参数(DAEMON_FEEDS_SCHEDULE_UPDATE)启动。它通过读取第一个命令行参数并与预定义常量进行比较来实现这一逻辑。此功能主要用于区分常规应用启动和后台守护进程调度任务的执行场景。", + "interfaces": [ + { + "description": "检查当前进程是否以 DAEMON_FEEDS_SCHEDULE_UPDATE 参数启动", + "interface_type": "function", + "name": "is_daemon", + "parameters": [], + "return_type": "bool", + "visibility": "public" + } + ], + "responsibilities": [ + "解析命令行参数以确定启动模式", + "提供简洁的API判断是否为守护进程模式", + "与系统环境交互获取运行时参数" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供守护进程相关的文件锁路径管理功能,用于协调后台任务的并发执行", + "file_path": "app/src-tauri/src/daemon/locks.rs", + "functions": [ + "get_lock_path" + ], + "importance_score": 0.6, + "interfaces": [ + "LOCK_FEEDS_SCHEDULE_UPDATE" + ], + "name": "locks.rs", + "source_summary": "use std::path::PathBuf;\n\nuse recorder::path::get_appdata_file_in_dir;\n\npub const LOCK_FEEDS_SCHEDULE_UPDATE: &str = \"feeds_schedule_update.lock\";\n\npub fn get_lock_path(locker_name: &str) -> PathBuf {\n get_appdata_file_in_dir(\"daemons\", locker_name)\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 2.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 9, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "standard_library", + "is_external": false, + "line_number": 1, + "name": "std::path::PathBuf", + "path": "std::path::PathBuf", + "version": null + }, + { + "dependency_type": "internal_module", + "is_external": false, + "line_number": 3, + "name": "recorder::path::get_appdata_file_in_dir", + "path": "recorder::path::get_appdata_file_in_dir", + "version": null + } + ], + "detailed_description": "该组件定义了一个常量LOCK_FEEDS_SCHEDULE_UPDATE和一个工具函数get_lock_path。其主要功能是为守护进程(daemon)系统生成特定锁文件的完整路径,通过调用recorder模块的get_appdata_file_in_dir函数,将锁文件统一存储在'appdata/daemons/'目录下。这种设计实现了锁文件路径的集中管理和命名规范化。", + "interfaces": [ + { + "description": "用于feeds定时更新任务的锁文件名称常量", + "interface_type": "const", + "name": "LOCK_FEEDS_SCHEDULE_UPDATE", + "parameters": [], + "return_type": "&str", + "visibility": "pub" + } + ], + "responsibilities": [ + "管理守护进程相关的锁文件路径生成", + "提供标准化的锁文件命名约定", + "封装锁文件存储位置的细节实现", + "确保锁文件路径的跨平台兼容性" + ] + }, + { + "code_dossier": { + "code_purpose": "other", + "description": null, + "file_path": "app/src-tauri/src/daemon/mod.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "mod.rs", + "source_summary": "pub(crate) mod args;\npub(crate) mod feeds_update;\npub(crate) mod launcher;\npub(crate) mod locks;\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.8, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 4, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": false, + "line_number": 1, + "name": "args", + "path": "app/src-tauri/src/daemon/args", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 2, + "name": "feeds_update", + "path": "app/src-tauri/src/daemon/feeds_update", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 3, + "name": "launcher", + "path": "app/src-tauri/src/daemon/launcher", + "version": null + }, + { + "dependency_type": "module", + "is_external": false, + "line_number": 4, + "name": "locks", + "path": "app/src-tauri/src/daemon/locks", + "version": null + } + ], + "detailed_description": "该组件是一个Rust模块的组织文件,用于将daemon功能域下的多个子模块(args, feeds_update, launcher, locks)进行聚合和封装。它本身不包含具体实现逻辑,而是通过pub(crate)关键字将内部模块暴露给当前crate的其他部分使用,起到模块路由和命名空间管理的作用。", + "interfaces": [], + "responsibilities": [ + "组织和聚合daemon相关的子模块", + "提供统一的模块访问入口", + "控制模块的可见性范围(仅限当前crate)" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "定义守护进程的命令行参数常量,用于配置定时任务调度行为", + "file_path": "app/src-tauri/src/daemon/args.rs", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "args.rs", + "source_summary": "pub const DAEMON_FEEDS_SCHEDULE_UPDATE: &str = \"--feeds-schedule-update\";\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 1, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件定义了一个公共常量 DAEMON_FEEDS_SCHEDULE_UPDATE,表示用于触发守护进程中 feeds 定时更新任务的命令行参数。该常量作为配置项被其他模块引用,用于解析启动参数并决定是否启用定时更新功能。尽管当前仅包含一个常量,但其在系统启动流程中起到关键的配置作用。", + "interfaces": [], + "responsibilities": [ + "定义守护进程相关的命令行参数常量", + "提供跨模块共享的配置标识符", + "支持守护进程功能的条件性启用控制", + "确保命令行接口的一致性和可维护性" + ] + }, + { + "code_dossier": { + "code_purpose": "entry", + "description": "SvelteKit应用的全局类型声明文件,用于扩展App命名空间下的类型定义。", + "file_path": "app/src/app.d.ts", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "app.d.ts", + "source_summary": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n\tnamespace App {\n\t\t// interface Error {}\n\t\t// interface Locals {}\n\t\t// interface PageData {}\n\t\t// interface PageState {}\n\t\t// interface Platform {}\n\t}\n}\n\nexport {};\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 13, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是SvelteKit项目的类型声明文件(app.d.ts),主要用于在TypeScript环境中为应用程序提供全局类型扩展能力。通过declare global语句,在App命名空间中预留了Error、Locals、PageData、PageState和Platform等接口的定义位置,开发者可根据需要取消注释并实现这些接口以增强类型安全性和开发体验。当前版本为空模板,未实际定义任何类型。", + "interfaces": [], + "responsibilities": [ + "提供SvelteKit框架所需的全局类型扩展入口", + "定义应用程序级别的类型接口(如Locals、PageData等)", + "支持跨模块的类型共享与一致性校验", + "作为TypeScript类型系统的集成点" + ] + }, + { + "code_dossier": { + "code_purpose": "middleware", + "description": "Sentry客户端错误监控和会话重放初始化配置文件", + "file_path": "app/src/hooks.client.ts", + "functions": [ + "handleError" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "hooks.client.ts", + "source_summary": "import { handleErrorWithSentry, replayIntegration } from '@sentry/sveltekit';\nimport * as Sentry from '@sentry/sveltekit';\n\nSentry.init({\n\tdsn: 'https://19ca433cd275a680d5e35857bc289cb0@o83602.ingest.us.sentry.io/4507827211862016',\n\ttracesSampleRate: 1.0,\n\n\t// This sets the sample rate to be 10%. You may want this to be 100% while\n\t// in development and sample at a lower rate in production\n\treplaysSessionSampleRate: 0.1,\n\n\t// If the entire session is not sampled, use the below sample rate to sample\n\t// sessions when an error occurs.\n\treplaysOnErrorSampleRate: 1.0,\n\n\t// If you don't want to use Session Replay, just remove the line below:\n\tintegrations: [replayIntegration()]\n});\n\n// If you have a custom error handler, pass it to `handleErrorWithSentry`\nexport const handleError = handleErrorWithSentry();\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.095, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 21, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "module", + "is_external": true, + "line_number": 1, + "name": "@sentry/sveltekit", + "path": null, + "version": null + }, + { + "dependency_type": "module", + "is_external": true, + "line_number": 3, + "name": "@sentry/sveltekit", + "path": null, + "version": null + } + ], + "detailed_description": "该组件用于在SvelteKit客户端环境中初始化Sentry错误追踪服务,配置了分布式追踪、会话采样率以及错误发生时的重放机制。通过集成replayIntegration实现了用户行为回放功能,并导出经过封装的handleError函数以统一处理运行时异常。", + "interfaces": [ + { + "description": "处理并上报捕获到的错误至Sentry服务", + "interface_type": "function", + "name": "handleError", + "parameters": [ + { + "description": "包含错误对象和请求事件的输入参数", + "is_optional": false, + "name": "input", + "param_type": "{ error: unknown; event: import('@sentry/sveltekit').RequestEvent }" + } + ], + "return_type": "void", + "visibility": "public" + } + ], + "responsibilities": [ + "初始化Sentry客户端监控实例", + "配置错误追踪与性能监控参数", + "启用用户会话重放功能以辅助调试", + "提供标准化的错误处理函数", + "管理前端异常上报策略" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义文章数据结构,用于表示系统中的文章实体及其属性。", + "file_path": "app/src/lib/types/article.ts", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "Article" + ], + "name": "article.ts", + "source_summary": "interface Article {\n\tid: number;\n\ttitle: string;\n\thead_read: string;\n\tpublished_at: string;\n\thas_read: boolean;\n\tsource_link: string;\n\tpurged_content: string;\n\toptimized_content: string;\n\tmelted_content: string;\n\tcreated_at: string;\n\tgroup_id: string;\n\tis_favorite: boolean;\n}\n\nexport type { Article };\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 16, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件定义了一个名为 Article 的接口,用于描述系统中文章的数据结构。包含文章的基本信息如 ID、标题、阅读状态、发布时间、内容变体(purged、optimized、melted)、分组标识、收藏状态等。主要用于类型约束和前后端数据交互的结构一致性保障。", + "interfaces": [ + { + "description": "表示一篇文章的完整数据结构", + "interface_type": "interface", + "name": "Article", + "parameters": [ + { + "description": "文章唯一标识符", + "is_optional": false, + "name": "id", + "param_type": "number" + }, + { + "description": "文章标题", + "is_optional": false, + "name": "title", + "param_type": "string" + }, + { + "description": "摘要或首段预览文本", + "is_optional": false, + "name": "head_read", + "param_type": "string" + }, + { + "description": "文章发布时间(ISO 字符串格式)", + "is_optional": false, + "name": "published_at", + "param_type": "string" + }, + { + "description": "用户是否已读该文章", + "is_optional": false, + "name": "has_read", + "param_type": "boolean" + }, + { + "description": "原始来源链接", + "is_optional": false, + "name": "source_link", + "param_type": "string" + }, + { + "description": "清理后的纯文本内容", + "is_optional": false, + "name": "purged_content", + "param_type": "string" + }, + { + "description": "优化渲染的内容(如富文本)", + "is_optional": false, + "name": "optimized_content", + "param_type": "string" + }, + { + "description": "聚合或融合处理后的内容版本", + "is_optional": false, + "name": "melted_content", + "param_type": "string" + }, + { + "description": "记录创建时间", + "is_optional": false, + "name": "created_at", + "param_type": "string" + }, + { + "description": "所属分组 ID", + "is_optional": false, + "name": "group_id", + "param_type": "string" + }, + { + "description": "是否被标记为收藏", + "is_optional": false, + "name": "is_favorite", + "param_type": "boolean" + } + ], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "定义文章实体的数据结构", + "提供类型安全支持以确保数据一致性", + "作为多个模块间数据传输的契约" + ] + }, + { + "code_dossier": { + "code_purpose": "model", + "description": "定义加载状态的枚举类型,用于表示异步操作的不同阶段", + "file_path": "app/src/lib/types/loading.ts", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "LoadingStatus" + ], + "name": "loading.ts", + "source_summary": "enum LoadingStatus {\n\tLoading,\n\tCompleted,\n\tError\n}\n\nexport { LoadingStatus };\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 7, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件定义了一个名为LoadingStatus的枚举类型,包含三个状态值:Loading(加载中)、Completed(已完成)和Error(出错)。该枚举主要用于表示异步操作(如数据获取、文件上传等)的生命周期状态,为前端UI状态管理和错误处理提供标准化的状态标识。", + "interfaces": [ + { + "description": "表示异步操作的三种可能状态:加载中、已完成、出错", + "interface_type": "enum", + "name": "LoadingStatus", + "parameters": [], + "return_type": null, + "visibility": "public" + } + ], + "responsibilities": [ + "定义异步操作的标准状态枚举", + "提供类型安全的状态值引用", + "支持UI根据加载状态进行条件渲染", + "作为领域模型在不同组件间传递状态信息" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供DOM操作相关的工具函数,用于禁用右键菜单和监听元素可见性变化。", + "file_path": "app/src/lib/utils/dom.ts", + "functions": [ + "disableContextMenu", + "observeVisiblity" + ], + "importance_score": 0.6, + "interfaces": [ + "ObserveVisiblityOption" + ], + "name": "dom.ts", + "source_summary": "import { browser } from '$app/environment';\n\nfunction disableContextMenu(node: Document | HTMLElement) {\n\tif (!browser) return;\n\tconst handler = (e: Event) => {\n\t\tconst target = e.target;\n\t\tif (target instanceof HTMLInputElement) {\n\t\t\treturn;\n\t\t}\n\t\te.preventDefault();\n\t};\n\tnode.addEventListener('contextmenu', handler, false);\n\treturn {\n\t\tdestroy() {\n\t\t\tnode.removeEventListener('contextmenu', handler, false);\n\t\t}\n\t};\n}\n\ntype ObserveVisiblityOption = {\n\tcallback: (v: boolean) => void;\n};\n\nfunction observeVisiblity(node: HTMLElement, opt: ObserveVisiblityOption) {\n\tconst { callback } = opt;\n\tconst observer = new IntersectionObserver((entries) => {\n\t\tentries.forEach((entry) => {\n\t\t\tif (entry.isIntersecting) {\n\t\t\t\tcallback(true);\n\t\t\t} else {\n\t\t\t\tcallback(false);\n\t\t\t}\n\t\t\treturn;\n\t\t});\n\t});\n\n\tobserver.observe(node);\n\n\treturn {\n\t\tdestroy() {\n\t\t\tobserver.unobserve(node);\n\t\t}\n\t};\n}\n\nexport { disableContextMenu, observeVisiblity };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.5, + "cyclomatic_complexity": 4.0, + "depth_of_inheritance": 0, + "lines_of_code": 46, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "$app/environment", + "path": "$app/environment", + "version": null + } + ], + "detailed_description": "该组件包含两个核心工具函数:`disableContextMenu`用于在浏览器环境中禁用指定节点的上下文菜单(右键菜单),但允许输入框等表单元素保留默认行为;`observeVisiblity`利用IntersectionObserver API监听页面元素的可见状态变化,并通过回调通知。这两个函数均返回Svelte风格的销毁对象,便于在组件生命周期中清理事件监听或观察器。", + "interfaces": [ + { + "description": "定义observeVisiblity函数所需的配置选项结构", + "interface_type": "type", + "name": "ObserveVisiblityOption", + "parameters": [ + { + "description": "当元素可见性发生变化时调用的回调函数,参数为boolean表示是否可见", + "is_optional": false, + "name": "callback", + "param_type": "(v: boolean) => void" + } + ], + "return_type": null, + "visibility": "exported" + } + ], + "responsibilities": [ + "禁用非输入元素的右键上下文菜单", + "监听DOM元素的可视状态变化", + "提供可销毁的DOM行为绑定机制", + "适配Svelte运行时环境(通过$env判断)" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供日期格式化工具函数,将当前日期转换为YYYY-MM-DD字符串格式", + "file_path": "app/src/lib/utils/date.ts", + "functions": [ + "currentDateText" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "date.ts", + "source_summary": "function currentDateText() {\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = now.getMonth() + 1;\n\tconst day = now.getDate();\n\n\tconst formattedMonth = String(month).padStart(2, '0');\n\tconst formattedDay = String(day).padStart(2, '0');\n\n\treturn `${year}-${formattedMonth}-${formattedDay}`;\n}\n\nexport { currentDateText };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 13, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [], + "detailed_description": "该组件包含一个名为currentDateText的函数,用于获取当前系统日期并将其格式化为'YYYY-MM-DD'的标准字符串格式。函数通过JavaScript内置Date对象获取年、月、日,并对月份和日期进行零填充处理以确保两位数显示,最后返回组合后的日期字符串。该功能常用于日志记录、文件命名、数据标识等需要标准化日期表示的场景。", + "interfaces": [], + "responsibilities": [ + "获取当前系统日期时间", + "将日期格式化为标准的YYYY-MM-DD字符串格式", + "确保月份和日期的两位数显示(零填充)", + "提供可复用的日期格式化工具函数" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "提供文本处理相关的通用工具函数,包括判空、模板替换和去除代码块包装等。", + "file_path": "app/src/lib/utils/text.ts", + "functions": [ + "isTextEmpty", + "format", + "removeCodeBlockWrapper" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "text.ts", + "source_summary": "function isTextEmpty(text: string | null) {\n\treturn text == null || text.length === 0;\n}\n\nfunction format(template: string, variables: Record) {\n\treturn template.replace(/\\{(\\w+)\\}/g, (match, key) => {\n\t\treturn variables[key] !== undefined ? variables[key] : match;\n\t});\n}\n\nfunction removeCodeBlockWrapper(str: string) {\n\t// 定义正则表达式来匹配开头的代码块包裹字符\n\tconst startRegex = /^(```(?:\\w+)?[\\s\\n]*)*/;\n\t// 定义正则表达式来匹配结尾的代码块包裹字符\n\tconst endRegex = /(```)$/;\n\t// 去除开头的代码块包裹字符\n\tlet result = str.replace(startRegex, '');\n\t// 去除结尾的代码块包裹字符\n\tresult = result.replace(endRegex, '');\n\treturn result;\n}\n\nexport { isTextEmpty, format, removeCodeBlockWrapper };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 23, + "number_of_classes": 0, + "number_of_functions": 3 + }, + "dependencies": [], + "detailed_description": "该组件包含三个纯函数,用于处理字符串操作:isTextEmpty 判断字符串是否为空或 null;format 使用键值对替换模板中的占位符;removeCodeBlockWrapper 移除 Markdown 风格的代码块包裹符号(如 ```language 和 ```)。所有函数均为无副作用的工具函数,适合在多处复用。", + "interfaces": [], + "responsibilities": [ + "判断文本是否为空值", + "执行字符串模板变量替换", + "去除 Markdown 代码块的包裹符号" + ] + }, + { + "code_dossier": { + "code_purpose": "util", + "description": "生成基于时间戳的字符串ID", + "file_path": "app/src/lib/utils/id.ts", + "functions": [ + "genStringId" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "id.ts", + "source_summary": "function genStringId(): string {\n\treturn `${Date.now()}`;\n}\n\nexport { genStringId };\n" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 5, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [], + "detailed_description": "该组件提供了一个简单的函数 genStringId,用于生成基于当前时间戳的字符串形式的唯一ID。通过调用 Date.now() 获取毫秒级时间戳,并将其转换为字符串返回。适用于需要轻量级、无依赖ID生成的场景。", + "interfaces": [ + { + "description": "生成一个基于当前时间戳的字符串ID", + "interface_type": "function", + "name": "genStringId", + "parameters": [], + "return_type": "string", + "visibility": "public" + } + ], + "responsibilities": [ + "生成基于时间戳的唯一字符串ID", + "提供轻量级ID生成能力", + "避免外部依赖实现基本标识生成功能" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "负责管理设置窗口的打开行为,封装了窗口配置参数并调用单例模式展示窗口。", + "file_path": "app/src/lib/windows/settings.ts", + "functions": [ + "open" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "settings.ts", + "source_summary": "import { showWindowSingleton } from './utils';\n\nasync function open() {\n\tshowWindowSingleton('settings', '/settings', {\n\t\ttitle: '应用设置',\n\t\twidth: 600,\n\t\theight: screen.availHeight - 50,\n\t\tcenter: true,\n\t\tresizable: false,\n\t\tmaximizable: false\n\t});\n}\n\nexport { open };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 1.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 14, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "function", + "is_external": false, + "line_number": 1, + "name": "showWindowSingleton", + "path": "./utils", + "version": null + } + ], + "detailed_description": "该组件定义了一个异步函数 open,用于打开名为 'settings' 的应用设置窗口。通过导入并调用 showWindowSingleton 工具函数,传入窗口标识、URL 路径及一系列窗口属性(如标题、尺寸、居中显示、不可调整大小和不可最大化),实现统一且受控的窗口展示逻辑。此模块作为配置与行为的桥梁,将窗口的视觉和交互特性集中声明。", + "interfaces": [], + "responsibilities": [ + "封装设置窗口的打开逻辑", + "定义设置窗口的UI配置参数(尺寸、标题、可调整性等)", + "利用单例模式确保设置窗口唯一实例", + "协调窗口系统与具体业务需求之间的交互" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "中文语言包配置文件,包含应用所有界面的文本内容翻译与展示文案。", + "file_path": "app/src/lib/i18n/locales/zh.json", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "zh.json", + "source_summary": "{\n \"common\": {\n \"product_name\": \"麒睿智库\",\n \"product_slogan\": \"智能阅读新体验\",\n \"product_tip\": \"由AI驱动的知识软件,定制你的个人智库助理\"\n },\n \"main\": {\n \"menu\": {\n \"create_feeds_package\": \"添加订阅\",\n \"settings\": \"设置\"\n },\n \"section_frequently_used\": {\n \"label\": \"常用\",\n \"menu\": {\n \"today\": \"今日最新\",\n \"this_week\": \"本周快递\",\n \"favorites\": \"我的收藏\",\n \"unread\": \"未读内容\"\n }\n },\n \"section_subscriptions\": {\n \"label\": \"所有订阅\"\n },\n \"feeds\": {\n \"menu\": {\n \"actions\": {\n \"create\": \"新增\",\n \"edit\": \"编辑\",\n \"delete\": \"删除\",\n \"delete_prompt\": \"要删除订阅包{name}吗?,该订阅包下的{length}个订阅栏目都将移除。\",\n \"delete_dialog_title\": \"删除订阅包\"\n }\n },\n \"create_or_edit\": {\n \"field_feeds_package_name\": \"订阅组名称\",\n \"field_feeds_package_placeholder\": \"请填写订阅组的名称,建议8个字以内\",\n \"tip_modify_failured\": \"修改失败,请检查表单字段是否填写正确。{e}\",\n \"tip_footer\": \"注意:订阅组名称建议不与其他已有的订阅组名称相同。\"\n }\n },\n \"feed\": {\n \"menu\": {\n \"actions\": {\n \"edit\": \"编辑\",\n \"delete\": \"删除\",\n \"delete_prompt\": \"要删除订阅{name}吗?\",\n \"delete_dialog_title\": \"删除订阅\"\n }\n },\n \"create_or_edit\": {\n \"field_feed_name\": \"订阅名称\",\n \"field_feed_placeholder\": \"请填写订阅的名称,建议8个字以内\",\n \"field_fetcher_type_name\": \"信息来源\",\n \"field_fetcher_type_selection_1\": \"巴顿引擎(全球情报侦测引擎)\",\n \"field_fetcher_type_selection_2\": \"RSS订阅\",\n \"field_keywords\": \"信息关键词\",\n \"field_rss_url\": \"RSS地址\",\n \"tip_unknown_fetcher\": \"未知Fetcher:{formFetcherId}\",\n \"field_keywords_placeholder\": \"请填写信息关键词,多个关键词可以用空格隔开,就像使用搜索引擎一样。\",\n \"field_rss_url_placeholder\": \"请填写RSS地址。\",\n \"tip_modify_failured\": \"修改失败,请检查表单字段是否填写正确。{e}\",\n \"tip_footer\": \"注意:订阅名称建议不与其他已有的订阅组名称相同。\"\n }\n },\n \"search\": {\n \"results_label\": \"搜索结果\",\n \"placeholder_input\": \"智能搜索\"\n },\n \"articles\": {\n \"tip_click_to_load_more\": \"点击继续加载\",\n \"tip_loading\": \"加载中...\",\n \"error_retry\": \"发生错误,点击重试\",\n \"tip_empty_try_again\": \"无内容,点击尝试更新\",\n \"tip_empty\": \"无内容\"\n },\n \"footer\": {\n \"tasks\": {\n \"label\": \"后台任务\",\n \"idle\": \"当前无运行中任务\",\n \"status_summary_part1\": \"处理中\",\n \"status_summary_part2\": \"项\",\n \"status_ready\": \"就绪\",\n \"status_error\": \"出现错误,点击查看详情\"\n }\n }\n },\n \"reader\": {\n \"tab_optimized_content\": \"速读\",\n \"tab_melted_content\": \"总结\",\n \"tab_melted_original\": \"原文\",\n \"tip_link_copyed\": \"链接已复制\",\n \"blank_tip_0\": \"请选择订阅内容\",\n \"blank_tip_1\": \"1、添加订阅主题\",\n \"blank_tip_2\": \"2、刷新订阅内容清单\",\n \"blank_tip_3\": \"3、点击订阅内容标题\"\n },\n \"aisprite\": {\n \"label\": \"麒睿AI伴读\",\n \"chat_me\": \"我\",\n \"tip_wait_llm_response\": \"请等候Copilot完成思考\",\n \"tip_no_input\": \"请输入内容\",\n \"tip_error_llm_error\": \"大模型服务调用异常\",\n \"tip_placeholder_please_input\": \"向Copilot了解...\"\n },\n \"settings\": {\n \"label\": \"应用设置\",\n \"loading\": \"加载中\",\n \"section_llm_appearance\": {\n \"label\": \"外观\",\n \"theme\": {\n \"label\": \"启用暗夜黑\",\n \"description\": \"开启以使用暗夜黑主题,关闭则使用白月光主题\"\n }\n },\n \"section_llm_provider\": {\n \"label\": \"大模型配置\",\n \"tip\": \"选择大模型引擎\",\n \"provider_ollama\": \"Ollama(本地大模型)\",\n \"provider_ollama_tip\": \"Ollama可以本地部署在您的设备上,提供适合您硬件设备的私有模型与极佳的数据隐私安全性,需要先安装Ollama,\",\n \"provider_ollama_sentence_1\": \"点击这里去下载\",\n \"provider_ollama_sentence_2\": \"Ollama服务地址\",\n \"provider_ollama_sentence_3\": \"模型名称\",\n \"provider_ollama_sentence_4\": \"请填写模型名称,例如“qwen2.5:3b”\",\n \"provider_ollama_sentence_5\": \"默认为“http://localhost:11434”\",\n \"provider_glm\": \"智谱AI(云端大模型)\",\n \"provider_glm_sentence_1\": \"您可以注册并使用智谱AI的云端大模型,智谱提供可免费使用的GLM Flash模型推理服务。\",\n \"provider_glm_sentence_2\": \"点击这里申请\",\n \"provider_glm_sentence_3\": \"输入API KEY\",\n \"provider_openai\": \"自定义云端大模型(与OpenAI接口兼容)\",\n \"provider_openai_sentence_1\": \"大多数大模型服务与OpenAI兼容,输入对应的配置信息即可\",\n \"provider_openai_sentence_2\": \"输入大模型服务地址\",\n \"provider_openai_sentence_3\": \"输入大模型供应商授权的API Key\",\n \"provider_openai_sentence_4\": \"输入模型名称\",\n \"provider_barton\": \"巴顿引擎(本地大模型)\",\n \"provider_barton_sentence_1\": \"(内侧中)自研的巴顿引擎推理速度快且占用内存极小,具备极佳的数据隐私安全性,也不需要额外安装其他程序。\",\n \"provider_barton_sentence_2\": \"模型文件路径\",\n \"provider_barton_sentence_3\": \"输入模型文件路径\"\n },\n \"section_llm_instruct\": {\n \"label\": \"AI行为偏好\",\n \"lang\": {\n \"label\": \"自动翻译为目标语言\",\n \"description\": \"当获取的内容语言为其他语种时,会自动翻译为设置的语种。\",\n \"as_system\": \"跟随系统\",\n \"english\": \"英文\",\n \"chinese\": \"中文\"\n }\n },\n \"section_app_behavior\": {\n \"label\": \"应用行为\",\n \"option_autostart\": {\n \"label\": \"开机自启动\",\n \"description\": \"启用该选项会在系统启动时自动执行订阅内容更新。如果关闭该选项,则您需要手动启动程序后才能自动更新订阅内容。\"\n },\n \"option_scheduled_fetch\": {\n \"label\": \"更快的后台更新\",\n \"description\": \"启用该选项有助于更快的更新您的订阅内容。\"\n }\n },\n \"section_users_support\": {\n \"label\": \"用户服务\",\n \"visit_home\": \"访问官网\",\n \"feedback\": \"用户反馈\",\n \"blogs\": \"产品博客\",\n \"changelogs\": \"更新日志\"\n },\n \"section_version\": {\n \"label\": \"版本信息\",\n \"ver_app\": \"应用版本\",\n \"ver_engine\": \"引擎版本\",\n \"ver_system\": \"系统信息\"\n }\n },\n \"common_dialog\": {\n \"save\": \"保存更改\",\n \"cancel\": \"取消\"\n },\n \"about\": {\n \"ver_app\": \"应用版本\",\n \"ver_engine\": \"引擎版本\",\n \"visit_home\": \"访问官网\"\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 183, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是一个标准的JSON格式国际化(i18n)语言包,用于存储应用程序的中文界面文本。其结构按功能模块组织,如 common、main、reader、settings 等,每个模块下定义了对应的用户可见字符串,包括按钮标签、提示信息、菜单名称、对话框文本等。该文件不包含任何业务逻辑或可执行代码,纯粹作为资源配置使用,由前端框架在运行时根据当前语言环境动态加载并注入到UI组件中。", + "interfaces": [], + "responsibilities": [ + "提供完整的中文用户界面文本资源", + "支持多语言切换下的文案映射", + "按功能模块组织翻译内容以提高可维护性", + "为表单验证、错误提示、操作反馈等场景提供本地化消息" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "英文语言包配置文件,包含应用所有用户界面的国际化文本内容。", + "file_path": "app/src/lib/i18n/locales/en.json", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "en.json", + "source_summary": "{\n \"common\": {\n \"product_name\": \"Saga Reader\",\n \"product_slogan\": \"Your AI-Powered think tank assistant\",\n \"product_tip\": \"Start your journey of intelligent reading\"\n },\n \"main\": {\n \"menu\": {\n \"create_feeds_package\": \"Add\",\n \"settings\": \"Settings\"\n },\n \"section_frequently_used\": {\n \"label\": \"Frequently Used\",\n \"menu\": {\n \"today\": \"Today\",\n \"this_week\": \"This Week\",\n \"favorites\": \"Favorites\",\n \"unread\": \"Unread\"\n }\n },\n \"feeds\": {\n \"menu\": {\n \"actions\": {\n \"create\": \"New\",\n \"edit\": \"Edit\",\n \"delete\": \"Delete\",\n \"delete_prompt\": \"Do you want to delete the subscription package {name}? All {length} subscription columns under this subscription package will be removed.\",\n \"delete_dialog_title\": \"Delete the subscription package\"\n }\n },\n \"create_or_edit\": {\n \"field_feeds_package_name\": \"Subscription Group Name\",\n \"field_feeds_package_placeholder\": \"Please fill in the name of the subscription group, preferably within 8 Chinese characters.\",\n \"tip_modify_failured\": \"Modification failed. Please check if the form fields are filled in correctly. {e}\",\n \"tip_footer\": \"Note: Subscription group names should be unique.\"\n }\n },\n \"section_subscriptions\": {\n \"label\": \"Subscriptions\"\n },\n \"feed\": {\n \"menu\": {\n \"actions\": {\n \"edit\": \"Edit\",\n \"delete\": \"Delete\",\n \"delete_prompt\": \"Do you want to delete the subscription {name}?\",\n \"delete_dialog_title\": \"Delete the subscription\"\n }\n },\n \"create_or_edit\": {\n \"field_feed_name\": \"Subscription Name\",\n \"field_feed_placeholder\": \"Please fill in the name of the subscription, preferably within 8 Chinese characters.\",\n \"field_fetcher_type_name\": \"Information Source\",\n \"field_fetcher_type_selection_1\": \"Barton Engine (Global Intelligence Detection Engine)\",\n \"field_fetcher_type_selection_2\": \"RSS Subscription\",\n \"field_keywords\": \"Keywords\",\n \"field_rss_url\": \"RSS Address\",\n \"tip_unknown_fetcher\": \"Unknown Fetcher: {formFetcherId}\",\n \"field_keywords_placeholder\": \"Please fill in the information keywords. Multiple keywords can be separated by spaces, just like using a search engine.\",\n \"field_rss_url_placeholder\": \"Please fill in the RSS address.\",\n \"tip_modify_failured\": \"Modification failed. Please check if the form fields are filled in correctly. {e}\",\n \"tip_footer\": \"Note: Subscription names should be distinct from existing ones.\"\n }\n },\n \"search\": {\n \"results_label\": \"Search Results\",\n \"placeholder_input\": \"Search\"\n },\n \"articles\": {\n \"tip_click_to_load_more\": \"Click to load more\",\n \"tip_loading\": \"Loading\",\n \"error_retry\": \"Click to retry\",\n \"tip_empty_try_again\": \"No articles. Click to update\",\n \"tip_empty\": \"No articles\"\n },\n \"footer\": {\n \"tasks\": {\n \"label\": \"Background Tasks\",\n \"idle\": \"No tasks running currently.\",\n \"status_summary_part1\": \"In Processing\",\n \"status_summary_part2\": \"Items\",\n \"status_ready\": \"Ready\",\n \"status_error\": \"Error occurred, click to view details\"\n }\n }\n },\n \"reader\": {\n \"tab_optimized_content\": \"Glance\",\n \"tab_melted_content\": \"Summarize\",\n \"tab_melted_original\": \"Original\",\n \"tip_link_copyed\": \"The link has been copied\",\n \"blank_tip_0\": \"Please select the subscription content\",\n \"blank_tip_1\": \"1.Add a subscription topic.\",\n \"blank_tip_2\": \"2.Refresh the subscription content list.\",\n \"blank_tip_3\": \"3.Click on the title of the subscription content.\"\n },\n \"aisprite\": {\n \"label\": \"AI Companion Reading\",\n \"chat_me\": \"Me\",\n \"tip_wait_llm_response\": \"Please wait for Copilot to finish thinking.\",\n \"tip_no_input\": \"Please enter the content\",\n \"tip_error_llm_error\": \"An exception occurred\",\n \"tip_placeholder_please_input\": \"Learn about something from Copilot\"\n },\n \"settings\": {\n \"label\": \"Settings\",\n \"loading\": \"Loading...\",\n \"section_llm_appearance\": {\n \"label\": \"Apperience\",\n \"theme\": {\n \"label\": \"Dark Mode\",\n \"description\": \"Turn on to use the Dark Night, turn off to use the White Moonlight.\"\n }\n },\n \"section_llm_provider\": {\n \"label\": \"AI Configuration\",\n \"tip\": \"Select the AI Provider\",\n \"provider_ollama\": \"Ollama (Local Deploy)\",\n \"provider_ollama_tip\": \"Ollama can be deployed locally on your device, providing a private model suitable for your hardware device and excellent data privacy and security. You need to install Ollama first.\",\n \"provider_ollama_sentence_1\": \"Click here to download\",\n \"provider_ollama_sentence_2\": \"Ollama Service URL\",\n \"provider_ollama_sentence_3\": \"Model Name\",\n \"provider_ollama_sentence_4\": \"Please fill in the model name, for example, \\\"qwen2.5:3b\\\"\",\n \"provider_ollama_sentence_5\": \"The default is `http://localhost:11434`.\",\n \"provider_glm\": \"GLM Flash (Cloud-based)\",\n \"provider_glm_sentence_1\": \"You can register and use the cloud-based AI of GLM. It provides a free GLM Flash model inference service.\",\n \"provider_glm_sentence_2\": \"Click here to apply\",\n \"provider_glm_sentence_3\": \"Input API KEY\",\n \"provider_openai\": \"Custom AI(Compatible with OpenAI)\",\n \"provider_openai_sentence_1\": \"Most large model services are compatible with OpenAI; just enter the configuration.\",\n \"provider_openai_sentence_2\": \"Enter the large model service URL\",\n \"provider_openai_sentence_3\": \"Enter the API Key authorized by the large model provider\",\n \"provider_openai_sentence_4\": \"Enter the model name\",\n \"provider_barton\": \"Barton Engine (Local Integrated)\",\n \"provider_barton_sentence_1\": \"(In beta) The self-developed Barton engine has a fast inference speed and extremely low memory usage, and it has excellent data privacy and security\",\n \"provider_barton_sentence_2\": \"Model File Path\",\n \"provider_barton_sentence_3\": \"Enter the model file path\"\n },\n \"section_llm_instruct\": {\n \"label\": \"AI Behavior Preferences\",\n \"lang\": {\n \"label\": \"Auto-translate to\",\n \"description\": \"When the content language is different, it will be automatically translated.\",\n \"as_system\": \"Follow system\",\n \"english\": \"English\",\n \"chinese\": \"Chinese\"\n }\n },\n \"section_app_behavior\": {\n \"label\": \"Application Behavior\",\n \"option_autostart\": {\n \"label\": \"Launch deamon on System Boot\",\n \"description\": \"Enabling this option will automatically execute the subscription content update when the system starts. If this option is disabled, you need to manually start the program before the subscription content can be updated automatically.\"\n },\n \"option_scheduled_fetch\": {\n \"label\": \"Faster Background Update\",\n \"description\": \"Enabling this option helps to update your subscription content more quickly.\"\n }\n },\n \"section_users_support\": {\n \"label\": \"Product Support\",\n \"visit_home\": \"Website\",\n \"feedback\": \"Feedback\",\n \"blogs\": \"Blogs\",\n \"changelogs\": \"Changelogs\"\n },\n \"section_version\": {\n \"label\": \"Information\",\n \"ver_app\": \"App Version\",\n \"ver_engine\": \"Engine Version\",\n \"ver_system\": \"System Information\"\n }\n },\n \"common_dialog\": {\n \"save\": \"Save\",\n \"cancel\": \"Cancel\"\n },\n \"about\": {\n \"ver_app\": \"App Version\",\n \"ver_engine\": \"Engine Version\",\n \"visit_home\": \"Visit Website\"\n }\n}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 6.0, + "depth_of_inheritance": 0, + "lines_of_code": 183, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是一个JSON格式的国际化语言配置文件,用于存储Saga Reader应用的英文用户界面文本。它按照功能模块(如common、main、reader、settings等)组织键值对,覆盖了产品名称、菜单项、对话框按钮、表单提示、状态消息等UI元素的显示文本。支持动态占位符(如{name}、{length}、{e}),允许在运行时注入变量值。该文件是i18n系统的核心资源之一,与前端框架结合实现多语言切换。", + "interfaces": [], + "responsibilities": [ + "提供应用界面的英文文本资源", + "支持多语言国际化(i18n)功能", + "管理UI元素的静态文案和动态提示信息", + "通过结构化键路径组织语言资源便于维护" + ] + }, + { + "code_dossier": { + "code_purpose": "config", + "description": "国际化语言设置配置模块,用于获取浏览器语言并提供默认和备用语言选项", + "file_path": "app/src/lib/i18n/settings.ts", + "functions": [ + "getLocale", + "setLocale" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "settings.ts", + "source_summary": "import { browser } from \"$app/environment\";\n\nconst defaultLocale = \"zh\";\nconst fallbackLocale = \"en\";\n\nfunction getLocale() {\n return browser ? window.navigator.language : defaultLocale;\n}\n\nfunction setLocale() {}\n\nexport { getLocale, setLocale, defaultLocale, fallbackLocale };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.8, + "coupling_factor": 0.5, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 12, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "import", + "is_external": true, + "line_number": 1, + "name": "$app/environment", + "path": "$app/environment", + "version": null + } + ], + "detailed_description": "该组件是SvelteKit应用中的国际化(i18n)配置模块,主要负责语言环境的初始化设置。在浏览器环境中,通过window.navigator.language获取用户首选语言;在服务端则返回默认中文(zh)。提供了默认语言和备用语言的常量定义,并导出了获取当前语言和设置语言的函数接口,为应用的多语言支持提供基础配置。", + "interfaces": [], + "responsibilities": [ + "管理应用的默认和备用语言配置", + "根据运行环境获取用户的语言偏好", + "提供语言设置的基础API接口", + "支持SSR/CSR环境下的语言检测" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "一个用于保存操作的Svelte前端UI组件,包含保存和取消按钮。", + "file_path": "app/src/lib/widgets/SaveOperatePanel.svelte", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "onSave: MouseEventHandler", + "onCancel: MouseEventHandler", + "canSave: boolean" + ], + "name": "SaveOperatePanel.svelte", + "source_summary": "\n\n
\n\t\n
\n" + }, + "complexity_metrics": { + "cohesion_score": 0.9, + "coupling_factor": 0.15, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 21, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [ + { + "dependency_type": "i18n", + "is_external": true, + "line_number": 1, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + }, + { + "dependency_type": "type", + "is_external": true, + "line_number": 2, + "name": "svelte/elements", + "path": "svelte/elements", + "version": null + } + ], + "detailed_description": "该组件是一个轻量级的Svelte UI组件,主要用于呈现保存与取消操作按钮。它通过props接收三个参数:onSave(点击保存时触发的回调函数)、onCancel(点击取消时触发的回调函数)以及canSave(控制保存按钮是否可交互的布尔值)。保存按钮使用国际化文本$_('common_dialog.save'),取消按钮使用$_('common_dialog.cancel')。布局采用Flexbox实现右对齐排列,并添加间距。保存按钮在canSave为false时被禁用。", + "interfaces": [ + { + "description": "保存操作的回调函数", + "interface_type": "function", + "name": "onSave", + "parameters": [ + { + "description": "鼠标事件对象", + "is_optional": false, + "name": "event", + "param_type": "MouseEventHandler" + } + ], + "return_type": "void", + "visibility": "public" + }, + { + "description": "取消操作的回调函数", + "interface_type": "function", + "name": "onCancel", + "parameters": [ + { + "description": "鼠标事件对象", + "is_optional": false, + "name": "event", + "param_type": "MouseEventHandler" + } + ], + "return_type": "void", + "visibility": "public" + }, + { + "description": "控制保存按钮是否可用", + "interface_type": "property", + "name": "canSave", + "parameters": [], + "return_type": "boolean", + "visibility": "public" + } + ], + "responsibilities": [ + "提供保存和取消操作的UI按钮", + "根据canSave状态控制保存按钮的启用/禁用状态", + "处理用户点击事件并调用传入的回调函数", + "支持多语言显示文本", + "保持简洁的操作面板布局" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "定义前端UI组件所需的数据结构和类型,支持Markdown渲染、HTML内容展示及嵌入式WebView功能。", + "file_path": "app/src/lib/widgets/types.ts", + "functions": [], + "importance_score": 0.6, + "interfaces": [ + "MarkdownProps", + "ArticleRenderProps", + "EmbedWebViewProps", + "ArticleRenderType" + ], + "name": "types.ts", + "source_summary": "interface MarkdownProps {\n\tvalue: string;\n}\n\ntype ArticleRenderProps = MarkdownProps;\ntype ArticleRenderType = 'markdown' | 'html';\n\ninterface EmbedWebViewProps {\n\tsrc: string;\n\tonLoadStart?: (src: string) => void;\n\tonLoadEnd?: (src: string) => void;\n}\n\nexport type { EmbedWebViewProps, MarkdownProps, ArticleRenderProps, ArticleRenderType };\n" + }, + "complexity_metrics": { + "cohesion_score": 0.95, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 14, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该文件是一个TypeScript类型定义文件,主要用于声明前端UI组件(特别是富文本和嵌入式内容展示)所需的接口与联合类型。其中,MarkdownProps用于传递Markdown内容字符串;ArticleRenderProps是其同名类型别名,表明可复用性设计;ArticleRenderType为字面量联合类型,用于区分内容渲染方式(markdown或html);EmbedWebViewProps则定义了嵌入式WebView的属性,包括源地址和可选的加载生命周期回调函数。所有类型均通过export type导出,供其他组件安全引用。", + "interfaces": [ + { + "description": "描述包含Markdown字符串值的对象结构", + "interface_type": "interface", + "name": "MarkdownProps", + "parameters": [ + { + "description": "要渲染的Markdown格式文本内容", + "is_optional": false, + "name": "value", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "exported" + }, + { + "description": "MarkdownProps的类型别名,用于语义化区分用途", + "interface_type": "type", + "name": "ArticleRenderProps", + "parameters": [], + "return_type": "MarkdownProps", + "visibility": "exported" + }, + { + "description": "表示文章渲染方式的字面量联合类型", + "interface_type": "type", + "name": "ArticleRenderType", + "parameters": [], + "return_type": "'markdown' | 'html'", + "visibility": "exported" + }, + { + "description": "定义嵌入式WebView的行为配置属性", + "interface_type": "interface", + "name": "EmbedWebViewProps", + "parameters": [ + { + "description": "嵌入网页的URL地址", + "is_optional": false, + "name": "src", + "param_type": "string" + }, + { + "description": "页面开始加载时触发的回调", + "is_optional": true, + "name": "onLoadStart", + "param_type": "(src: string) => void" + }, + { + "description": "页面加载完成时触发的回调", + "is_optional": true, + "name": "onLoadEnd", + "param_type": "(src: string) => void" + } + ], + "return_type": null, + "visibility": "exported" + } + ], + "responsibilities": [ + "定义Markdown内容渲染所需的属性结构", + "提供文章内容渲染类型的枚举支持(markdown/html)", + "声明嵌入式WebView组件的输入参数及事件回调机制", + "促进类型安全的跨组件通信", + "减少重复类型声明,提升代码可维护性" + ] + }, + { + "code_dossier": { + "code_purpose": "widget", + "description": "一个用于渲染 Markdown 图像的 Svelte 组件,支持错误处理和备用文本显示。", + "file_path": "app/src/lib/widgets/MarkdownImg.svelte", + "functions": [ + "onerror" + ], + "importance_score": 0.6, + "interfaces": [ + "Props" + ], + "name": "MarkdownImg.svelte", + "source_summary": "\n\n{#if !error}\n {text}\n{/if}\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.0, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 19, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [], + "detailed_description": "该组件是一个轻量级的 Svelte UI 组件,旨在安全地渲染由 Markdown 生成的图像标签。它接收可选的 href(图像源)、title 和 alt 文本(通过 text 传递),并在图像加载失败时触发 onerror 回调,将 error 状态设置为 true,从而防止损坏的图像影响用户体验。当发生错误时,整个 img 标签不会被渲染(通过 {#if !error} 控制)。此外,组件使用 $props() 自动解构传入的属性,并利用 Svelte 的反应式 $state 实现内部状态管理。", + "interfaces": [ + { + "description": "定义组件接受的所有可选输入属性", + "interface_type": "interface", + "name": "Props", + "parameters": [ + { + "description": "图像的源地址,对应 标签的 src 属性", + "is_optional": true, + "name": "href", + "param_type": "string" + }, + { + "description": "图像的标题提示,对应 title 属性", + "is_optional": true, + "name": "title", + "param_type": "string" + }, + { + "description": "图像的替代文本,对应 alt 属性", + "is_optional": true, + "name": "text", + "param_type": "string" + } + ], + "return_type": null, + "visibility": "public" + }, + { + "description": "图像加载失败时的事件处理器,设置 error 状态并输出警告日志", + "interface_type": "function", + "name": "onerror", + "parameters": [], + "return_type": "void", + "visibility": "private" + } + ], + "responsibilities": [ + "接收并解析图像相关的属性(src, title, alt)", + "实现图像加载失败的错误处理机制", + "通过条件渲染避免显示损坏的图像", + "提供基础的用户反馈(控制台警告)", + "保持轻量和可复用性作为UI组件" + ] + }, + { + "code_dossier": { + "code_purpose": "middleware", + "description": "SvelteKit服务端钩子文件,集成Sentry错误监控并处理国际化语言设置", + "file_path": "app/src/hooks.server.ts", + "functions": [ + "handle", + "handleError" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "hooks.server.ts", + "source_summary": "import type { Handle } from '@sveltejs/kit';\nimport { sequence } from '@sveltejs/kit/hooks';\nimport { handleErrorWithSentry, sentryHandle } from '@sentry/sveltekit';\nimport * as Sentry from '@sentry/sveltekit';\nimport { locale } from 'svelte-i18n';\n\nSentry.init({\n\tdsn: 'https://19ca433cd275a680d5e35857bc289cb0@o83602.ingest.us.sentry.io/4507827211862016',\n\ttracesSampleRate: 1.0\n\n\t// uncomment the line below to enable Spotlight (https://spotlightjs.com)\n\t// spotlight: import.meta.env.DEV,\n});\n\n// If you have custom handlers, make sure to place them after `sentryHandle()` in the `sequence` function.\nexport const handle: Handle = sequence(sentryHandle(), async ({ event, resolve }) => {\n\tconst lang = event.request.headers.get('accept-language')?.split(',')[0];\n\tif (lang) {\n\t\tlocale.set(lang);\n\t}\n\treturn resolve(event);\n});\n\n// If you have a custom error handler, pass it to `handleErrorWithSentry`\nexport const handleError = handleErrorWithSentry();\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.6, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 25, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "framework", + "is_external": true, + "line_number": 1, + "name": "@sveltejs/kit", + "path": null, + "version": null + }, + { + "dependency_type": "monitoring", + "is_external": true, + "line_number": 3, + "name": "@sentry/sveltekit", + "path": null, + "version": null + }, + { + "dependency_type": "internationalization", + "is_external": true, + "line_number": 5, + "name": "svelte-i18n", + "path": null, + "version": null + } + ], + "detailed_description": "该组件是SvelteKit应用的服务端钩子(hooks),主要负责两个核心功能:一是初始化Sentry性能监控和错误追踪系统,配置DSN和采样率;二是通过HTTP请求头中的accept-language字段动态设置国际化语言环境。组件使用sequence组合多个handle处理器,确保Sentry的中间件优先执行,然后处理语言本地化逻辑。", + "interfaces": [], + "responsibilities": [ + "初始化Sentry监控系统并配置DSN和追踪采样率", + "作为请求处理中间件链的一部分,处理进入的HTTP请求", + "从请求头提取accept-language信息并设置当前locale", + "集成Sentry错误处理机制,捕获和上报运行时异常", + "维护应用的可观测性和错误监控能力" + ] + }, + { + "code_dossier": { + "code_purpose": "router", + "description": "SvelteKit布局加载函数,用于初始化国际化并设置浏览器语言环境", + "file_path": "app/src/routes/+layout.ts", + "functions": [ + "load" + ], + "importance_score": 0.6, + "interfaces": [], + "name": "+layout.ts", + "source_summary": "import '$lib/i18n'; // Import to initialize. Important :)\nimport { browser } from '$app/environment';\nimport { locale, waitLocale } from 'svelte-i18n';\nimport type { LayoutLoad } from './$types';\n\nexport const prerender = true;\n\nexport const load: LayoutLoad = async () => {\n\tif (browser) {\n\t\tlocale.set(window.navigator.language);\n\t}\n\tawait waitLocale();\n};\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.3076923076923077, + "cyclomatic_complexity": 2.0, + "depth_of_inheritance": 0, + "lines_of_code": 13, + "number_of_classes": 0, + "number_of_functions": 1 + }, + "dependencies": [ + { + "dependency_type": "initialization", + "is_external": false, + "line_number": 1, + "name": "$lib/i18n", + "path": "$lib/i18n", + "version": null + }, + { + "dependency_type": "environment", + "is_external": true, + "line_number": 2, + "name": "$app/environment", + "path": "$app/environment", + "version": null + }, + { + "dependency_type": "internationalization", + "is_external": true, + "line_number": 3, + "name": "svelte-i18n", + "path": "svelte-i18n", + "version": null + }, + { + "dependency_type": "typing", + "is_external": false, + "line_number": 4, + "name": "./$types", + "path": "./$types", + "version": null + } + ], + "detailed_description": "该组件是SvelteKit应用中的布局级加载器(+layout.ts),在页面渲染前执行。其主要功能是在客户端环境中初始化国际化支持:检测浏览器的默认语言并设置当前locale,然后等待本地化资源加载完成。通过await waitLocale()确保所有i18n资源准备就绪后再渲染页面内容,避免出现未翻译的文本。prerender设为true表示该布局可被预渲染。", + "interfaces": [], + "responsibilities": [ + "初始化应用的国际化系统", + "根据浏览器语言自动设置当前locale", + "等待本地化资源加载完成以确保正确渲染", + "配置布局的预渲染行为", + "作为路由布局的入口加载逻辑" + ] + }, + { + "code_dossier": { + "code_purpose": "page", + "description": null, + "file_path": "app/src/routes/+page.svelte", + "functions": [], + "importance_score": 0.6, + "interfaces": [], + "name": "+page.svelte", + "source_summary": "" + }, + "complexity_metrics": { + "cohesion_score": 1.0, + "coupling_factor": 0.0, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 0, + "number_of_classes": 0, + "number_of_functions": 0 + }, + "dependencies": [], + "detailed_description": "该组件是一个Svelte框架下的路由页面组件,用于定义特定路由的UI和逻辑。但由于源代码为空,实际功能无法确定,可能为占位符或待实现页面。", + "interfaces": [], + "responsibilities": [ + "作为应用中某个路由的展示页面入口", + "负责渲染该路径下的用户界面内容", + "可能承载数据加载与状态管理逻辑(当前未实现)" + ] + }, + { + "code_dossier": { + "code_purpose": "router", + "description": "SvelteKit路由布局组件,负责应用主题的初始化与系统级暗黑模式监听。", + "file_path": "app/src/routes/+layout.svelte", + "functions": [ + "onMount" + ], + "importance_score": 0.6, + "interfaces": [ + "themeListener" + ], + "name": "+layout.svelte", + "source_summary": "\n\n\n" + }, + "complexity_metrics": { + "cohesion_score": 0.85, + "coupling_factor": 0.15, + "cyclomatic_complexity": 1.0, + "depth_of_inheritance": 0, + "lines_of_code": 20, + "number_of_classes": 0, + "number_of_functions": 2 + }, + "dependencies": [ + { + "dependency_type": "framework", + "is_external": true, + "line_number": 2, + "name": "svelte", + "path": null, + "version": null + }, + { + "dependency_type": "library", + "is_external": false, + "line_number": 3, + "name": "$lib/themes", + "path": "$lib/themes", + "version": null + }, + { + "dependency_type": "stylesheet", + "is_external": false, + "line_number": 1, + "name": "app.css", + "path": "app/src/app.css", + "version": null + } + ], + "detailed_description": "该组件是SvelteKit应用的根布局组件,主要职责是在页面挂载时初始化UI主题。通过监听`prefers-color-scheme`媒体查询,动态响应用户的系统级深色/浅色模式偏好,并调用`$lib/themes`中的`applyTheme`和`setWebInnerOnly`函数进行主题应用与状态同步。使用`onMount`确保仅在客户端执行DOM相关操作,并正确清理事件监听器以避免内存泄漏。", + "interfaces": [ + { + "description": "响应系统暗黑模式切换的事件处理器", + "interface_type": "function", + "name": "themeListener", + "parameters": [ + { + "description": "媒体查询状态变更事件", + "is_optional": false, + "name": "event", + "param_type": "MediaQueryListEvent" + } + ], + "return_type": "void", + "visibility": "private" + } + ], + "responsibilities": [ + "监听系统颜色偏好变化以实现自动主题切换", + "初始化应用的主题配置", + "管理主题相关的事件监听器生命周期", + "作为路由布局容器提供内容渲染" + ] + } +] +``` + +## Memory存储统计 + +**总存储大小**: 870629 bytes + +- **studies_research**: 64147 bytes (7.4%) +- **preprocess**: 690819 bytes (79.3%) +- **timing**: 38 bytes (0.0%) +- **documentation**: 115625 bytes (13.3%) + +## 生成文档统计 + +生成文档数量: 9 个 + +- 核心模块与组件调研报告_用户界面域 +- 核心流程 +- 核心模块与组件调研报告_状态管理域 +- 核心模块与组件调研报告_系统启动与配置域 +- 项目概述 +- 核心模块与组件调研报告_AI能力集成域 +- 核心模块与组件调研报告_内容获取与处理域 +- 核心模块与组件调研报告_数据持久化域 +- 架构说明