entari-plugin-hyw 4.0.0rc9__py3-none-any.whl → 4.0.0rc11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of entari-plugin-hyw might be problematic. Click here for more details.
- entari_plugin_hyw/__init__.py +76 -39
- {entari_plugin_hyw-4.0.0rc9.dist-info → entari_plugin_hyw-4.0.0rc11.dist-info}/METADATA +1 -1
- {entari_plugin_hyw-4.0.0rc9.dist-info → entari_plugin_hyw-4.0.0rc11.dist-info}/RECORD +16 -14
- hyw_core/browser_control/__init__.py +1 -3
- hyw_core/browser_control/assets/card-dist/index.html +48 -32
- hyw_core/browser_control/engines/__init__.py +0 -2
- hyw_core/browser_control/manager.py +18 -5
- hyw_core/browser_control/renderer.py +36 -6
- hyw_core/browser_control/service.py +245 -142
- hyw_core/core.py +0 -7
- hyw_core/crawling/__init__.py +18 -0
- hyw_core/crawling/completeness.py +437 -0
- hyw_core/crawling/models.py +88 -0
- hyw_core/search.py +4 -6
- hyw_core/browser_control/engines/google.py +0 -155
- {entari_plugin_hyw-4.0.0rc9.dist-info → entari_plugin_hyw-4.0.0rc11.dist-info}/WHEEL +0 -0
- {entari_plugin_hyw-4.0.0rc9.dist-info → entari_plugin_hyw-4.0.0rc11.dist-info}/top_level.txt +0 -0
entari_plugin_hyw/__init__.py
CHANGED
|
@@ -108,6 +108,13 @@ def parse_filter_syntax(query: str, max_count: int = 3):
|
|
|
108
108
|
if total > max_count:
|
|
109
109
|
return [], search_query, f"最多选择{max_count}个结果 (当前选择了{total}个)"
|
|
110
110
|
|
|
111
|
+
# Append filter names to search query
|
|
112
|
+
# Extract filter names (only 'link' type, skip 'index' type)
|
|
113
|
+
filter_names = [f[1] for f in filters if f[0] == 'link']
|
|
114
|
+
if filter_names:
|
|
115
|
+
# Append filter names to search query: "search_query filter1 filter2"
|
|
116
|
+
search_query = f"{search_query} {' '.join(filter_names)}"
|
|
117
|
+
|
|
111
118
|
return filters, search_query, None
|
|
112
119
|
|
|
113
120
|
|
|
@@ -162,6 +169,7 @@ class HywConfig(BasicConfModel):
|
|
|
162
169
|
admins: List[str] = field(default_factory=list)
|
|
163
170
|
models: List[Dict[str, Any]] = field(default_factory=list)
|
|
164
171
|
question_command: str = "/q"
|
|
172
|
+
web_command: str = "/w"
|
|
165
173
|
language: str = "Simplified Chinese"
|
|
166
174
|
temperature: float = 0.4
|
|
167
175
|
|
|
@@ -169,7 +177,7 @@ class HywConfig(BasicConfModel):
|
|
|
169
177
|
api_key: Optional[str] = None
|
|
170
178
|
base_url: str = "https://openrouter.ai/api/v1"
|
|
171
179
|
|
|
172
|
-
search_engine: str = "
|
|
180
|
+
search_engine: str = "duckduckgo"
|
|
173
181
|
|
|
174
182
|
headless: bool = False
|
|
175
183
|
save_conversation: bool = False
|
|
@@ -177,19 +185,14 @@ class HywConfig(BasicConfModel):
|
|
|
177
185
|
quote: bool = False
|
|
178
186
|
theme_color: str = "#ff0000"
|
|
179
187
|
|
|
180
|
-
#
|
|
188
|
+
# Main model configuration (used for summary/main LLM calls)
|
|
181
189
|
main: Optional[Dict[str, Any]] = None
|
|
182
|
-
instruct: Optional[Dict[str, Any]] = None
|
|
183
|
-
vision: Optional[Dict[str, Any]] = None
|
|
184
|
-
deepsearch_instruct: Optional[Dict[str, Any]] = None
|
|
185
|
-
deepsearch_agent: Optional[Dict[str, Any]] = None
|
|
186
190
|
|
|
187
191
|
def __post_init__(self):
|
|
188
192
|
self.theme_color = parse_color(self.theme_color)
|
|
189
193
|
|
|
190
194
|
def to_hyw_core_config(self) -> HywCoreConfig:
|
|
191
195
|
main_cfg = self.main or {}
|
|
192
|
-
instruct_cfg = self.instruct or {}
|
|
193
196
|
|
|
194
197
|
return HywCoreConfig.from_dict({
|
|
195
198
|
"models": self.models,
|
|
@@ -207,20 +210,7 @@ class HywConfig(BasicConfModel):
|
|
|
207
210
|
"summary_api_key": main_cfg.get("api_key"),
|
|
208
211
|
"summary_base_url": main_cfg.get("base_url"),
|
|
209
212
|
"summary_extra_body": main_cfg.get("extra_body"),
|
|
210
|
-
|
|
211
|
-
# Map nested 'instruct' config to instruct stage
|
|
212
|
-
"instruct_model": instruct_cfg.get("model_name"),
|
|
213
|
-
"instruct_api_key": instruct_cfg.get("api_key"),
|
|
214
|
-
"instruct_base_url": instruct_cfg.get("base_url"),
|
|
215
|
-
"instruct_extra_body": instruct_cfg.get("extra_body"),
|
|
216
213
|
})
|
|
217
|
-
|
|
218
|
-
def get_model_config(self, stage: str) -> Dict[str, Any]:
|
|
219
|
-
return {
|
|
220
|
-
"model_name": self.model_name,
|
|
221
|
-
"api_key": self.api_key,
|
|
222
|
-
"base_url": self.base_url,
|
|
223
|
-
}
|
|
224
214
|
|
|
225
215
|
|
|
226
216
|
conf = plugin_config(HywConfig)
|
|
@@ -229,12 +219,11 @@ renderer = ContentRenderer(headless=conf.headless)
|
|
|
229
219
|
set_global_renderer(renderer)
|
|
230
220
|
search_cache = SearchResultCache(ttl_seconds=600.0) # 10 minutes
|
|
231
221
|
|
|
232
|
-
|
|
222
|
+
# Initialize HywCore immediately at plugin load time (not lazy)
|
|
223
|
+
# This avoids the 2s delay on first user request caused by AsyncOpenAI client creation
|
|
224
|
+
_hyw_core: HywCore = HywCore(conf.to_hyw_core_config())
|
|
233
225
|
|
|
234
226
|
def get_hyw_core() -> HywCore:
|
|
235
|
-
global _hyw_core
|
|
236
|
-
if _hyw_core is None:
|
|
237
|
-
_hyw_core = HywCore(conf.to_hyw_core_config())
|
|
238
227
|
return _hyw_core
|
|
239
228
|
|
|
240
229
|
|
|
@@ -690,7 +679,7 @@ async def handle_question_command(session: Session[MessageCreatedEvent], result:
|
|
|
690
679
|
|
|
691
680
|
|
|
692
681
|
# Search/Web Command (/w)
|
|
693
|
-
alc_search = Alconna(
|
|
682
|
+
alc_search = Alconna(conf.web_command, Args["query;?", AllParam])
|
|
694
683
|
|
|
695
684
|
@command.on(alc_search)
|
|
696
685
|
async def handle_web_command(session: Session[MessageCreatedEvent], result: Arparma):
|
|
@@ -756,6 +745,17 @@ async def handle_web_command(session: Session[MessageCreatedEvent], result: Arpa
|
|
|
756
745
|
|
|
757
746
|
search_cache.cleanup()
|
|
758
747
|
return
|
|
748
|
+
else:
|
|
749
|
+
# Reply to a non-cached message: append reply content to query
|
|
750
|
+
try:
|
|
751
|
+
# session.reply.origin.message is a list, wrap it in MessageChain
|
|
752
|
+
reply_msg = MessageChain(session.reply.origin.message)
|
|
753
|
+
reply_content = str(reply_msg.get(Text)).strip()
|
|
754
|
+
if reply_content:
|
|
755
|
+
query = f"{query} {reply_content}".strip() if query else reply_content
|
|
756
|
+
logger.info(f"/w appended reply content, new query: '{query}'")
|
|
757
|
+
except Exception as e:
|
|
758
|
+
logger.warning(f"/w failed to extract reply content: {e}")
|
|
759
759
|
|
|
760
760
|
# No query and no cache context - nothing to do
|
|
761
761
|
if not query:
|
|
@@ -805,9 +805,15 @@ async def handle_web_command(session: Session[MessageCreatedEvent], result: Arpa
|
|
|
805
805
|
await session.send(filter_error)
|
|
806
806
|
return
|
|
807
807
|
|
|
808
|
-
#
|
|
808
|
+
# Start search first
|
|
809
|
+
local_renderer = await get_content_renderer()
|
|
809
810
|
search_task = asyncio.create_task(core.search([search_query]))
|
|
810
811
|
|
|
812
|
+
# Only pre-warm tab if NOT in filter mode (filter mode = screenshots only, no card render)
|
|
813
|
+
tab_task = None
|
|
814
|
+
if not filters:
|
|
815
|
+
tab_task = asyncio.create_task(local_renderer.prepare_tab())
|
|
816
|
+
|
|
811
817
|
if conf.reaction:
|
|
812
818
|
asyncio.create_task(react(session, "🔍"))
|
|
813
819
|
|
|
@@ -815,17 +821,24 @@ async def handle_web_command(session: Session[MessageCreatedEvent], result: Arpa
|
|
|
815
821
|
flat_results = results[0] if results else []
|
|
816
822
|
|
|
817
823
|
if not flat_results:
|
|
824
|
+
if tab_task:
|
|
825
|
+
try: await tab_task
|
|
826
|
+
except: pass
|
|
818
827
|
await session.send("Search returned no results.")
|
|
819
828
|
return
|
|
820
829
|
|
|
821
830
|
visible = [r for r in flat_results if not r.get("_hidden", False)]
|
|
822
831
|
|
|
823
832
|
if not visible:
|
|
833
|
+
if tab_task:
|
|
834
|
+
try: await tab_task
|
|
835
|
+
except: pass
|
|
824
836
|
await session.send("Search returned no visible results.")
|
|
825
837
|
return
|
|
826
838
|
|
|
827
|
-
# === Filter Mode: Screenshot matching links ===
|
|
839
|
+
# === Filter Mode: Screenshot matching links (NO tab needed) ===
|
|
828
840
|
if filters:
|
|
841
|
+
|
|
829
842
|
urls_to_screenshot = []
|
|
830
843
|
|
|
831
844
|
for filter_type, filter_value, count in filters:
|
|
@@ -881,20 +894,42 @@ async def handle_web_command(session: Session[MessageCreatedEvent], result: Arpa
|
|
|
881
894
|
await session.send("截图失败")
|
|
882
895
|
return
|
|
883
896
|
|
|
884
|
-
# === Normal Search Mode:
|
|
885
|
-
|
|
886
|
-
|
|
897
|
+
# === Normal Search Mode: Render search results as Sources card ===
|
|
898
|
+
|
|
899
|
+
# Build references from search results for Sources card
|
|
900
|
+
references = []
|
|
901
|
+
for i, res in enumerate(visible[:10]):
|
|
902
|
+
references.append({
|
|
903
|
+
"title": res.get("title", f"Result {i+1}"),
|
|
904
|
+
"url": res.get("url", ""),
|
|
905
|
+
"snippet": res.get("content", "") or res.get("snippet", ""),
|
|
906
|
+
"original_idx": i + 1,
|
|
907
|
+
})
|
|
908
|
+
|
|
909
|
+
try:
|
|
910
|
+
tab_id = await tab_task
|
|
911
|
+
except Exception:
|
|
912
|
+
tab_id = None
|
|
887
913
|
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
import urllib.parse
|
|
891
|
-
encoded_query = urllib.parse.quote_plus(search_query)
|
|
892
|
-
search_url = f"https://www.google.com/search?q={encoded_query}"
|
|
914
|
+
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as tf:
|
|
915
|
+
output_path = tf.name
|
|
893
916
|
|
|
894
|
-
|
|
917
|
+
# Render Sources card with search results (no markdown content, just references)
|
|
918
|
+
render_ok = await core.render(
|
|
919
|
+
markdown_content=f"# 搜索结果: {search_query}",
|
|
920
|
+
output_path=output_path,
|
|
921
|
+
stats={"total_time": 0},
|
|
922
|
+
references=references,
|
|
923
|
+
page_references=[],
|
|
924
|
+
stages_used=[{"name": "search", "description": f"搜索 \"{search_query}\"", "time": 0}],
|
|
925
|
+
tab_id=tab_id
|
|
926
|
+
)
|
|
895
927
|
|
|
896
|
-
if
|
|
897
|
-
|
|
928
|
+
if render_ok and os.path.exists(output_path):
|
|
929
|
+
with open(output_path, "rb") as f:
|
|
930
|
+
img_data = base64.b64encode(f.read()).decode()
|
|
931
|
+
|
|
932
|
+
msg_chain = MessageChain(Image(src=f'data:image/png;base64,{img_data}'))
|
|
898
933
|
if conf.quote:
|
|
899
934
|
msg_chain = MessageChain(Quote(session.event.message.id)) + msg_chain
|
|
900
935
|
|
|
@@ -909,8 +944,10 @@ async def handle_web_command(session: Session[MessageCreatedEvent], result: Arpa
|
|
|
909
944
|
mid = str(session.event.message.id) if getattr(session.event, "message", None) else str(session.event.id)
|
|
910
945
|
context_id = f"guild_{session.guild.id}" if session.guild else "user"
|
|
911
946
|
history_manager.remember(mid, [{"role": "user", "content": f"/w {query}"}], [], {}, context_id=context_id)
|
|
947
|
+
|
|
948
|
+
os.remove(output_path)
|
|
912
949
|
else:
|
|
913
|
-
await session.send(
|
|
950
|
+
await session.send("渲染搜索结果失败")
|
|
914
951
|
|
|
915
952
|
search_cache.cleanup() # Lazy cleanup
|
|
916
953
|
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
entari_plugin_hyw/Untitled-1,sha256=wbsr5i9iorqBMIYK4aAnpNTek3mXbhvyo2YOYw38pE4,30187
|
|
2
|
-
entari_plugin_hyw/__init__.py,sha256=
|
|
2
|
+
entari_plugin_hyw/__init__.py,sha256=QctcJLLU2B86EiiNZPS5HDK7vVwm2PpOmd5aL2Ge0J0,36757
|
|
3
3
|
entari_plugin_hyw/history.py,sha256=0XJwbfvXH5T1EPt4G1J5wWMJsKi0FfmajY5cvw8CQWE,12065
|
|
4
4
|
entari_plugin_hyw/misc.py,sha256=4ABzCHbEA87UCQfBX7AgAqACQwjQIhCSZuqHXPFGokg,5527
|
|
5
5
|
entari_plugin_hyw/search_cache.py,sha256=7MIhTm5_YnZjc0aBaX7AE4AJp0VT8eU6ObR6mTkoerc,4285
|
|
6
6
|
hyw_core/__init__.py,sha256=Jlr9Ic-BLOPTnff6OctUCdjDMdK4nssTF_vHie4QKTo,1958
|
|
7
7
|
hyw_core/config.py,sha256=DHxwToUVLm1nT88gG05e3hVzSLxXMk9BjgjAnhGCADk,4918
|
|
8
|
-
hyw_core/core.py,sha256=
|
|
8
|
+
hyw_core/core.py,sha256=TVtZd0ufppThNlqygpp84u7eNwcAs17SquTHqLTXM1g,10236
|
|
9
9
|
hyw_core/definitions.py,sha256=syYMNy3vdey7VuSlD3JUZ0gjlp5tmVkGHup-nimT0X0,3264
|
|
10
10
|
hyw_core/image_cache.py,sha256=t8pr1kgH2ngK9IhrBAhzUqhBWERNztUywMzgCFZEtQk,9899
|
|
11
11
|
hyw_core/pipeline.py,sha256=ZWwF0DHa29-65lUMU1_Fem3xQmxl7X_vgeni0ErOb8Q,22826
|
|
12
|
-
hyw_core/search.py,sha256=
|
|
13
|
-
hyw_core/browser_control/__init__.py,sha256=
|
|
12
|
+
hyw_core/search.py,sha256=L9LF3s4o4-ypDRyevvIlAqC0pa7xNYv-nESAql9N-pk,7345
|
|
13
|
+
hyw_core/browser_control/__init__.py,sha256=IeMErRC6fbq1PJWNK3klSbarSrUwOM4yyd_kJ6uWCPM,1406
|
|
14
14
|
hyw_core/browser_control/landing.html,sha256=wgqldumdylz69T83pvOkrigT1Mdb9GY0_KU0ceLGwdY,4642
|
|
15
|
-
hyw_core/browser_control/manager.py,sha256
|
|
16
|
-
hyw_core/browser_control/renderer.py,sha256=
|
|
17
|
-
hyw_core/browser_control/service.py,sha256=
|
|
15
|
+
hyw_core/browser_control/manager.py,sha256=-dHb0FamRsLfuU3jqX5cKaDo8DOOFV32zY912GuMdXU,6048
|
|
16
|
+
hyw_core/browser_control/renderer.py,sha256=s-QNIU-NMVQGLd_drLmeERgHsTm6C9XYm78CObt2KXc,17409
|
|
17
|
+
hyw_core/browser_control/service.py,sha256=L2_gwEqOXZJBZGJSgWfqEBNZoGNHaDhJSq9gl7NqIuQ,41009
|
|
18
18
|
hyw_core/browser_control/assets/index.html,sha256=BpbM0vD9OYicE5MBHSVLo3j_y-MpULI82PMqmBKpWT8,2328623
|
|
19
|
-
hyw_core/browser_control/assets/card-dist/index.html,sha256=
|
|
19
|
+
hyw_core/browser_control/assets/card-dist/index.html,sha256=Xw-hQ5ctdQkK-1jV8_gqMdgVGNZDwWZvIAqNrh2eK7g,2210054
|
|
20
20
|
hyw_core/browser_control/assets/card-dist/vite.svg,sha256=SnSK_UQ5GLsWWRyDTEAdrjPoeGGrXbrQgRw6O0qSFPs,1497
|
|
21
21
|
hyw_core/browser_control/assets/card-dist/logos/anthropic.svg,sha256=ASsy1ypo3osNc3n-B0R81tk_dIFsVgg7qQORrd5T2kA,558
|
|
22
22
|
hyw_core/browser_control/assets/card-dist/logos/cerebras.svg,sha256=bpmiiYTODwc06knTmPj3GQ7NNtosMog5lkggvB_Z-7M,44166
|
|
@@ -54,15 +54,17 @@ hyw_core/browser_control/assets/logos/qwen.png,sha256=eqLbnIPbjh2_PsODU_mmqjeD82
|
|
|
54
54
|
hyw_core/browser_control/assets/logos/xai.png,sha256=uSulvvDVqoA4RUOW0ZAkdvBVM2rpyGJRZIbn5dEFspw,362
|
|
55
55
|
hyw_core/browser_control/assets/logos/xiaomi.png,sha256=WHxlDFGU5FCjb-ure3ngdGG18-efYZUUfqA3_lqCUN0,4084
|
|
56
56
|
hyw_core/browser_control/assets/logos/zai.png,sha256=K-gnabdsjMLInppHA1Op7Nyt33iegrx1x-yNlvCZ0Tc,2351
|
|
57
|
-
hyw_core/browser_control/engines/__init__.py,sha256=
|
|
57
|
+
hyw_core/browser_control/engines/__init__.py,sha256=01-jOjvtQcqWIwwY56ql3j00oSHGE2XhDHjkIi1Ij3Q,284
|
|
58
58
|
hyw_core/browser_control/engines/base.py,sha256=q5y4SM1G6xS7-6TQ-nZz9iTWw3XonjJn01fWzoTxr6c,414
|
|
59
59
|
hyw_core/browser_control/engines/default.py,sha256=BlHCQI4-rN9cEzLLfqvRD4bvhyP2G2KUGlo92J4kFNw,6092
|
|
60
60
|
hyw_core/browser_control/engines/duckduckgo.py,sha256=QVYj1I6Fw6--2-f3DYdHVlOmeLPzet9qG4HUT7ynrSE,6789
|
|
61
|
-
hyw_core/
|
|
61
|
+
hyw_core/crawling/__init__.py,sha256=W5Be02uQueAyADFhPXVbDAFpNUJ_W7KdMtMr923_N24,437
|
|
62
|
+
hyw_core/crawling/completeness.py,sha256=OKdS8XlYYWDU1Vl1k-u7yEFqppukuJv-YQB0Px5KC2Q,16371
|
|
63
|
+
hyw_core/crawling/models.py,sha256=pCKe0k9xT3taSAlTlh0PazcLV0xYsm8p3XIkLHGf-LM,2353
|
|
62
64
|
hyw_core/stages/__init__.py,sha256=W89cWpq-HBLi2FprtJQSjQNLzpbhM8ZCkqPG61D_imE,521
|
|
63
65
|
hyw_core/stages/base.py,sha256=EfnTkISXbBNxjARykqIhmMrVqw2tqZl7ozJbJEbRnhI,2806
|
|
64
66
|
hyw_core/stages/summary.py,sha256=ODOwhIAmBZJuA4KOhUP7Lygch7XSkshrTZj-MdZjbEs,7085
|
|
65
|
-
entari_plugin_hyw-4.0.
|
|
66
|
-
entari_plugin_hyw-4.0.
|
|
67
|
-
entari_plugin_hyw-4.0.
|
|
68
|
-
entari_plugin_hyw-4.0.
|
|
67
|
+
entari_plugin_hyw-4.0.0rc11.dist-info/METADATA,sha256=2ljFQCOFDAcJDu-M_UnHxS2acIbUSPMXd57Yvyrj5S4,3845
|
|
68
|
+
entari_plugin_hyw-4.0.0rc11.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
69
|
+
entari_plugin_hyw-4.0.0rc11.dist-info/top_level.txt,sha256=ah76OrufRX0okOl4Fv8MO6PXiT0IaZ1oG0eDrdAPoNo,27
|
|
70
|
+
entari_plugin_hyw-4.0.0rc11.dist-info/RECORD,,
|
|
@@ -5,7 +5,7 @@ This subpackage provides:
|
|
|
5
5
|
- BrowserManager: Shared browser instance management
|
|
6
6
|
- PageService: Page fetching and screenshot capabilities
|
|
7
7
|
- RenderService: Vue-based card rendering
|
|
8
|
-
- Search engines:
|
|
8
|
+
- Search engines: DuckDuckGo adapter
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
from .manager import (
|
|
@@ -28,7 +28,6 @@ from .renderer import (
|
|
|
28
28
|
)
|
|
29
29
|
|
|
30
30
|
from .engines.base import SearchEngine
|
|
31
|
-
from .engines.google import GoogleEngine
|
|
32
31
|
from .engines.duckduckgo import DuckDuckGoEngine
|
|
33
32
|
from .engines.default import DefaultEngine
|
|
34
33
|
|
|
@@ -59,7 +58,6 @@ __all__ = [
|
|
|
59
58
|
|
|
60
59
|
# Search Engines
|
|
61
60
|
"SearchEngine",
|
|
62
|
-
"GoogleEngine",
|
|
63
61
|
"DuckDuckGoEngine",
|
|
64
62
|
"DefaultEngine",
|
|
65
63
|
]
|